From 8df3db566a3a937b45ebf11adb90d265e6f5e2d4 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 17 Nov 2019 20:45:02 +0100 Subject: initial checking of customized version 1.0rc9 --- plugins/dokuwiki/conf/.htaccess | 3 + plugins/dokuwiki/conf/acronyms.conf | 143 + plugins/dokuwiki/conf/dokuwiki.php | 132 + plugins/dokuwiki/conf/entities.conf | 21 + plugins/dokuwiki/conf/interwiki.conf | 121 + plugins/dokuwiki/conf/mime.conf | 41 + plugins/dokuwiki/conf/smileys.conf | 28 + plugins/dokuwiki/dokuwiki_constants.inc.php | 9 + plugins/dokuwiki/dokuwiki_formattext.inc.php | 155 + plugins/dokuwiki/img/divider.gif | Bin 0 -> 56 bytes plugins/dokuwiki/img/email.png | Bin 0 -> 1333 bytes plugins/dokuwiki/img/format-text-bold.png | Bin 0 -> 939 bytes plugins/dokuwiki/img/format-text-italic.png | Bin 0 -> 784 bytes plugins/dokuwiki/img/format-text-strikethrough.png | Bin 0 -> 797 bytes plugins/dokuwiki/img/format-text-underline.png | Bin 0 -> 869 bytes plugins/dokuwiki/img/h1.gif | Bin 0 -> 696 bytes plugins/dokuwiki/img/h2.gif | Bin 0 -> 699 bytes plugins/dokuwiki/img/h3.gif | Bin 0 -> 700 bytes plugins/dokuwiki/img/hr.gif | Bin 0 -> 664 bytes plugins/dokuwiki/img/image-x-generic.png | Bin 0 -> 900 bytes plugins/dokuwiki/img/img.gif | Bin 0 -> 370 bytes plugins/dokuwiki/img/network.png | Bin 0 -> 1779 bytes plugins/dokuwiki/img/ol.gif | Bin 0 -> 677 bytes plugins/dokuwiki/img/source.png | Bin 0 -> 1443 bytes plugins/dokuwiki/img/source_php.png | Bin 0 -> 1376 bytes plugins/dokuwiki/img/text-html.png | Bin 0 -> 1097 bytes plugins/dokuwiki/img/ul.gif | Bin 0 -> 668 bytes plugins/dokuwiki/inc/HTTPClient.php | 436 ++ plugins/dokuwiki/inc/JpegMeta.php | 2982 ++++++++++++ plugins/dokuwiki/inc/cache.php | 291 ++ plugins/dokuwiki/inc/common.php | 1009 +++++ plugins/dokuwiki/inc/confutils.php | 189 + plugins/dokuwiki/inc/events.php | 202 + plugins/dokuwiki/inc/geshi.php | 4775 ++++++++++++++++++++ plugins/dokuwiki/inc/geshi/actionscript-french.php | 957 ++++ plugins/dokuwiki/inc/geshi/actionscript.php | 199 + plugins/dokuwiki/inc/geshi/ada.php | 135 + plugins/dokuwiki/inc/geshi/apache.php | 173 + plugins/dokuwiki/inc/geshi/applescript.php | 136 + plugins/dokuwiki/inc/geshi/asm.php | 200 + plugins/dokuwiki/inc/geshi/asp.php | 155 + plugins/dokuwiki/inc/geshi/autoit.php | 196 + plugins/dokuwiki/inc/geshi/bash.php | 137 + plugins/dokuwiki/inc/geshi/c.php | 144 + plugins/dokuwiki/inc/geshi/c_mac.php | 176 + plugins/dokuwiki/inc/geshi/caddcl.php | 127 + plugins/dokuwiki/inc/geshi/cadlisp.php | 187 + plugins/dokuwiki/inc/geshi/cpp.php | 172 + plugins/dokuwiki/inc/geshi/csharp.php | 233 + plugins/dokuwiki/inc/geshi/css.php | 178 + plugins/dokuwiki/inc/geshi/d.php | 287 ++ plugins/dokuwiki/inc/geshi/delphi.php | 272 ++ plugins/dokuwiki/inc/geshi/diff.php | 186 + plugins/dokuwiki/inc/geshi/div.php | 128 + plugins/dokuwiki/inc/geshi/dos.php | 185 + plugins/dokuwiki/inc/geshi/eiffel.php | 397 ++ plugins/dokuwiki/inc/geshi/freebasic.php | 137 + plugins/dokuwiki/inc/geshi/gml.php | 504 +++ plugins/dokuwiki/inc/geshi/html4strict.php | 256 ++ plugins/dokuwiki/inc/geshi/html5.php | 210 + plugins/dokuwiki/inc/geshi/ini.php | 125 + plugins/dokuwiki/inc/geshi/inno.php | 215 + plugins/dokuwiki/inc/geshi/java.php | 1390 ++++++ plugins/dokuwiki/inc/geshi/javascript.php | 146 + plugins/dokuwiki/inc/geshi/lisp.php | 135 + plugins/dokuwiki/inc/geshi/lua.php | 137 + plugins/dokuwiki/inc/geshi/matlab.php | 869 ++++ plugins/dokuwiki/inc/geshi/mpasm.php | 160 + plugins/dokuwiki/inc/geshi/nsis.php | 354 ++ plugins/dokuwiki/inc/geshi/objc.php | 241 + plugins/dokuwiki/inc/geshi/ocaml-brief.php | 114 + plugins/dokuwiki/inc/geshi/ocaml.php | 163 + plugins/dokuwiki/inc/geshi/oobas.php | 132 + plugins/dokuwiki/inc/geshi/oracle8.php | 489 ++ plugins/dokuwiki/inc/geshi/pascal.php | 145 + plugins/dokuwiki/inc/geshi/perl.php | 169 + plugins/dokuwiki/inc/geshi/php-brief.php | 162 + plugins/dokuwiki/inc/geshi/php.php | 356 ++ plugins/dokuwiki/inc/geshi/python.php | 229 + plugins/dokuwiki/inc/geshi/qbasic.php | 147 + plugins/dokuwiki/inc/geshi/ruby.php | 149 + plugins/dokuwiki/inc/geshi/scheme.php | 172 + plugins/dokuwiki/inc/geshi/sdlbasic.php | 163 + plugins/dokuwiki/inc/geshi/smarty.php | 168 + plugins/dokuwiki/inc/geshi/sql.php | 137 + plugins/dokuwiki/inc/geshi/vb.php | 150 + plugins/dokuwiki/inc/geshi/vbnet.php | 199 + plugins/dokuwiki/inc/geshi/vhdl.php | 140 + plugins/dokuwiki/inc/geshi/visualfoxpro.php | 444 ++ plugins/dokuwiki/inc/geshi/xml.php | 147 + plugins/dokuwiki/inc/html.php | 1290 ++++++ plugins/dokuwiki/inc/infoutils.php | 249 + plugins/dokuwiki/inc/init.php | 367 ++ plugins/dokuwiki/inc/io.php | 567 +++ plugins/dokuwiki/inc/pageutils.php | 478 ++ plugins/dokuwiki/inc/parser/handler.php | 1653 +++++++ plugins/dokuwiki/inc/parser/lexer.php | 607 +++ plugins/dokuwiki/inc/parser/parser.php | 932 ++++ plugins/dokuwiki/inc/parser/renderer.php | 212 + plugins/dokuwiki/inc/parser/xhtml.php | 1097 +++++ plugins/dokuwiki/inc/parserutils.php | 524 +++ plugins/dokuwiki/inc/pluginutils.php | 95 + plugins/dokuwiki/inc/utf8.php | 1276 ++++++ plugins/dokuwiki/lib/exe/fetch.php | 433 ++ plugins/dokuwiki/lib/images/fileicons/bz2.png | Bin 0 -> 720 bytes plugins/dokuwiki/lib/images/fileicons/conf.png | Bin 0 -> 717 bytes plugins/dokuwiki/lib/images/fileicons/deb.png | Bin 0 -> 716 bytes plugins/dokuwiki/lib/images/fileicons/doc.png | Bin 0 -> 659 bytes plugins/dokuwiki/lib/images/fileicons/file.gif | Bin 0 -> 942 bytes plugins/dokuwiki/lib/images/fileicons/file.png | Bin 0 -> 720 bytes plugins/dokuwiki/lib/images/fileicons/gif.png | Bin 0 -> 1001 bytes plugins/dokuwiki/lib/images/fileicons/gz.png | Bin 0 -> 716 bytes plugins/dokuwiki/lib/images/fileicons/htm.png | Bin 0 -> 748 bytes plugins/dokuwiki/lib/images/fileicons/html.png | Bin 0 -> 748 bytes plugins/dokuwiki/lib/images/fileicons/index.php | 49 + plugins/dokuwiki/lib/images/fileicons/jpeg.png | Bin 0 -> 1001 bytes plugins/dokuwiki/lib/images/fileicons/jpg.png | Bin 0 -> 1001 bytes plugins/dokuwiki/lib/images/fileicons/odc.png | Bin 0 -> 749 bytes plugins/dokuwiki/lib/images/fileicons/odf.png | Bin 0 -> 807 bytes plugins/dokuwiki/lib/images/fileicons/odg.png | Bin 0 -> 788 bytes plugins/dokuwiki/lib/images/fileicons/odi.png | Bin 0 -> 788 bytes plugins/dokuwiki/lib/images/fileicons/odp.png | Bin 0 -> 744 bytes plugins/dokuwiki/lib/images/fileicons/ods.png | Bin 0 -> 749 bytes plugins/dokuwiki/lib/images/fileicons/odt.png | Bin 0 -> 577 bytes plugins/dokuwiki/lib/images/fileicons/pdf.png | Bin 0 -> 663 bytes plugins/dokuwiki/lib/images/fileicons/png.png | Bin 0 -> 1001 bytes plugins/dokuwiki/lib/images/fileicons/ppt.png | Bin 0 -> 762 bytes plugins/dokuwiki/lib/images/fileicons/ps.png | Bin 0 -> 534 bytes plugins/dokuwiki/lib/images/fileicons/rpm.png | Bin 0 -> 638 bytes plugins/dokuwiki/lib/images/fileicons/rtf.png | Bin 0 -> 474 bytes plugins/dokuwiki/lib/images/fileicons/swf.png | Bin 0 -> 843 bytes plugins/dokuwiki/lib/images/fileicons/sxc.png | Bin 0 -> 749 bytes plugins/dokuwiki/lib/images/fileicons/sxd.png | Bin 0 -> 788 bytes plugins/dokuwiki/lib/images/fileicons/sxi.png | Bin 0 -> 744 bytes plugins/dokuwiki/lib/images/fileicons/sxw.png | Bin 0 -> 577 bytes plugins/dokuwiki/lib/images/fileicons/tar.png | Bin 0 -> 747 bytes plugins/dokuwiki/lib/images/fileicons/tgz.png | Bin 0 -> 716 bytes plugins/dokuwiki/lib/images/fileicons/txt.png | Bin 0 -> 542 bytes plugins/dokuwiki/lib/images/fileicons/xls.png | Bin 0 -> 731 bytes plugins/dokuwiki/lib/images/fileicons/xml.png | Bin 0 -> 475 bytes plugins/dokuwiki/lib/images/fileicons/zip.png | Bin 0 -> 874 bytes .../dokuwiki/lib/images/interwiki/amazon.de.gif | Bin 0 -> 882 bytes plugins/dokuwiki/lib/images/interwiki/amazon.gif | Bin 0 -> 882 bytes .../dokuwiki/lib/images/interwiki/amazon.uk.gif | Bin 0 -> 882 bytes plugins/dokuwiki/lib/images/interwiki/bug.gif | Bin 0 -> 166 bytes plugins/dokuwiki/lib/images/interwiki/coral.gif | Bin 0 -> 85 bytes plugins/dokuwiki/lib/images/interwiki/doku.gif | Bin 0 -> 257 bytes plugins/dokuwiki/lib/images/interwiki/google.gif | Bin 0 -> 980 bytes plugins/dokuwiki/lib/images/interwiki/meatball.gif | Bin 0 -> 1100 bytes plugins/dokuwiki/lib/images/interwiki/phpfn.gif | Bin 0 -> 330 bytes plugins/dokuwiki/lib/images/interwiki/sb.gif | Bin 0 -> 886 bytes plugins/dokuwiki/lib/images/interwiki/wiki.gif | Bin 0 -> 909 bytes plugins/dokuwiki/lib/images/interwiki/wp.gif | Bin 0 -> 680 bytes plugins/dokuwiki/lib/images/interwiki/wpde.gif | Bin 0 -> 680 bytes plugins/dokuwiki/lib/images/interwiki/wpmeta.gif | Bin 0 -> 680 bytes plugins/dokuwiki/lib/images/smileys/delete.gif | Bin 0 -> 1421 bytes plugins/dokuwiki/lib/images/smileys/fixme.gif | Bin 0 -> 1435 bytes plugins/dokuwiki/lib/images/smileys/icon_arrow.gif | Bin 0 -> 170 bytes .../dokuwiki/lib/images/smileys/icon_biggrin.gif | Bin 0 -> 172 bytes .../dokuwiki/lib/images/smileys/icon_confused.gif | Bin 0 -> 171 bytes plugins/dokuwiki/lib/images/smileys/icon_cool.gif | Bin 0 -> 172 bytes plugins/dokuwiki/lib/images/smileys/icon_cry.gif | Bin 0 -> 498 bytes plugins/dokuwiki/lib/images/smileys/icon_doubt.gif | Bin 0 -> 990 bytes .../dokuwiki/lib/images/smileys/icon_doubt2.gif | Bin 0 -> 992 bytes plugins/dokuwiki/lib/images/smileys/icon_eek.gif | Bin 0 -> 170 bytes plugins/dokuwiki/lib/images/smileys/icon_evil.gif | Bin 0 -> 236 bytes .../dokuwiki/lib/images/smileys/icon_exclaim.gif | Bin 0 -> 236 bytes plugins/dokuwiki/lib/images/smileys/icon_frown.gif | Bin 0 -> 171 bytes plugins/dokuwiki/lib/images/smileys/icon_fun.gif | Bin 0 -> 590 bytes plugins/dokuwiki/lib/images/smileys/icon_idea.gif | Bin 0 -> 176 bytes plugins/dokuwiki/lib/images/smileys/icon_kaddi.gif | Bin 0 -> 991 bytes plugins/dokuwiki/lib/images/smileys/icon_lol.gif | Bin 0 -> 336 bytes .../dokuwiki/lib/images/smileys/icon_mrgreen.gif | Bin 0 -> 349 bytes .../dokuwiki/lib/images/smileys/icon_neutral.gif | Bin 0 -> 171 bytes .../dokuwiki/lib/images/smileys/icon_question.gif | Bin 0 -> 248 bytes plugins/dokuwiki/lib/images/smileys/icon_razz.gif | Bin 0 -> 176 bytes .../dokuwiki/lib/images/smileys/icon_redface.gif | Bin 0 -> 650 bytes .../dokuwiki/lib/images/smileys/icon_rolleyes.gif | Bin 0 -> 485 bytes plugins/dokuwiki/lib/images/smileys/icon_sad.gif | Bin 0 -> 171 bytes .../dokuwiki/lib/images/smileys/icon_silenced.gif | Bin 0 -> 231 bytes plugins/dokuwiki/lib/images/smileys/icon_smile.gif | Bin 0 -> 174 bytes .../dokuwiki/lib/images/smileys/icon_smile2.gif | Bin 0 -> 174 bytes .../dokuwiki/lib/images/smileys/icon_surprised.gif | Bin 0 -> 174 bytes .../dokuwiki/lib/images/smileys/icon_twisted.gif | Bin 0 -> 238 bytes plugins/dokuwiki/lib/images/smileys/icon_wink.gif | Bin 0 -> 170 bytes .../dokuwiki/lib/plugins/changelinks/syntax.php | 157 + plugins/dokuwiki/lib/plugins/fslink/syntax.php | 81 + plugins/dokuwiki/lib/plugins/newline/syntax.php | 77 + plugins/dokuwiki/lib/plugins/syntax.php | 270 ++ 189 files changed, 34765 insertions(+) create mode 100644 plugins/dokuwiki/conf/.htaccess create mode 100644 plugins/dokuwiki/conf/acronyms.conf create mode 100644 plugins/dokuwiki/conf/dokuwiki.php create mode 100644 plugins/dokuwiki/conf/entities.conf create mode 100644 plugins/dokuwiki/conf/interwiki.conf create mode 100644 plugins/dokuwiki/conf/mime.conf create mode 100644 plugins/dokuwiki/conf/smileys.conf create mode 100644 plugins/dokuwiki/dokuwiki_constants.inc.php create mode 100644 plugins/dokuwiki/dokuwiki_formattext.inc.php create mode 100644 plugins/dokuwiki/img/divider.gif create mode 100644 plugins/dokuwiki/img/email.png create mode 100644 plugins/dokuwiki/img/format-text-bold.png create mode 100644 plugins/dokuwiki/img/format-text-italic.png create mode 100644 plugins/dokuwiki/img/format-text-strikethrough.png create mode 100644 plugins/dokuwiki/img/format-text-underline.png create mode 100644 plugins/dokuwiki/img/h1.gif create mode 100644 plugins/dokuwiki/img/h2.gif create mode 100644 plugins/dokuwiki/img/h3.gif create mode 100644 plugins/dokuwiki/img/hr.gif create mode 100644 plugins/dokuwiki/img/image-x-generic.png create mode 100644 plugins/dokuwiki/img/img.gif create mode 100644 plugins/dokuwiki/img/network.png create mode 100644 plugins/dokuwiki/img/ol.gif create mode 100644 plugins/dokuwiki/img/source.png create mode 100644 plugins/dokuwiki/img/source_php.png create mode 100644 plugins/dokuwiki/img/text-html.png create mode 100644 plugins/dokuwiki/img/ul.gif create mode 100644 plugins/dokuwiki/inc/HTTPClient.php create mode 100644 plugins/dokuwiki/inc/JpegMeta.php create mode 100644 plugins/dokuwiki/inc/cache.php create mode 100644 plugins/dokuwiki/inc/common.php create mode 100644 plugins/dokuwiki/inc/confutils.php create mode 100644 plugins/dokuwiki/inc/events.php create mode 100644 plugins/dokuwiki/inc/geshi.php create mode 100644 plugins/dokuwiki/inc/geshi/actionscript-french.php create mode 100644 plugins/dokuwiki/inc/geshi/actionscript.php create mode 100644 plugins/dokuwiki/inc/geshi/ada.php create mode 100644 plugins/dokuwiki/inc/geshi/apache.php create mode 100644 plugins/dokuwiki/inc/geshi/applescript.php create mode 100644 plugins/dokuwiki/inc/geshi/asm.php create mode 100644 plugins/dokuwiki/inc/geshi/asp.php create mode 100644 plugins/dokuwiki/inc/geshi/autoit.php create mode 100644 plugins/dokuwiki/inc/geshi/bash.php create mode 100644 plugins/dokuwiki/inc/geshi/c.php create mode 100644 plugins/dokuwiki/inc/geshi/c_mac.php create mode 100644 plugins/dokuwiki/inc/geshi/caddcl.php create mode 100644 plugins/dokuwiki/inc/geshi/cadlisp.php create mode 100644 plugins/dokuwiki/inc/geshi/cpp.php create mode 100644 plugins/dokuwiki/inc/geshi/csharp.php create mode 100644 plugins/dokuwiki/inc/geshi/css.php create mode 100644 plugins/dokuwiki/inc/geshi/d.php create mode 100644 plugins/dokuwiki/inc/geshi/delphi.php create mode 100644 plugins/dokuwiki/inc/geshi/diff.php create mode 100644 plugins/dokuwiki/inc/geshi/div.php create mode 100644 plugins/dokuwiki/inc/geshi/dos.php create mode 100644 plugins/dokuwiki/inc/geshi/eiffel.php create mode 100644 plugins/dokuwiki/inc/geshi/freebasic.php create mode 100644 plugins/dokuwiki/inc/geshi/gml.php create mode 100644 plugins/dokuwiki/inc/geshi/html4strict.php create mode 100644 plugins/dokuwiki/inc/geshi/html5.php create mode 100644 plugins/dokuwiki/inc/geshi/ini.php create mode 100644 plugins/dokuwiki/inc/geshi/inno.php create mode 100644 plugins/dokuwiki/inc/geshi/java.php create mode 100644 plugins/dokuwiki/inc/geshi/javascript.php create mode 100644 plugins/dokuwiki/inc/geshi/lisp.php create mode 100644 plugins/dokuwiki/inc/geshi/lua.php create mode 100644 plugins/dokuwiki/inc/geshi/matlab.php create mode 100644 plugins/dokuwiki/inc/geshi/mpasm.php create mode 100644 plugins/dokuwiki/inc/geshi/nsis.php create mode 100644 plugins/dokuwiki/inc/geshi/objc.php create mode 100644 plugins/dokuwiki/inc/geshi/ocaml-brief.php create mode 100644 plugins/dokuwiki/inc/geshi/ocaml.php create mode 100644 plugins/dokuwiki/inc/geshi/oobas.php create mode 100644 plugins/dokuwiki/inc/geshi/oracle8.php create mode 100644 plugins/dokuwiki/inc/geshi/pascal.php create mode 100644 plugins/dokuwiki/inc/geshi/perl.php create mode 100644 plugins/dokuwiki/inc/geshi/php-brief.php create mode 100644 plugins/dokuwiki/inc/geshi/php.php create mode 100644 plugins/dokuwiki/inc/geshi/python.php create mode 100644 plugins/dokuwiki/inc/geshi/qbasic.php create mode 100644 plugins/dokuwiki/inc/geshi/ruby.php create mode 100644 plugins/dokuwiki/inc/geshi/scheme.php create mode 100644 plugins/dokuwiki/inc/geshi/sdlbasic.php create mode 100644 plugins/dokuwiki/inc/geshi/smarty.php create mode 100644 plugins/dokuwiki/inc/geshi/sql.php create mode 100644 plugins/dokuwiki/inc/geshi/vb.php create mode 100644 plugins/dokuwiki/inc/geshi/vbnet.php create mode 100644 plugins/dokuwiki/inc/geshi/vhdl.php create mode 100644 plugins/dokuwiki/inc/geshi/visualfoxpro.php create mode 100644 plugins/dokuwiki/inc/geshi/xml.php create mode 100644 plugins/dokuwiki/inc/html.php create mode 100644 plugins/dokuwiki/inc/infoutils.php create mode 100644 plugins/dokuwiki/inc/init.php create mode 100644 plugins/dokuwiki/inc/io.php create mode 100644 plugins/dokuwiki/inc/pageutils.php create mode 100644 plugins/dokuwiki/inc/parser/handler.php create mode 100644 plugins/dokuwiki/inc/parser/lexer.php create mode 100644 plugins/dokuwiki/inc/parser/parser.php create mode 100644 plugins/dokuwiki/inc/parser/renderer.php create mode 100644 plugins/dokuwiki/inc/parser/xhtml.php create mode 100644 plugins/dokuwiki/inc/parserutils.php create mode 100644 plugins/dokuwiki/inc/pluginutils.php create mode 100644 plugins/dokuwiki/inc/utf8.php create mode 100644 plugins/dokuwiki/lib/exe/fetch.php create mode 100644 plugins/dokuwiki/lib/images/fileicons/bz2.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/conf.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/deb.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/doc.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/file.gif create mode 100644 plugins/dokuwiki/lib/images/fileicons/file.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/gif.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/gz.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/htm.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/html.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/index.php create mode 100644 plugins/dokuwiki/lib/images/fileicons/jpeg.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/jpg.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/odc.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/odf.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/odg.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/odi.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/odp.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/ods.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/odt.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/pdf.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/png.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/ppt.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/ps.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/rpm.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/rtf.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/swf.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/sxc.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/sxd.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/sxi.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/sxw.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/tar.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/tgz.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/txt.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/xls.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/xml.png create mode 100644 plugins/dokuwiki/lib/images/fileicons/zip.png create mode 100644 plugins/dokuwiki/lib/images/interwiki/amazon.de.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/amazon.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/amazon.uk.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/bug.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/coral.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/doku.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/google.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/meatball.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/phpfn.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/sb.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/wiki.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/wp.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/wpde.gif create mode 100644 plugins/dokuwiki/lib/images/interwiki/wpmeta.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/delete.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/fixme.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_arrow.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_biggrin.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_confused.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_cool.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_cry.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_doubt.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_doubt2.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_eek.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_evil.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_exclaim.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_frown.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_fun.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_idea.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_kaddi.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_lol.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_mrgreen.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_neutral.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_question.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_razz.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_redface.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_rolleyes.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_sad.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_silenced.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_smile.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_smile2.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_surprised.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_twisted.gif create mode 100644 plugins/dokuwiki/lib/images/smileys/icon_wink.gif create mode 100644 plugins/dokuwiki/lib/plugins/changelinks/syntax.php create mode 100644 plugins/dokuwiki/lib/plugins/fslink/syntax.php create mode 100644 plugins/dokuwiki/lib/plugins/newline/syntax.php create mode 100644 plugins/dokuwiki/lib/plugins/syntax.php (limited to 'plugins/dokuwiki') diff --git a/plugins/dokuwiki/conf/.htaccess b/plugins/dokuwiki/conf/.htaccess new file mode 100644 index 0000000..bcc3ea0 --- /dev/null +++ b/plugins/dokuwiki/conf/.htaccess @@ -0,0 +1,3 @@ +## no access to the conf directory +order allow,deny +deny from all diff --git a/plugins/dokuwiki/conf/acronyms.conf b/plugins/dokuwiki/conf/acronyms.conf new file mode 100644 index 0000000..2cfedea --- /dev/null +++ b/plugins/dokuwiki/conf/acronyms.conf @@ -0,0 +1,143 @@ +# Acronyms. + +ACL Access Control List +AFAICS As far as I can see +AFAIK As far as I know +AJAX Asynchronous JavaScript and XML +AIM AOL (America Online) Instant Messenger +AOL America Online +API Application Programming Interface +ASAP As soon as possible +ASCII American Standard Code for Information Interchange +ASP Active Server Pages +BTW By the way +CGI Common Gateway Interface +CMS Content Management System +CSS Cascading Style Sheets +CVS Concurrent Versions System +DBA Database Administrator +DHTML Dynamic HyperText Markup Language +DMCA Digital Millenium Copyright Act +DNS Domain Name Server +DOM Document Object Model +DTD Document Type Definition +EOF End of file +EOL End of line +EOM End of message +EOT End of text +ESMTP Extended Simple Mail Transfer Protocol +FAQ Frequently Asked Questions +FDL GNU Free Documentation License +FTP File Transfer Protocol +FOSS Free & Open-Source Software +FLOSS Free/Libre and Open Source Software +FUD Fear, Uncertainty, and Doubt +GB Gigabyte +GHz Gigahertz +GIF Graphics Interchange Format +GPL GNU General Public License +GUI Graphical User Interface +HTML HyperText Markup Language +HTTP Hyper Text Transfer Protocol +HTTPS Hypertext Transfer Protocol Secure +IANAL I am not a lawyer (but) +ICANN Internet Corporation for Assigned Names and Numbers +ICQ I seek you (Instant Messenger) +IE5 Internet Explorer 5 +IE6 Internet Explorer 6 +IE Internet Explorer +IIRC If I remember correctly +IIS Internet Information Services +IMAP Internet Message Access Protocol +IMHO In my humble opinion +IMO In my opinion +IOW In other words +IRC Internet Relay Chat +IRL In real life +ISO International Organization for Standardization +ISP Internet Service Provider +JDK Java Development Kit +JPEG Joint Photographics Experts Group +JPG Joint Photographics Experts Group +JS JavaScript +KISS Keep it simple stupid +LGPL GNU Lesser General Public License +LOL Laughing out loud +MathML Mathematical Markup Language +MB Megabyte +MHz Megahertz +MIME Multipurpose Internet Mail Extension +MIT Massachusetts Institute of Technology +MML Mathematical Markup Language +MP3 Motion Picture Experts Group Layer 3 +MPEG Motion Picture Experts Group +MSDN Microsoft Developer Network +MS Microsoft +MSIE Microsoft Internet Explorer +NS4.7 Netscape 4.7 +NS4 Netscape 4 +NS6 Netscape 6 +NS7 Netscape 7 +OMG Oh my God +OPML Outline Processor Markup Language +OS Operating System +OSS Open Source Software +OTOH On the other hand +P2P Peer to Peer +PDA Personal Digital Assistant +PDF Portable Document Format +Perl Practical Extraction and Report Language +PERL Practical Extraction and Report Language +PHP Hypertext Preprocessor +PICS Platform for Internet Content Selection +PIN Personal Identification Number +PITA Pain in the Ass +PNG Portable Network Graphics +POP3 Post Office Protocol 3 +POP Post Office Protocol +QoS Quality of Service +RAID Redundant Array of Inexpensive Disks +RFC Request for Comments (Internet Standards) +RDF Resource Description Framework +ROTFL Rolling on the floor laughing +RPC Remote Procedure Call +RSS Rich Site Summary +RTFM Read The Fine Manual +RTF Rich Text File +SCSI Small Computer System Interface +SDK Software Development Kit +SGML Standard General Markup Language +SMIL Synchronized Multimedia Integration Language +SMTP Simple Mail Transfer Protocol +SOAP Simple Object Access Protocol +spec specification +SQL Structured Query Language +SSH Secure Shell +SSI Server Side Includes +SSL Secure Sockets Layer +SVG Scalable Vector Graphics +TIA Thanks in advance +TIFF Tagged Image File Format +TLD Top Level Domain +TLS Transport Layer Security +TOC Table of Contents +URI Uniform Resource Identifier +URL Uniform Resource Locator +URN Uniform Resource Name +VBA Visual Basic for Applications +VB Visual Basic +W3C World Wide Web Consortium +WAN Wide Area Network +WAP Wireless Access Protocol +WML Wireless Markup Language +WTF? What the f*** +WWW World Wide Web +WYSIWYG What You See Is What You Get +XHTML Extensible HyperText Markup Language +XML Extensible Markup Language +XMPP Extensible Messaging and Presence Protocol +XSD XML (Extensible Markup Language) Schema Definition +XSL Extensible Stylesheet Language +XSLT Extensible Stylesheet Language Transformations +XUL XML User Interface Language +YMMV Your mileage may vary diff --git a/plugins/dokuwiki/conf/dokuwiki.php b/plugins/dokuwiki/conf/dokuwiki.php new file mode 100644 index 0000000..21dd285 --- /dev/null +++ b/plugins/dokuwiki/conf/dokuwiki.php @@ -0,0 +1,132 @@ += 4.3.0 and aspell installed) +$conf['subscribers'] = 0; //enable change notice subscription support +$conf['compress'] = 1; //Strip whitespaces and comments from Styles and JavaScript? 1|0 +$conf['hidepages'] = ''; //Regexp for pages to be skipped from RSS, Search and Recent Changes +$conf['send404'] = 0; //Send a HTTP 404 status for non existing pages? +$conf['sitemap'] = 0; //Create a google sitemap? How often? In days. +$conf['rss_type'] = 'rss1'; //type of RSS feed to provide, by default: + // 'rss' - RSS 0.91 + // 'rss1' - RSS 1.0 + // 'rss2' - RSS 2.0 + // 'atom' - Atom 0.3 +$conf['rss_linkto'] = 'diff'; //what page RSS entries link to: + // 'diff' - page showing revision differences + // 'page' - the revised page itself + // 'rev' - page showing all revisions + // 'current' - most recent revision of page +$conf['rss_update'] = 5*60; //Update the RSS feed every n minutes (defaults to 5 minutes) +$conf['recent_days'] = 7; //How many days of recent changes to keep. (days) + +//Set target to use when creating links - leave empty for same window +$conf['target']['wiki'] = ''; +$conf['target']['interwiki'] = ''; +$conf['target']['extern'] = ''; +$conf['target']['media'] = ''; +$conf['target']['windows'] = ''; + +//Proxy setup - if your Server needs a proxy to access the web set these +$conf['proxy']['host'] = ''; +$conf['proxy']['port'] = ''; +$conf['proxy']['user'] = ''; +$conf['proxy']['pass'] = ''; +$conf['proxy']['ssl'] = 0; + +/* Safemode Hack */ + +$conf['safemodehack'] = 0; //read http://wiki.splitbrain.org/wiki:safemodehack ! +$conf['ftp']['host'] = 'localhost'; +$conf['ftp']['port'] = '21'; +$conf['ftp']['user'] = 'user'; +$conf['ftp']['pass'] = 'password'; +$conf['ftp']['root'] = '/home/user/htdocs'; + diff --git a/plugins/dokuwiki/conf/entities.conf b/plugins/dokuwiki/conf/entities.conf new file mode 100644 index 0000000..888224d --- /dev/null +++ b/plugins/dokuwiki/conf/entities.conf @@ -0,0 +1,21 @@ +# Typography replacements +# +# Order does matter! +# +# Do not use HTML entities here because it may break non-HTML renderers (XML Atomfeed for instance). +# Use UTF-8 chars directly instead. + +<-> ↔ +-> → +<- ← +<=> ⇔ +=> ⇒ +<= ⇐ +>> » +<< « +--- — +-- – +(c) © +(tm) ™ +(r) ® +... … diff --git a/plugins/dokuwiki/conf/interwiki.conf b/plugins/dokuwiki/conf/interwiki.conf new file mode 100644 index 0000000..4ba2f9e --- /dev/null +++ b/plugins/dokuwiki/conf/interwiki.conf @@ -0,0 +1,121 @@ +# Each URL may contain one of the placeholders {URL} or {NAME} +# {URL} is replaced by the URL encoded representation of the wikiname +# this is the right thing to do in most cases +# {NAME} this is replaced by the wikiname as given in the document +# no further encoding is done +# If no placeholder is defined the urlencoded name is appended to the URL + +# You can add more InterWiki shortcuts here. + +wp http://en.wikipedia.org/wiki/ +wpde http://de.wikipedia.org/wiki/ +wpmeta http://meta.wikipedia.org/wiki/ +doku http://wiki.splitbrain.org/ +rfc https://tools.ietf.org/html/rfc +sb http://www.splitbrain.org/go/ +amazon http://www.amazon.com/exec/obidos/ASIN/ +amazon.de http://www.amazon.de/exec/obidos/ASIN/ +amazon.uk http://www.amazon.co.uk/exec/obidos/ASIN/ +google.de http://www.google.de/search?q= +man http://man.cx/ +phpfn http://www.php.net/{NAME} +go http://www.google.com/search?q={URL}&btnI=lucky +bug http://bugs.splitbrain.org/index.php?do=details&id= +coral http://{HOST}.{PORT}.nyud.net:8090/{PATH}?{QUERY} +xref http://dev.splitbrain.org/reference/dokuwiki/{NAME}.html + +# Standards from http://usemod.com/intermap.txt follow + +AbbeNormal http://www.ourpla.net/cgi-bin/pikie.cgi? +AcadWiki http://xarch.tu-graz.ac.at/autocad/wiki/ +Acronym http://www.acronymfinder.com/af-query.asp?String=exact&Acronym= +Advogato http://www.advogato.org/ +AIWiki http://www.ifi.unizh.ch/ailab/aiwiki/aiw.cgi? +ALife http://news.alife.org/wiki/index.php? +AndStuff http://andstuff.org/wiki.php? +Annotation http://bayle.stanford.edu/crit/nph-med.cgi/ +AnnotationWiki http://www.seedwiki.com/page.cfm?wikiid=368&doc= +AwarenessWiki http://taoriver.net/aware/ +BenefitsWiki http://www.benefitslink.com/cgi-bin/wiki.cgi? +BridgesWiki http://c2.com/w2/bridges/ +C2find http://c2.com/cgi/wiki?FindPage&value= +Cache http://www.google.com/search?q=cache: +CLiki http://ww.telent.net/cliki/ +CmWiki http://www.ourpla.net/cgi-bin/wiki.pl? +CreationMatters http://www.ourpla.net/cgi-bin/wiki.pl? +DejaNews http://www.deja.com/=dnc/getdoc.xp?AN= +DeWikiPedia http://www.wikipedia.de/wiki.cgi? +Dictionary http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query= +DiveIntoOsx http://diveintoosx.org/ +DocBook http://docbook.org/wiki/moin.cgi/ +DolphinWiki http://www.object-arts.com/wiki/html/Dolphin/ +EfnetCeeWiki http://purl.net/wiki/c/ +EfnetCppWiki http://purl.net/wiki/cpp/ +EfnetPythonWiki http://purl.net/wiki/python/ +EfnetXmlWiki http://purl.net/wiki/xml/ +EljWiki http://elj.sourceforge.net/phpwiki/index.php/ +EmacsWiki http://www.emacswiki.org/cgi-bin/wiki.pl? +FinalEmpire http://final-empire.sourceforge.net/cgi-bin/wiki.pl? +Foldoc http://www.foldoc.org/foldoc/foldoc.cgi? +FoxWiki http://fox.wikis.com/wc.dll?Wiki~ +FreeBSDman http://www.FreeBSD.org/cgi/man.cgi?apropos=1&query= +Google http://www.google.com/search?q= +GoogleGroups http://groups.google.com/groups?q= +GreenCheese http://www.greencheese.org/ +HammondWiki http://www.dairiki.org/HammondWiki/index.php3? +Haribeau http://wiki.haribeau.de/cgi-bin/wiki.pl? +IAWiki http://www.IAwiki.net/ +IMDB http://us.imdb.com/Title? +JargonFile http://sunir.org/apps/meta.pl?wiki=JargonFile&redirect= +JiniWiki http://www.cdegroot.com/cgi-bin/jini? +JspWiki http://www.ecyrd.com/JSPWiki/Wiki.jsp?page= +KmWiki http://www.voght.com/cgi-bin/pywiki? +KnowHow http://www2.iro.umontreal.ca/~paquetse/cgi-bin/wiki.cgi? +LanifexWiki http://opt.lanifex.com/cgi-bin/wiki.pl? +LegoWiki http://www.object-arts.com/wiki/html/Lego-Robotics/ +LinuxWiki http://www.linuxwiki.de/ +LugKR http://lug-kr.sourceforge.net/cgi-bin/lugwiki.pl? +MathSongsWiki http://SeedWiki.com/page.cfm?wikiid=237&doc= +MbTest http://www.usemod.com/cgi-bin/mbtest.pl? +MeatBall http://www.usemod.com/cgi-bin/mb.pl? +MetaWiki http://sunir.org/apps/meta.pl? +MetaWikiPedia http://meta.wikipedia.com/wiki/ +MoinMoin http://purl.net/wiki/moin/ +MuWeb http://www.dunstable.com/scripts/MuWebWeb? +NetVillage http://www.netbros.com/? +OpenWiki http://openwiki.com/? +OrgPatterns http://www.bell-labs.com/cgi-user/OrgPatterns/OrgPatterns? +PangalacticOrg http://www.pangalactic.org/Wiki/ +PersonalTelco http://www.personaltelco.net/index.cgi/ +PhpWiki http://phpwiki.sourceforge.net/phpwiki/index.php? +Pikie http://pikie.darktech.org/cgi/pikie? +PPR http://c2.com/cgi/wiki? +PurlNet http://purl.oclc.org/NET/ +PythonInfo http://www.python.org/cgi-bin/moinmoin/ +PythonWiki http://www.pythonwiki.de/ +PyWiki http://www.voght.com/cgi-bin/pywiki? +SeaPig http://www.seapig.org/ +SeattleWireless http://seattlewireless.net/? +SenseisLibrary http://senseis.xmp.net/? +Shakti http://cgi.algonet.se/htbin/cgiwrap/pgd/ShaktiWiki/ +SourceForge http://sourceforge.net/{NAME} +Squeak http://minnow.cc.gatech.edu/squeak/ +StrikiWiki http://ch.twi.tudelft.nl/~mostert/striki/teststriki.pl? +SVGWiki http://www.protocol7.com/svg-wiki/default.asp? +Tavi http://tavi.sourceforge.net/index.php? +TmNet http://www.technomanifestos.net/? +TMwiki http://www.EasyTopicMaps.com/?page= +TWiki http://twiki.org/cgi-bin/view/{NAME} +TwistedWiki http://purl.net/wiki/twisted/ +Unreal http://wiki.beyondunreal.com/wiki/ +UseMod http://www.usemod.com/cgi-bin/wiki.pl? +VisualWorks http://wiki.cs.uiuc.edu/VisualWorks/ +WebDevWikiNL http://www.promo-it.nl/WebDevWiki/index.php?page= +WebSeitzWiki http://webseitz.fluxent.com/wiki/ +Why http://clublet.com/c/c/why? +Wiki http://c2.com/cgi/wiki? +WikiPedia http://www.wikipedia.com/wiki/ +WikiWorld http://WikiWorld.com/wiki/index.php/ +YpsiEyeball http://sknkwrks.dyndns.org:1957/writewiki/wiki.pl? +ZWiki http://www.zwiki.org/ + diff --git a/plugins/dokuwiki/conf/mime.conf b/plugins/dokuwiki/conf/mime.conf new file mode 100644 index 0000000..90356ff --- /dev/null +++ b/plugins/dokuwiki/conf/mime.conf @@ -0,0 +1,41 @@ +#Add extensions and mimetypes of files you want to allow to upload here + +jpg image/jpeg +jpeg image/jpeg +gif image/gif +png image/png +tgz application/octet-stream +tar application/x-gtar +gz application/octet-stream +zip application/zip +pdf application/pdf +txt text/plain +ps application/postscript +doc application/msword +xls application/msexcel +ppt application/mspowerpoint +rtf application/msword +xml text/xml +swf application/x-shockwave-flash + +# You should enable HTML uploads only for restricted Wikis. +# Spammers are known to upload spam pages through unprotected Wikis. +#html text/html +#htm text/html + +rpm application/octet-stream +deb application/octet-stream +conf text/plain + +sxw application/soffice +sxc application/soffice +sxi application/soffice +sxd application/soffice + +odc application/vnd.oasis.opendocument.chart +odf application/vnd.oasis.opendocument.formula +odg application/vnd.oasis.opendocument.graphics +odi application/vnd.oasis.opendocument.image +odp application/vnd.oasis.opendocument.presentation +ods application/vnd.oasis.opendocument.spreadsheet +odt application/vnd.oasis.opendocument.text diff --git a/plugins/dokuwiki/conf/smileys.conf b/plugins/dokuwiki/conf/smileys.conf new file mode 100644 index 0000000..f0e59c9 --- /dev/null +++ b/plugins/dokuwiki/conf/smileys.conf @@ -0,0 +1,28 @@ +# Smileys configured here will be replaced by the +# configured images in the smiley directory + +8-) icon_cool.gif +8-O icon_eek.gif +8-o icon_eek.gif +:-( icon_sad.gif +:-) icon_smile.gif +=) icon_smile2.gif +:-/ icon_doubt.gif +:-\ icon_doubt2.gif +:-? icon_confused.gif +:-D icon_biggrin.gif +:-P icon_razz.gif +:-o icon_surprised.gif +:-O icon_surprised.gif +:-x icon_silenced.gif +:-X icon_silenced.gif +:-| icon_neutral.gif +;-) icon_wink.gif +^_^ icon_fun.gif +:?: icon_question.gif +:!: icon_exclaim.gif +LOL icon_lol.gif +FIXME fixme.gif +DELETEME delete.gif + +#;<P icon_kaddi.gif diff --git a/plugins/dokuwiki/dokuwiki_constants.inc.php b/plugins/dokuwiki/dokuwiki_constants.inc.php new file mode 100644 index 0000000..f984c2f --- /dev/null +++ b/plugins/dokuwiki/dokuwiki_constants.inc.php @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/plugins/dokuwiki/dokuwiki_formattext.inc.php b/plugins/dokuwiki/dokuwiki_formattext.inc.php new file mode 100644 index 0000000..e101502 --- /dev/null +++ b/plugins/dokuwiki/dokuwiki_formattext.inc.php @@ -0,0 +1,155 @@ +Handler = new Doku_Handler(); + + // Add modes to parser + foreach($modes as $mode){ + $Parser->addMode($mode['mode'], $mode['obj']); + } + $instructions = $Parser->parse($text); + + + // Cache the parsed text + if (!is_null($type) && !is_null($id)) { + $fields = array('content'=> serialize($instructions), 'type'=> $type , 'topic'=> $id, + 'last_updated'=> time()); + + $keys = array('type','topic'); + //autoquote is always true on db class + $db->Replace('{cache}', $fields, $keys); + } + } else { + $instructions = unserialize($instructions); + } + + $Renderer->smileys = getSmileys(); + $Renderer->entities = getEntities(); + $Renderer->acronyms = getAcronyms(); + $Renderer->interwiki = getInterwiki(); + + $conf = $fs_conf; + $conf['cachedir'] = FS_CACHE_DIR; // for dokuwiki + $conf['fperm'] = 0600; + $conf['dperm'] = 0700; + + // Loop through the instructions + foreach ($instructions as $instruction) { + // Execute the callback against the Renderer + call_user_func_array(array(&$Renderer, $instruction[0]), $instruction[1]); + } + + $return = $Renderer->doc; + + // Display the output + if (Get::val('histring')) { + $words = explode(' ', Get::val('histring')); + foreach($words as $word) { + $return = html_hilight($return, $word); + } + } + + return $return; + } + static function textarea( $name, $rows, $cols, $attrs = null, $content = null) { + + $name = htmlspecialchars($name, ENT_QUOTES, 'utf-8'); + $rows = intval($rows); + $cols = intval($cols); + $return = '
' + . dokuwiki_TextFormatter::getDokuWikiToolbar( $attrs['id'] ) + . '
'; + + $return .= " + +
+ + + + + + + */ +function html_search(){ + require_once(DOKU_INC.'inc/search.php'); + require_once(DOKU_INC.'inc/fulltext.php'); + global $conf; + global $QUERY; + global $ID; + global $lang; + + print p_locale_xhtml('searchpage'); + flush(); + + //check if search is restricted to namespace + if(preg_match('/([^@]*)@([^@]*)/',$QUERY,$match)) { + $id = cleanID($match[1]); + if(empty($id)) { + print '
'.$lang['nothingfound'].'
'; + flush(); + return; + } + } else { + $id = cleanID($QUERY); + } + + //show progressbar + print '
'; + print ''; + print "
\n"; + flush(); + + //do quick pagesearch + $data = array(); + + $data = ft_pageLookup($id); + if(count($data)){ + sort($data); + print '
'; + print '

'.$lang['quickhits'].':

'; + print ' '; + //clear float (see http://www.complexspiral.com/publications/containing-floats/) + print '
 
'; + print '
'; + } + flush(); + + //do fulltext search + $data = ft_pageSearch($QUERY,$poswords); + if(count($data)){ + $num = 1; + foreach($data as $id => $cnt){ + print '
'; + print html_wikilink(':'.$id,$conf['useheading']?NULL:$id,$poswords); + print ': '.$cnt.' '.$lang['hits'].'
'; + if($num < 15){ // create snippets for the first number of matches only #FIXME add to conf ? + print '
'.ft_snippet($id,$poswords).'
'; + } + print '
'; + flush(); + $num++; + } + }else{ + print '
'.$lang['nothingfound'].'
'; + } + + //hide progressbar + print ''; + flush(); +} + +/** + * Display error on locked pages + * + * @author Andreas Gohr + */ +function html_locked(){ + global $ID; + global $conf; + global $lang; + global $INFO; + + $locktime = filemtime(wikiLockFN($ID)); + $expire = @date($conf['dformat'], $locktime + $conf['locktime'] ); + $min = round(($conf['locktime'] - (time() - $locktime) )/60); + + print p_locale_xhtml('locked'); + print ''; +} + +/** + * list old revisions + * + * @author Andreas Gohr + * @author Ben Coburn + */ +function html_revisions($first=0){ + global $ID; + global $INFO; + global $conf; + global $lang; + /* we need to get one additionally log entry to be able to + * decide if this is the last page or is there another one. + * see html_recent() + */ + $revisions = getRevisions($ID, $first, $conf['recent']+1); + if(count($revisions)==0 && $first!=0){ + $first=0; + $revisions = getRevisions($ID, $first, $conf['recent']+1);; + } + $hasNext = false; + if (count($revisions)>$conf['recent']) { + $hasNext = true; + array_pop($revisions); // remove extra log entry + } + + $date = @date($conf['dformat'],$INFO['lastmod']); + + print p_locale_xhtml('revisions'); + print ''; + + print ''; + +} + +/** + * display recent changes + * + * @author Andreas Gohr + * @author Matthias Grimm + * @author Ben Coburn + */ +function html_recent($first=0){ + global $conf; + global $lang; + global $ID; + /* we need to get one additionally log entry to be able to + * decide if this is the last page or is there another one. + * This is the cheapest solution to get this information. + */ + $recents = getRecents($first,$conf['recent'] + 1,getNS($ID)); + if(count($recents) == 0 && $first != 0){ + $first=0; + $recents = getRecents($first,$conf['recent'] + 1,getNS($ID)); + } + $hasNext = false; + if (count($recents)>$conf['recent']) { + $hasNext = true; + array_pop($recents); // remove extra log entry + } + + print p_locale_xhtml('recent'); + print ''; + + print ''; +} + +/** + * Display page index + * + * @author Andreas Gohr + */ +function html_index($ns){ + require_once(DOKU_INC.'inc/search.php'); + global $conf; + global $ID; + $dir = $conf['datadir']; + $ns = cleanID($ns); + #fixme use appropriate function + if(empty($ns)){ + $ns = dirname(str_replace(':','/',$ID)); + if($ns == '.') $ns =''; + } + $ns = utf8_encodeFN(str_replace(':','/',$ns)); + + print p_locale_xhtml('index'); + + $data = array(); + search($data,$conf['datadir'],'search_index',array('ns' => $ns)); + print html_buildlist($data,'idx','html_list_index','html_li_index'); +} + +/** + * Index item formatter + * + * User function for html_buildlist() + * + * @author Andreas Gohr + */ +function html_list_index($item){ + global $ID; + $ret = ''; + $base = ':'.$item['id']; + $base = substr($base,strrpos($base,':')+1); + if($item['type']=='d'){ + $ret .= ''; + $ret .= $base; + $ret .= ''; + }else{ + $ret .= html_wikilink(':'.$item['id']); + } + return $ret; +} + +/** + * Index List item + * + * This user function is used in html_build_lidt to build the + *
  • tags for namespaces when displaying the page index + * it gives different classes to opened or closed "folders" + * + * @author Andreas Gohr + */ +function html_li_index($item){ + if($item['type'] == "f"){ + return '
  • '; + }elseif($item['open']){ + return '
  • '; + }else{ + return '
  • '; + } +} + +/** + * Default List item + * + * @author Andreas Gohr + */ +function html_li_default($item){ + return '
  • '; +} + +/** + * Build an unordered list + * + * Build an unordered list from the given $data array + * Each item in the array has to have a 'level' property + * the item itself gets printed by the given $func user + * function. The second and optional function is used to + * print the
  • tag. Both user function need to accept + * a single item. + * + * Both user functions can be given as array to point to + * a member of an object. + * + * @author Andreas Gohr + */ +function html_buildlist($data,$class,$func,$lifunc='html_li_default'){ + $level = 0; + $opens = 0; + $ret = ''; + + foreach ($data as $item){ + + if( $item['level'] > $level ){ + //open new list + for($i=0; $i<($item['level'] - $level); $i++){ + if ($i) $ret .= "
  • \n"; + $ret .= "\n
      \n"; + } + }elseif( $item['level'] < $level ){ + //close last item + $ret .= "\n"; + for ($i=0; $i<($level - $item['level']); $i++){ + //close higher lists + $ret .= "
    \n
  • \n"; + } + }else{ + //close last item + $ret .= "\n"; + } + + //remember current level + $level = $item['level']; + + //print item + if(is_array($lifunc)){ + $ret .= $lifunc[0]->$lifunc[1]($item); //user object method + }else{ + $ret .= $lifunc($item); //user function + } + $ret .= '
    '; + if(is_array($func)){ + $ret .= $func[0]->$func[1]($item); //user object method + }else{ + $ret .= $func($item); //user function + } + $ret .= '
    '; + } + + //close remaining items and lists + for ($i=0; $i < $level; $i++){ + $ret .= "\n"; + } + + return $ret; +} + +/** + * display backlinks + * + * @author Andreas Gohr + */ +function html_backlinks(){ + require_once(DOKU_INC.'inc/fulltext.php'); + global $ID; + global $conf; + + print p_locale_xhtml('backlinks'); + + $data = ft_backlinks($ID); + + print '
      '; + foreach($data as $blink){ + print '
    • '; + print html_wikilink(':'.$blink,$conf['useheading']?NULL:$blink); + print '
    • '; + } + print '
    '; +} + +/** + * show diff + * + * @author Andreas Gohr + */ +function html_diff($text='',$intro=true){ + require_once(DOKU_INC.'inc/DifferenceEngine.php'); + global $ID; + global $REV; + global $lang; + global $conf; + + if($text){ + $df = new Diff(explode("\n",htmlspecialchars(rawWiki($ID,''))), + explode("\n",htmlspecialchars(cleanText($text)))); + $left = ''. + $ID.' '.date($conf['dformat'],@filemtime(wikiFN($ID))).''. + $lang['current']; + $right = $lang['yours']; + }else{ + if($REV){ + $r = $REV; + }else{ + //use last revision if none given + $revs = getRevisions($ID, 0, 1); + $r = $revs[0]; + } + + if($r){ + $df = new Diff(explode("\n",htmlspecialchars(rawWiki($ID,$r))), + explode("\n",htmlspecialchars(rawWiki($ID,'')))); + $left = ''. + $ID.' '.date($conf['dformat'],$r).''; + }else{ + $df = new Diff(array(''), + explode("\n",htmlspecialchars(rawWiki($ID,'')))); + $left = ''. + $ID.''; + } + $right = ''. + $ID.' '.date($conf['dformat'],@filemtime(wikiFN($ID))).' '. + $lang['current']; + } + $tdf = new TableDiffFormatter(); + if($intro) print p_locale_xhtml('diff'); + ?> + + + + + + format($df)?> +
    + + + +
    + + */ +function html_conflict($text,$summary){ + global $ID; + global $lang; + + print p_locale_xhtml('conflict'); + ?> +
    +
    + + + + + + +
    +
    +



    + + */ +function html_msgarea(){ + global $MSG; + + if(!isset($MSG)) return; + + foreach($MSG as $msg){ + print '
    '; + print $msg['msg']; + print '
    '; + } +} + +/** + * Prints the registration form + * + * @author Andreas Gohr + */ +function html_register(){ + global $lang; + global $conf; + global $ID; + + print p_locale_xhtml('register'); +?> +
    +
    +
    + + + + +
    + + +
    +
    + + +
    +
    + +
    +
    +
    + + * @author Andreas Gohr + */ +function html_updateprofile(){ + global $lang; + global $conf; + global $ID; + global $INFO; + global $auth; + + print p_locale_xhtml('updateprofile'); + + if (empty($_POST['fullname'])) $_POST['fullname'] = $INFO['userinfo']['name']; + if (empty($_POST['email'])) $_POST['email'] = $INFO['userinfo']['mail']; +?> +
    +
    +
    + + + + +
    +
    +

    + + canDo('modPass')) { ?> +
    +
    + + + +
    +
    + + + + +
    +
    +
    + + */ +function html_edit($text=null,$include='edit'){ //FIXME: include needed? + global $ID; + global $REV; + global $DATE; + global $RANGE; + global $PRE; + global $SUF; + global $INFO; + global $SUM; + global $lang; + global $conf; + + //set summary default + if(!$SUM){ + if($REV){ + $SUM = $lang['restored']; + }elseif(!$INFO['exists']){ + $SUM = $lang['created']; + } + } + + //no text? Load it! + if(!isset($text)){ + $pr = false; //no preview mode + if($INFO['exists']){ + if($RANGE){ + list($PRE,$text,$SUF) = rawWikiSlices($RANGE,$ID,$REV); + }else{ + $text = rawWiki($ID,$REV); + } + }else{ + //try to load a pagetemplate + $data = array($ID); + $text = trigger_event('HTML_PAGE_FROMTEMPLATE',$data,'pageTemplate',true); + } + }else{ + $pr = true; //preview mode + } + + $wr = $INFO['writable']; + if($wr){ + if ($REV) print p_locale_xhtml('editrev'); + print p_locale_xhtml($include); + $ro=false; + }else{ + // check pseudo action 'source' + if(!actionOK('source')){ + msg('Command disabled: source',-1); + return; + } + print p_locale_xhtml('read'); + $ro='readonly="readonly"'; + } + if(!$DATE) $DATE = $INFO['lastmod']; + + +?> +
    + +
    +
    +
    + + + + +
    + +
    +
    + + +
    + + + + + +
    + + + +
    +
    + +
    + + + +
    + + +
    + + + +
    + +
    +
    +
    + + */ +function html_minoredit(){ + global $conf; + global $lang; + // minor edits are for logged in users only + if(!$conf['useacl'] || !$_SERVER['REMOTE_USER']){ + return; + } + + $p = array(); + $p['name'] = 'minor'; + $p['type'] = 'checkbox'; + $p['id'] = 'minoredit'; + $p['tabindex'] = 3; + $p['value'] = '1'; + if(!empty($_REQUEST['minor'])) $p['checked']='checked'; + $att = buildAttributes($p); + + print ''; + print ""; + print ''; + print ''; +} + +/** + * prints some debug info + * + * @author Andreas Gohr + */ +function html_debug(){ + global $conf; + global $lang; + global $auth; + global $INFO; + + //remove sensitive data + $cnf = $conf; + $cnf['auth']='***'; + $cnf['notify']='***'; + $cnf['ftp']='***'; + $nfo = $INFO; + $nfo['userinfo'] = '***'; + $ses = $_SESSION; + $ses[$conf['title']]['auth'] = '***'; + + print ''; + + print '

    When reporting bugs please send all the following '; + print 'output as a mail to andi@splitbrain.org '; + print 'The best way to do this is to save this page in your browser

    '; + + print '$INFO:
    ';
    +  print_r($nfo);
    +  print '
    '; + + print '$_SERVER:
    ';
    +  print_r($_SERVER);
    +  print '
    '; + + print '$conf:
    ';
    +  print_r($cnf);
    +  print '
    '; + + print 'DOKU_BASE:
    ';
    +  print DOKU_BASE;
    +  print '
    '; + + print 'abs DOKU_BASE:
    ';
    +  print DOKU_URL;
    +  print '
    '; + + print 'rel DOKU_BASE:
    ';
    +  print dirname($_SERVER['PHP_SELF']).'/';
    +  print '
    '; + + print 'PHP Version:
    ';
    +  print phpversion();
    +  print '
    '; + + print 'locale:
    ';
    +  print setlocale(LC_ALL,0);
    +  print '
    '; + + print 'encoding:
    ';
    +  print $lang['encoding'];
    +  print '
    '; + + if($auth){ + print 'Auth backend capabilities:
    ';
    +    print_r($auth->cando);
    +    print '
    '; + } + + print '$_SESSION:
    ';
    +  print_r($ses);
    +  print '
    '; + + print 'Environment:
    ';
    +  print_r($_ENV);
    +  print '
    '; + + print 'PHP settings:
    ';
    +  $inis = ini_get_all();
    +  print_r($inis);
    +  print '
    '; + + print ''; +} + +function html_admin(){ + global $ID; + global $lang; + global $conf; + + print p_locale_xhtml('admin'); + + // build menu of admin functions from the plugins that handle them + $pluginlist = plugin_list('admin'); + $menu = array(); + foreach ($pluginlist as $p) { + if($obj =& plugin_load('admin',$p) === NULL) continue; + $menu[] = array('plugin' => $p, + 'prompt' => $obj->getMenuText($conf['lang']), + 'sort' => $obj->getMenuSort() + ); + } + + usort($menu, 'p_sort_modes'); + + // output the menu + ptln('
      '); + + foreach ($menu as $item) { + if (!$item['prompt']) continue; + ptln('
    • '); + } + + ptln('
    '); +} + +/** + * Form to request a new password for an existing account + * + * @author Benoit Chesneau + */ +function html_resendpwd() { + global $lang; + global $conf; + global $ID; + + print p_locale_xhtml('resendpwd'); +?> +
    +
    +
    +
    + + + +
    + +
    +
    +
    + + */ +if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); +if(!defined('DOKU_MESSAGEURL')) define('DOKU_MESSAGEURL','http://update.dokuwiki.org/check/'); +require_once(DOKU_INC.'inc/HTTPClient.php'); + +/** + * Check for new messages from upstream + * + * @author Andreas Gohr + */ +function checkUpdateMessages(){ + global $conf; + global $INFO; + if(!$conf['updatecheck']) return; + if($conf['useacl'] && $INFO['perm'] < AUTH_ADMIN) return; + + $cf = $conf['cachedir'].'/messages.txt'; + $lm = @filemtime($cf); + + // check if new messages needs to be fetched + if($lm < time()-(60*60*24) || $lm < @filemtime(DOKU_CONF.'msg')){ + $num = @file(DOKU_CONF.'msg'); + $num = is_array($num) ? (int) $num[0] : 0; + $http = new DokuHTTPClient(); + $http->timeout = 8; + $data = $http->get(DOKU_MESSAGEURL.$num); + io_saveFile($cf,$data); + }else{ + $data = io_readFile($cf); + } + + // show messages through the usual message mechanism + $msgs = explode("\n%\n",$data); + foreach($msgs as $msg){ + if($msg) msg($msg,2); + } +} + + +/** + * Return DokuWikis version + * + * @author Andreas Gohr + */ +function getVersion(){ + //import version string + if(@file_exists('VERSION')){ + //official release + return 'Release '.trim(io_readfile(DOKU_INC.'/VERSION')); + }elseif(is_dir('_darcs')){ + //darcs checkout - read last 2000 bytes of inventory + $sz = filesize('_darcs/inventory'); + $seek = max(0,$sz-2000); + $fh = fopen('_darcs/inventory','rb'); + fseek($fh,$seek); + $chunk = fread($fh,2000); + fclose($fh); + $inv = preg_grep('#\*\*\d{14}[\]$]#',explode("\n",$chunk)); + $cur = array_pop($inv); + preg_match('#\*\*(\d{4})(\d{2})(\d{2})#',$cur,$matches); + return 'Darcs '.$matches[1].'-'.$matches[2].'-'.$matches[3]; + }else{ + return 'snapshot?'; + } +} + +/** + * Run a few sanity checks + * + * @author Andreas Gohr + */ +function check(){ + global $conf; + global $INFO; + + msg('DokuWiki version: '.getVersion(),1); + + if(version_compare(phpversion(),'4.3.3','<')){ + msg('Your PHP version is too old ('.phpversion().' vs. 4.3.3+ recommended)',-1); + }elseif(version_compare(phpversion(),'4.3.10','<')){ + msg('Consider upgrading PHP to 4.3.10 or higher for security reasons (your version: '.phpversion().')',0); + }else{ + msg('PHP version '.phpversion(),1); + } + + if(is_writable($conf['changelog'])){ + msg('Changelog is writable',1); + }else{ + if (@file_exists($conf['changelog'])) { + msg('Changelog is not writable',-1); + } + } + + if (isset($conf['changelog_old']) && @file_exists($conf['changelog_old'])) { + msg('Old changelog exists', 0); + } + + if (@file_exists($conf['changelog'].'_failed')) { + msg('Importing old changelog failed', -1); + } else if (@file_exists($conf['changelog'].'_importing')) { + msg('Importing old changelog now.', 0); + } else if (@file_exists($conf['changelog'].'_import_ok')) { + msg('Old changelog imported', 1); + if (!plugin_isdisabled('importoldchangelog')) { + msg('Importoldchangelog plugin not disabled after import', -1); + } + } + + if(is_writable($conf['datadir'])){ + msg('Datadir is writable',1); + }else{ + msg('Datadir is not writable',-1); + } + + if(is_writable($conf['olddir'])){ + msg('Attic is writable',1); + }else{ + msg('Attic is not writable',-1); + } + + if(is_writable($conf['mediadir'])){ + msg('Mediadir is writable',1); + }else{ + msg('Mediadir is not writable',-1); + } + + if(is_writable($conf['cachedir'])){ + msg('Cachedir is writable',1); + }else{ + msg('Cachedir is not writable',-1); + } + + if(is_writable($conf['lockdir'])){ + msg('Lockdir is writable',1); + }else{ + msg('Lockdir is not writable',-1); + } + + if(is_writable(DOKU_CONF.'users.auth.php')){ + msg('conf/users.auth.php is writable',1); + }else{ + msg('conf/users.auth.php is not writable',0); + } + + if(function_exists('mb_strpos')){ + if(defined('UTF8_NOMBSTRING')){ + msg('mb_string extension is available but will not be used',0); + }else{ + msg('mb_string extension is available and will be used',1); + } + }else{ + msg('mb_string extension not available - PHP only replacements will be used',0); + } + + if($conf['allowdebug']){ + msg('Debugging support is enabled. If you don\'t need it you should set $conf[\'allowdebug\'] = 0',-1); + }else{ + msg('Debugging support is disabled',1); + } + + msg('Your current permission for this page is '.$INFO['perm'],0); + + if(is_writable($INFO['filepath'])){ + msg('The current page is writable by the webserver',0); + }else{ + msg('The current page is not writable by the webserver',0); + } + + if($INFO['writable']){ + msg('The current page is writable by you',0); + }else{ + msg('The current page is not writable by you',0); + } +} + +/** + * print a message + * + * If HTTP headers were not sent yet the message is added + * to the global message array else it's printed directly + * using html_msgarea() + * + * + * Levels can be: + * + * -1 error + * 0 info + * 1 success + * + * @author Andreas Gohr + * @see html_msgarea + */ +function msg($message,$lvl=0,$line='',$file=''){ + global $MSG; + $errors[-1] = 'error'; + $errors[0] = 'info'; + $errors[1] = 'success'; + $errors[2] = 'notify'; + + if($line || $file) $message.=' ['.basename($file).':'.$line.']'; + + if(!headers_sent()){ + if(!isset($MSG)) $MSG = array(); + $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message); + }else{ + $MSG = array(); + $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message); + if(function_exists('html_msgarea')){ + html_msgarea(); + }else{ + print "ERROR($lvl) $message"; + } + } +} + +/** + * print debug messages + * + * little function to print the content of a var + * + * @author Andreas Gohr + */ +function dbg($msg,$hidden=false){ + (!$hidden) ? print '
    ' : print "";
    +}
    +
    +/**
    + * Print info to a log file
    + *
    + * @author Andreas Gohr 
    + */
    +function dbglog($msg){
    +  global $conf;
    +  $file = $conf['cachedir'].'/debug.log';
    +  $fh = fopen($file,'a');
    +  if($fh){
    +    fwrite($fh,date('H:i:s ').$_SERVER['REMOTE_ADDR'].': '.$msg."\n");
    +    fclose($fh);
    +  }
    +}
    +
    diff --git a/plugins/dokuwiki/inc/init.php b/plugins/dokuwiki/inc/init.php
    new file mode 100644
    index 0000000..272f759
    --- /dev/null
    +++ b/plugins/dokuwiki/inc/init.php
    @@ -0,0 +1,367 @@
    + 'pages',
    +                 'olddir'    => 'attic',
    +                 'mediadir'  => 'media',
    +                 'metadir'   => 'meta',
    +                 'cachedir'  => 'cache',
    +                 'lockdir'   => 'locks');
    +
    +  foreach($paths as $c => $p){
    +    if(empty($conf[$c]))  $conf[$c] = $conf['savedir'].'/'.$p;
    +    $conf[$c]             = init_path($conf[$c]);
    +    if(empty($conf[$c]))  nice_die("The $c does not exist, isn't accessable or writable.
    +                               You should check your config and permission settings.
    +                               Or maybe you want to run the
    +                               installer?");
    +  }
    +
    +  // path to old changelog only needed for upgrading
    +  $conf['changelog_old'] = init_path((isset($conf['changelog']))?($conf['changelog']):($conf['savedir'].'/changes.log'));
    +  if ($conf['changelog_old']=='') { unset($conf['changelog_old']); }
    +  // hardcoded changelog because it is now a cache that lives in meta
    +  $conf['changelog'] = $conf['metadir'].'/_dokuwiki.changes';
    +}
    +
    +/**
    + * Checks the existance of certain files and creates them if missing.
    + */
    +function init_files(){
    +  global $conf;
    +
    +  $files = array( $conf['cachedir'].'/word.idx',
    +                  $conf['cachedir'].'/page.idx',
    +                  $conf['cachedir'].'/index.idx');
    +
    +  foreach($files as $file){
    +    if(!@file_exists($file)){
    +      $fh = @fopen($file,'a');
    +      if($fh){
    +        fclose($fh);
    +        if($conf['fperm']) chmod($file, $conf['fperm']);
    +      }else{
    +        nice_die("$file is not writable. Check your permissions settings!");
    +      }
    +    }
    +  }
    +}
    +
    +/**
    + * Returns absolute path
    + *
    + * This tries the given path first, then checks in DOKU_INC.
    + * Check for accessability on directories as well.
    + *
    + * @author Andreas Gohr 
    + */
    +function init_path($path){
    +  // check existance
    +  $p = realpath($path);
    +  if(!@file_exists($p)){
    +    $p = realpath(DOKU_INC.$path);
    +    if(!@file_exists($p)){
    +      return '';
    +    }
    +  }
    +
    +  // check writability
    +  if(!@is_writable($p)){
    +    return '';
    +  }
    +
    +  // check accessability (execute bit) for directories
    +  if(@is_dir($p) && !@file_exists("$p/.")){
    +    return '';
    +  }
    +
    +  return $p;
    +}
    +
    +/**
    + * Sets the internal config values fperm and dperm which, when set,
    + * will be used to change the permission of a newly created dir or
    + * file with chmod. Considers the influence of the system's umask
    + * setting the values only if needed.
    + */
    +function init_creationmodes(){
    +  global $conf;
    +
    +  // Legacy support for old umask/dmask scheme
    +  unset($conf['dmask']);
    +  unset($conf['fmask']);
    +  unset($conf['umask']);
    +  unset($conf['fperm']);
    +  unset($conf['dperm']);
    +
    +  // get system umask, fallback to 0 if none available
    +  $umask = @umask();
    +  if(!$umask) $umask = 0000;
    +
    +  // check what is set automatically by the system on file creation
    +  // and set the fperm param if it's not what we want
    +  $auto_fmode = 0666 & ~$umask;
    +  if($auto_fmode != $conf['fmode']) $conf['fperm'] = $conf['fmode'];
    +
    +  // check what is set automatically by the system on file creation
    +  // and set the dperm param if it's not what we want
    +  $auto_dmode = $conf['dmode'] & ~$umask;
    +  if($auto_dmode != $conf['dmode']) $conf['dperm'] = $conf['dmode'];
    +}
    +
    +/**
    + * remove magic quotes recursivly
    + *
    + * @author Andreas Gohr 
    + */
    +function remove_magic_quotes(&$array) {
    +  foreach (array_keys($array) as $key) {
    +    if (is_array($array[$key])) {
    +      remove_magic_quotes($array[$key]);
    +    }else {
    +      $array[$key] = stripslashes($array[$key]);
    +    }
    +  }
    +}
    +
    +/**
    + * Returns the full absolute URL to the directory where
    + * DokuWiki is installed in (includes a trailing slash)
    + *
    + * @author Andreas Gohr 
    + */
    +function getBaseURL($abs=false){
    +  global $conf;
    +  //if canonical url enabled always return absolute
    +  if($conf['canonical']) $abs = true;
    +
    +  if($conf['basedir']){
    +    $dir = $conf['basedir'].'/';
    +  }elseif(substr($_SERVER['SCRIPT_NAME'],-4) == '.php'){
    +    $dir = dirname($_SERVER['SCRIPT_NAME']).'/';
    +  }elseif(substr($_SERVER['PHP_SELF'],-4) == '.php'){
    +    $dir = dirname($_SERVER['PHP_SELF']).'/';
    +  }elseif($_SERVER['DOCUMENT_ROOT'] && $_SERVER['SCRIPT_FILENAME']){
    +    $dir = preg_replace ('/^'.preg_quote($_SERVER['DOCUMENT_ROOT'],'/').'/','',
    +                         $_SERVER['SCRIPT_FILENAME']);
    +    $dir = dirname('/'.$dir).'/';
    +  }else{
    +    $dir = './'; //probably wrong
    +  }
    +
    +  $dir = str_replace('\\','/',$dir); #bugfix for weird WIN behaviour
    +  $dir = preg_replace('#//+#','/',$dir);
    +
    +  //handle script in lib/exe dir
    +  $dir = preg_replace('!lib/exe/$!','',$dir);
    +
    +  //handle script in lib/plugins dir
    +  $dir = preg_replace('!lib/plugins/.*$!','',$dir);
    +
    +  //finish here for relative URLs
    +  if(!$abs) return $dir;
    +
    +  //use config option if available
    +  if($conf['baseurl']) return $conf['baseurl'].$dir;
    +
    +  //split hostheader into host and port
    +  list($host,$port) = explode(':',$_SERVER['HTTP_HOST']);
    +  if(!$port)  $port = $_SERVER['SERVER_PORT'];
    +  if(!$port)  $port = 80;
    +
    +  // see if HTTPS is enabled - apache leaves this empty when not available,
    +  // IIS sets it to 'off', 'false' and 'disabled' are just guessing
    +  if (preg_match('/^(|off|false|disabled)$/i',$_SERVER['HTTPS'])){
    +    $proto = 'http://';
    +    if ($port == '80') {
    +      $port='';
    +    }
    +  }else{
    +    $proto = 'https://';
    +    if ($port == '443') {
    +      $port='';
    +    }
    +  }
    +
    +  if($port) $port = ':'.$port;
    +
    +  return $proto.$host.$port.$dir;
    +}
    +
    +/**
    + * Append a PHP extension to a given file and adds an exit call
    + *
    + * This is used to migrate some old configfiles. An added PHP extension
    + * ensures the contents are not shown to webusers even if .htaccess files
    + * do not work
    + *
    + * @author Jan Decaluwe 
    + */
    +function scriptify($file) {
    +  // checks
    +  if (!is_readable($file)) {
    +    return;
    +  }
    +  $fn = $file.'.php';
    +  if (@file_exists($fn)) {
    +    return;
    +  }
    +  $fh = fopen($fn, 'w');
    +  if (!$fh) {
    +    nice_die($fn.' is not writable. Check your permission settings!');
    +  }
    +  // write php exit hack first
    +  fwrite($fh, "# $fn\n");
    +  fwrite($fh, '# '."\n");
    +  fwrite($fh, "# Don't modify the lines above\n");
    +  fwrite($fh, "#\n");
    +  // copy existing lines
    +  $lines = file($file);
    +  foreach ($lines as $line){
    +    fwrite($fh, $line);
    +  }
    +  fclose($fh);
    +  //try to rename the old file
    +  io_rename($file,"$file.old");
    +}
    +
    +/**
    + * print a nice message even if no styles are loaded yet.
    + */
    +function nice_die($msg){
    +  echo<<
    +  
    +    DokuWiki Setup Error
    +    
    +      
    +

    DokuWiki Setup Error

    +

    $msg

    +
    + + +EOT; + exit; +} + + +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/io.php b/plugins/dokuwiki/inc/io.php new file mode 100644 index 0000000..d941ef0 --- /dev/null +++ b/plugins/dokuwiki/inc/io.php @@ -0,0 +1,567 @@ + + */ + + if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); + require_once(DOKU_INC.'inc/common.php'); + require_once(DOKU_INC.'inc/HTTPClient.php'); + require_once(DOKU_INC.'inc/events.php'); + require_once(DOKU_INC.'inc/utf8.php'); + +/** + * Removes empty directories + * + * Sends IO_NAMESPACE_DELETED events for 'pages' and 'media' namespaces. + * Event data: + * $data[0] ns: The colon separated namespace path minus the trailing page name. + * $data[1] ns_type: 'pages' or 'media' namespace tree. + * + * @todo use safemode hack + * @author Andreas Gohr + * @author Ben Coburn + */ +function io_sweepNS($id,$basedir='datadir'){ + global $conf; + $types = array ('datadir'=>'pages', 'mediadir'=>'media'); + $ns_type = (isset($types[$basedir])?$types[$basedir]:false); + + //scan all namespaces + while(($id = getNS($id)) !== false){ + $dir = $conf[$basedir].'/'.utf8_encodeFN(str_replace(':','/',$id)); + + //try to delete dir else return + if(@rmdir($dir)) { + if ($ns_type!==false) { + $data = array($id, $ns_type); + trigger_event('IO_NAMESPACE_DELETED', $data); + } + } else { return; } + } +} + +/** + * Used to read in a DokuWiki page from file, and send IO_WIKIPAGE_READ events. + * + * Generates the action event which delegates to io_readFile(). + * Action plugins are allowed to modify the page content in transit. + * The file path should not be changed. + * + * Event data: + * $data[0] The raw arguments for io_readFile as an array. + * $data[1] ns: The colon separated namespace path minus the trailing page name. (false if root ns) + * $data[2] page_name: The wiki page name. + * $data[3] rev: The page revision, false for current wiki pages. + * + * @author Ben Coburn + */ +function io_readWikiPage($file, $id, $rev=false) { + if (empty($rev)) { $rev = false; } + $data = array(array($file, false), getNS($id), noNS($id), $rev); + return trigger_event('IO_WIKIPAGE_READ', $data, '_io_readWikiPage_action', false); +} + +/** + * Callback adapter for io_readFile(). + * @author Ben Coburn + */ +function _io_readWikiPage_action($data) { + if (is_array($data) && is_array($data[0]) && count($data[0])===2) { + return call_user_func_array('io_readFile', $data[0]); + } else { + return ''; //callback error + } +} + +/** + * Returns content of $file as cleaned string. + * + * Uses gzip if extension is .gz + * + * If you want to use the returned value in unserialize + * be sure to set $clean to false! + * + * @author Andreas Gohr + */ +function io_readFile($file,$clean=true){ + $ret = ''; + if(@file_exists($file)){ + if(substr($file,-3) == '.gz'){ + $ret = join('',gzfile($file)); + }else if(substr($file,-4) == '.bz2'){ + $ret = bzfile($file); + }else{ + $ret = join('',file($file)); + } + } + if($clean){ + return cleanText($ret); + }else{ + return $ret; + } +} +/** +* Returns the content of a .bz2 compressed file as string +* @author marcel senf +*/ + +function bzfile($file){ + $bz = bzopen($file,"r"); + while (!feof($bz)){ + //8192 seems to be the maximum buffersize? + $str = $str . bzread($bz,8192); + } + bzclose($bz); + return $str; +} + + +/** + * Used to write out a DokuWiki page to file, and send IO_WIKIPAGE_WRITE events. + * + * This generates an action event and delegates to io_saveFile(). + * Action plugins are allowed to modify the page content in transit. + * The file path should not be changed. + * (The append parameter is set to false.) + * + * Event data: + * $data[0] The raw arguments for io_saveFile as an array. + * $data[1] ns: The colon separated namespace path minus the trailing page name. (false if root ns) + * $data[2] page_name: The wiki page name. + * $data[3] rev: The page revision, false for current wiki pages. + * + * @author Ben Coburn + */ +function io_writeWikiPage($file, $content, $id, $rev=false) { + if (empty($rev)) { $rev = false; } + if ($rev===false) { io_createNamespace($id); } // create namespaces as needed + $data = array(array($file, $content, false), getNS($id), noNS($id), $rev); + return trigger_event('IO_WIKIPAGE_WRITE', $data, '_io_writeWikiPage_action', false); +} + +/** + * Callback adapter for io_saveFile(). + * @author Ben Coburn + */ +function _io_writeWikiPage_action($data) { + if (is_array($data) && is_array($data[0]) && count($data[0])===3) { + return call_user_func_array('io_saveFile', $data[0]); + } else { + return false; //callback error + } +} + +/** + * Saves $content to $file. + * + * If the third parameter is set to true the given content + * will be appended. + * + * Uses gzip if extension is .gz + * and bz2 if extension is .bz2 + * + * @author Andreas Gohr + * @return bool true on success + */ +function io_saveFile($file,$content,$append=false){ + global $conf; + $mode = ($append) ? 'ab' : 'wb'; + + $fileexists = @file_exists($file); + io_makeFileDir($file); + io_lock($file); + if(substr($file,-3) == '.gz'){ + $fh = @gzopen($file,$mode.'9'); + if(!$fh){ + msg("Writing $file failed",-1); + io_unlock($file); + return false; + } + gzwrite($fh, $content); + gzclose($fh); + }else if(substr($file,-4) == '.bz2'){ + $fh = @bzopen($file,$mode); + if(!$fh){ + msg("Writing $file failed", -1); + io_unlock($file); + return false; + } + bzwrite($fh, $content); + bzclose($fh); + }else{ + $fh = @fopen($file,$mode); + if(!$fh){ + msg("Writing $file failed",-1); + io_unlock($file); + return false; + } + fwrite($fh, $content); + fclose($fh); + } + + if(!$fileexists and !empty($conf['fperm'])) chmod($file, $conf['fperm']); + io_unlock($file); + return true; +} + +/** + * Delete exact linematch for $badline from $file. + * + * Be sure to include the trailing newline in $badline + * + * Uses gzip if extension is .gz + * + * 2005-10-14 : added regex option -- Christopher Smith + * + * @author Steven Danz + * @return bool true on success + */ +function io_deleteFromFile($file,$badline,$regex=false){ + if (!@file_exists($file)) return true; + + io_lock($file); + + // load into array + if(substr($file,-3) == '.gz'){ + $lines = gzfile($file); + }else{ + $lines = file($file); + } + + // remove all matching lines + if ($regex) { + $lines = preg_grep($badline,$lines,PREG_GREP_INVERT); + } else { + $pos = array_search($badline,$lines); //return null or false if not found + while(is_int($pos)){ + unset($lines[$pos]); + $pos = array_search($badline,$lines); + } + } + + if(count($lines)){ + $content = join('',$lines); + if(substr($file,-3) == '.gz'){ + $fh = @gzopen($file,'wb9'); + if(!$fh){ + msg("Removing content from $file failed",-1); + io_unlock($file); + return false; + } + gzwrite($fh, $content); + gzclose($fh); + }else{ + $fh = @fopen($file,'wb'); + if(!$fh){ + msg("Removing content from $file failed",-1); + io_unlock($file); + return false; + } + fwrite($fh, $content); + fclose($fh); + } + }else{ + @unlink($file); + } + + io_unlock($file); + return true; +} + +/** + * Tries to lock a file + * + * Locking is only done for io_savefile and uses directories + * inside $conf['lockdir'] + * + * It waits maximal 3 seconds for the lock, after this time + * the lock is assumed to be stale and the function goes on + * + * @author Andreas Gohr + */ +function io_lock($file){ + global $conf; + // no locking if safemode hack + if($conf['safemodehack']) return; + + $lockDir = $conf['lockdir'].'/'.md5($file); + @ignore_user_abort(1); + + $timeStart = time(); + do { + //waited longer than 3 seconds? -> stale lock + if ((time() - $timeStart) > 3) break; + $locked = @mkdir($lockDir, $conf['dmode']); + if($locked){ + if(!empty($conf['dperm'])) chmod($lockDir, $conf['dperm']); + break; + } + usleep(50); + } while ($locked === false); +} + +/** + * Unlocks a file + * + * @author Andreas Gohr + */ +function io_unlock($file){ + global $conf; + // no locking if safemode hack + if($conf['safemodehack']) return; + + $lockDir = $conf['lockdir'].'/'.md5($file); + @rmdir($lockDir); + @ignore_user_abort(0); +} + +/** + * Create missing namespace directories and send the IO_NAMESPACE_CREATED events + * in the order of directory creation. (Parent directories first.) + * + * Event data: + * $data[0] ns: The colon separated namespace path minus the trailing page name. + * $data[1] ns_type: 'pages' or 'media' namespace tree. + * + * @author Ben Coburn + */ +function io_createNamespace($id, $ns_type='pages') { + // verify ns_type + $types = array('pages'=>'wikiFN', 'media'=>'mediaFN'); + if (!isset($types[$ns_type])) { + trigger_error('Bad $ns_type parameter for io_createNamespace().'); + return; + } + // make event list + $missing = array(); + $ns_stack = explode(':', $id); + $ns = $id; + $tmp = dirname( $file = call_user_func($types[$ns_type], $ns) ); + while (!@is_dir($tmp) && !(@file_exists($tmp) && !is_dir($tmp))) { + array_pop($ns_stack); + $ns = implode(':', $ns_stack); + if (strlen($ns)==0) { break; } + $missing[] = $ns; + $tmp = dirname(call_user_func($types[$ns_type], $ns)); + } + // make directories + io_makeFileDir($file); + // send the events + $missing = array_reverse($missing); // inside out + foreach ($missing as $ns) { + $data = array($ns, $ns_type); + trigger_event('IO_NAMESPACE_CREATED', $data); + } +} + +/** + * Create the directory needed for the given file + * + * @author Andreas Gohr + */ +function io_makeFileDir($file){ + global $conf; + + $dir = dirname($file); + if(!@is_dir($dir)){ + io_mkdir_p($dir) || msg("Creating directory $dir failed",-1); + } +} + +/** + * Creates a directory hierachy. + * + * @link http://www.php.net/manual/en/function.mkdir.php + * @author + * @author Andreas Gohr + */ +function io_mkdir_p($target){ + global $conf; + if (@is_dir($target)||empty($target)) return 1; // best case check first + if (@file_exists($target) && !is_dir($target)) return 0; + //recursion + if (io_mkdir_p(substr($target,0,strrpos($target,'/')))){ + if($conf['safemodehack']){ + $dir = preg_replace('/^'.preg_quote(realpath($conf['ftp']['root']),'/').'/','', $target); + return io_mkdir_ftp($dir); + }else{ + $ret = @mkdir($target,$conf['dmode']); // crawl back up & create dir tree + if($ret && $conf['dperm']) chmod($target, $conf['dperm']); + return $ret; + } + } + return 0; +} + +/** + * Creates a directory using FTP + * + * This is used when the safemode workaround is enabled + * + * @author + */ +function io_mkdir_ftp($dir){ + global $conf; + + if(!function_exists('ftp_connect')){ + msg("FTP support not found - safemode workaround not usable",-1); + return false; + } + + $conn = @ftp_connect($conf['ftp']['host'],$conf['ftp']['port'],10); + if(!$conn){ + msg("FTP connection failed",-1); + return false; + } + + if(!@ftp_login($conn, $conf['ftp']['user'], $conf['ftp']['pass'])){ + msg("FTP login failed",-1); + return false; + } + + //create directory + $ok = @ftp_mkdir($conn, $dir); + //set permissions + @ftp_site($conn,sprintf("CHMOD %04o %s",$conf['dmode'],$dir)); + + @ftp_close($conn); + return $ok; +} + +/** + * downloads a file from the net and saves it + * + * if $useAttachment is false, + * - $file is the full filename to save the file, incl. path + * - if successful will return true, false otherwise + + * if $useAttachment is true, + * - $file is the directory where the file should be saved + * - if successful will return the name used for the saved file, false otherwise + * + * @author Andreas Gohr + * @author Chris Smith + */ +function io_download($url,$file,$useAttachment=false,$defaultName='',$maxSize=2097152){ + global $conf; + $http = new DokuHTTPClient(); + $http->max_bodysize = $maxSize; + $http->timeout = 25; //max. 25 sec + + $data = $http->get($url); + if(!$data) return false; + + if ($useAttachment) { + $name = ''; + if (isset($http->resp_headers['content-disposition'])) { + $content_disposition = $http->resp_headers['content-disposition']; + $match=array(); + if (is_string($content_disposition) && + preg_match('/attachment;\s*filename\s*=\s*"([^"]*)"/i', $content_disposition, $match)) { + + $name = basename($match[1]); + } + + } + + if (!$name) { + if (!$defaultName) return false; + $name = $defaultName; + } + + $file = $file.$name; + } + + $fileexists = @file_exists($file); + $fp = @fopen($file,"w"); + if(!$fp) return false; + fwrite($fp,$data); + fclose($fp); + if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']); + if ($useAttachment) return $name; + return true; +} + +/** + * Windows compatible rename + * + * rename() can not overwrite existing files on Windows + * this function will use copy/unlink instead + */ +function io_rename($from,$to){ + global $conf; + if(!@rename($from,$to)){ + if(@copy($from,$to)){ + if($conf['fperm']) chmod($to, $conf['fperm']); + @unlink($from); + return true; + } + return false; + } + return true; +} + + +/** + * Runs an external command and returns it's output as string + * + * @author Harry Brueckner + * @author Andreas Gohr + * @deprecated + */ +function io_runcmd($cmd){ + $fh = popen($cmd, "r"); + if(!$fh) return false; + $ret = ''; + while (!feof($fh)) { + $ret .= fread($fh, 8192); + } + pclose($fh); + return $ret; +} + +/** + * Search a file for matching lines + * + * This is probably not faster than file()+preg_grep() but less + * memory intensive because not the whole file needs to be loaded + * at once. + * + * @author Andreas Gohr + * @param string $file The file to search + * @param string $pattern PCRE pattern + * @param int $max How many lines to return (0 for all) + * @param bool $baxkref When true returns array with backreferences instead of lines + * @return matching lines or backref, false on error + */ +function io_grep($file,$pattern,$max=0,$backref=false){ + $fh = @fopen($file,'r'); + if(!$fh) return false; + $matches = array(); + + $cnt = 0; + $line = ''; + while (!feof($fh)) { + $line .= fgets($fh, 4096); // read full line + if(substr($line,-1) != "\n") continue; + + // check if line matches + if(preg_match($pattern,$line,$match)){ + if($backref){ + $matches[] = $match; + }else{ + $matches[] = $line; + } + $cnt++; + } + if($max && $max == $cnt) break; + $line = ''; + } + fclose($fh); + return $matches; +} + +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/pageutils.php b/plugins/dokuwiki/inc/pageutils.php new file mode 100644 index 0000000..f58e751 --- /dev/null +++ b/plugins/dokuwiki/inc/pageutils.php @@ -0,0 +1,478 @@ + + * @todo Combine similar functions like {wiki,media,meta}FN() + */ + +/** + * Fetch the an ID from request + * + * Uses either standard $_REQUEST variable or extracts it from + * the full request URI when userewrite is set to 2 + * + * For $param='id' $conf['start'] is returned if no id was found. + * If the second parameter is true (default) the ID is cleaned. + * + * @author Andreas Gohr + */ +function getID($param='id',$clean=true){ + global $conf; + + $id = isset($_REQUEST[$param]) ? $_REQUEST[$param] : null; + + //construct page id from request URI + if(empty($id) && $conf['userewrite'] == 2){ + //get the script URL + if($conf['basedir']){ + $relpath = ''; + if($param != 'id') { + $relpath = 'lib/exe/'; + } + $script = $conf['basedir'].$relpath.basename($_SERVER['SCRIPT_FILENAME']); + }elseif($_SERVER['DOCUMENT_ROOT'] && $_SERVER['SCRIPT_FILENAME']){ + $script = preg_replace ('/^'.preg_quote($_SERVER['DOCUMENT_ROOT'],'/').'/','', + $_SERVER['SCRIPT_FILENAME']); + $script = '/'.$script; + }else{ + $script = $_SERVER['SCRIPT_NAME']; + } + + //clean script and request (fixes a windows problem) + $script = preg_replace('/\/\/+/','/',$script); + $request = preg_replace('/\/\/+/','/',$_SERVER['REQUEST_URI']); + + //remove script URL and Querystring to gain the id + if(preg_match('/^'.preg_quote($script,'/').'(.*)/',$request, $match)){ + $id = preg_replace ('/\?.*/','',$match[1]); + } + $id = urldecode($id); + //strip leading slashes + $id = preg_replace('!^/+!','',$id); + } + if($clean) $id = cleanID($id); + if(empty($id) && $param=='id') $id = $conf['start']; + + return $id; +} + +/** + * Remove unwanted chars from ID + * + * Cleans a given ID to only use allowed characters. Accented characters are + * converted to unaccented ones + * + * @author Andreas Gohr + * @param string $raw_id The pageid to clean + * @param boolean $ascii Force ASCII + */ +function cleanID($raw_id,$ascii=false){ + global $conf; + global $lang; + static $sepcharpat = null; + + global $cache_cleanid; + $cache = & $cache_cleanid; + + // check if it's already in the memory cache + if (isset($cache[$raw_id])) { + return $cache[$raw_id]; + } + + $sepchar = $conf['sepchar']; + if($sepcharpat == null) // build string only once to save clock cycles + $sepcharpat = '#\\'.$sepchar.'+#'; + + $id = trim($raw_id); + $id = utf8_strtolower($id); + + //alternative namespace seperator + $id = strtr($id,';',':'); + if($conf['useslash']){ + $id = strtr($id,'/',':'); + }else{ + $id = strtr($id,'/',$sepchar); + } + + if($conf['deaccent'] == 2 || $ascii) $id = utf8_romanize($id); + if($conf['deaccent'] || $ascii) $id = utf8_deaccent($id,-1); + + //remove specials + $id = utf8_stripspecials($id,$sepchar,'\*'); + + if($ascii) $id = utf8_strip($id); + + //clean up + $id = preg_replace($sepcharpat,$sepchar,$id); + $id = preg_replace('#:+#',':',$id); + $id = trim($id,':._-'); + $id = preg_replace('#:[:\._\-]+#',':',$id); + + $cache[$raw_id] = $id; + return($id); +} + +/** + * Return namespacepart of a wiki ID + * + * @author Andreas Gohr + */ +function getNS($id){ + $pos = strrpos($id,':'); + if($pos!==false){ + return substr($id,0,$pos); + } + return false; +} + +/** + * Returns the ID without the namespace + * + * @author Andreas Gohr + */ +function noNS($id) { + $pos = strrpos($id, ':'); + if ($pos!==false) { + return substr($id, $pos+1); + } else { + return $id; + } +} + +/** + * returns the full path to the datafile specified by ID and + * optional revision + * + * The filename is URL encoded to protect Unicode chars + * + * @author Andreas Gohr + */ +function wikiFN($raw_id,$rev='',$clean=true){ + global $conf; + + global $cache_wikifn; + $cache = & $cache_wikifn; + + if (isset($cache[$raw_id]) && isset($cache[$raw_id][$rev])) { + return $cache[$raw_id][$rev]; + } + + $id = $raw_id; + + if ($clean) $id = cleanID($id); + $id = str_replace(':','/',$id); + if(empty($rev)){ + $fn = $conf['datadir'].'/'.utf8_encodeFN($id).'.txt'; + }else{ + $fn = $conf['olddir'].'/'.utf8_encodeFN($id).'.'.$rev.'.txt'; + if($conf['compression']){ + //test for extensions here, we want to read both compressions + if (@file_exists($fn . '.gz')){ + $fn .= '.gz'; + }else if(@file_exists($fn . '.bz2')){ + $fn .= '.bz2'; + }else{ + //file doesnt exist yet, so we take the configured extension + $fn .= '.' . $conf['compression']; + } + } + } + + if (!isset($cache[$raw_id])) { $cache[$raw_id] = array(); } + $cache[$raw_id][$rev] = $fn; + return $fn; +} + +/** + * Returns the full path to the file for locking the page while editing. + * + * @author Ben Coburn + */ +function wikiLockFN($id) { + global $conf; + return $conf['lockdir'].'/'.md5(cleanID($id)).'.lock'; +} + + +/** + * returns the full path to the meta file specified by ID and extension + * + * The filename is URL encoded to protect Unicode chars + * + * @author Steven Danz + */ +function metaFN($id,$ext){ + global $conf; + $id = cleanID($id); + $id = str_replace(':','/',$id); + $fn = $conf['metadir'].'/'.utf8_encodeFN($id).$ext; + return $fn; +} + +/** + * returns an array of full paths to all metafiles of a given ID + * + * @author Esther Brunner + */ +function metaFiles($id){ + $name = noNS($id); + $dir = metaFN(getNS($id),''); + $files = array(); + + $dh = @opendir($dir); + if(!$dh) return $files; + while(($file = readdir($dh)) !== false){ + if(strpos($file,$name.'.') === 0 && !is_dir($dir.$file)) + $files[] = $dir.$file; + } + closedir($dh); + + return $files; +} + +/** + * returns the full path to the mediafile specified by ID + * + * The filename is URL encoded to protect Unicode chars + * + * @author Andreas Gohr + */ +function mediaFN($id){ + global $conf; + $id = cleanID($id); + $id = str_replace(':','/',$id); + $fn = $conf['mediadir'].'/'.utf8_encodeFN($id); + return $fn; +} + +/** + * Returns the full filepath to a localized textfile if local + * version isn't found the english one is returned + * + * @author Andreas Gohr + */ +function localeFN($id){ + global $conf; + $file = DOKU_INC.'inc/lang/'.$conf['lang'].'/'.$id.'.txt'; + if(!@file_exists($file)){ + //fall back to english + $file = DOKU_INC.'inc/lang/en/'.$id.'.txt'; + } + return $file; +} + +/** + * Resolve relative paths in IDs + * + * Do not call directly use resolve_mediaid or resolve_pageid + * instead + * + * Partyly based on a cleanPath function found at + * http://www.php.net/manual/en/function.realpath.php#57016 + * + * @author + */ +function resolve_id($ns,$id,$clean=true){ + // if the id starts with a dot we need to handle the + // relative stuff + if($id{0} == '.'){ + // normalize initial dots without a colon + $id = preg_replace('/^(\.+)(?=[^:\.])/','\1:',$id); + // prepend the current namespace + $id = $ns.':'.$id; + + // cleanup relatives + $result = array(); + $pathA = explode(':', $id); + if (!$pathA[0]) $result[] = ''; + foreach ($pathA AS $key => $dir) { + if ($dir == '..') { + if (end($result) == '..') { + $result[] = '..'; + } elseif (!array_pop($result)) { + $result[] = '..'; + } + } elseif ($dir && $dir != '.') { + $result[] = $dir; + } + } + if (!end($pathA)) $result[] = ''; + $id = implode(':', $result); + }elseif($ns !== false && strpos($id,':') === false){ + //if link contains no namespace. add current namespace (if any) + $id = $ns.':'.$id; + } + + if($clean) $id = cleanID($id); + return $id; +} + +/** + * Returns a full media id + * + * @author Andreas Gohr + */ +function resolve_mediaid($ns,&$page,&$exists){ + $page = resolve_id($ns,$page); + $file = mediaFN($page); + $exists = @file_exists($file); +} + +/** + * Returns a full page id + * + * @author Andreas Gohr + */ +function resolve_pageid($ns,&$page,&$exists){ + global $conf; + $exists = false; + + //keep hashlink if exists then clean both parts + if (strpos($page,'#')) { + list($page,$hash) = explode('#',$page,2); + } else { + $hash = ''; + } + $hash = cleanID($hash); + $page = resolve_id($ns,$page,false); // resolve but don't clean, yet + + // get filename (calls clean itself) + $file = wikiFN($page); + + // if ends with colon we have a namespace link + if(substr($page,-1) == ':'){ + if(@file_exists(wikiFN($page.$conf['start']))){ + // start page inside namespace + $page = $page.$conf['start']; + $exists = true; + }elseif(@file_exists(wikiFN($page.noNS(cleanID($page))))){ + // page named like the NS inside the NS + $page = $page.noNS(cleanID($page)); + $exists = true; + }elseif(@file_exists(wikiFN($page))){ + // page like namespace exists + $page = $page; + $exists = true; + }else{ + // fall back to default + $page = $page.$conf['start']; + } + }else{ + //check alternative plural/nonplural form + if(!@file_exists($file)){ + if( $conf['autoplural'] ){ + if(substr($page,-1) == 's'){ + $try = substr($page,0,-1); + }else{ + $try = $page.'s'; + } + if(@file_exists(wikiFN($try))){ + $page = $try; + $exists = true; + } + } + }else{ + $exists = true; + } + } + + // now make sure we have a clean page + $page = cleanID($page); + + //add hash if any + if(!empty($hash)) $page .= '#'.$hash; +} + +/** + * Returns the name of a cachefile from given data + * + * The needed directory is created by this function! + * + * @author Andreas Gohr + * + * @param string $data This data is used to create a unique md5 name + * @param string $ext This is appended to the filename if given + * @return string The filename of the cachefile + */ +function getCacheName($data,$ext=''){ + global $conf; + $md5 = md5($data); + $file = $conf['cachedir'].'/'.$md5{0}.'/'.$md5.$ext; + io_makeFileDir($file); + return $file; +} + +/** + * Checks a pageid against $conf['hidepages'] + * + * @author Andreas Gohr + */ +function isHiddenPage($id){ + global $conf; + if(empty($conf['hidepages'])) return false; + + if(preg_match('/'.$conf['hidepages'].'/ui',':'.$id)){ + return true; + } + return false; +} + +/** + * Reverse of isHiddenPage + * + * @author Andreas Gohr + */ +function isVisiblePage($id){ + return !isHiddenPage($id); +} + +/** + * Checks and sets HTTP headers for conditional HTTP requests + * + * @author Simon Willison + * @link http://simon.incutio.com/archive/2003/04/23/conditionalGet + * @param timestamp $timestamp lastmodified time of the cache file + * @returns void or void with previously header() commands executed + */ +function http_conditionalRequest($timestamp){ + // A PHP implementation of conditional get, see + // http://fishbowl.pastiche.org/archives/001132.html + $last_modified = substr(date('r', $timestamp), 0, -5).'GMT'; + $etag = '"'.md5($last_modified).'"'; + // Send the headers + header("Last-Modified: $last_modified"); + header("ETag: $etag"); + // See if the client has provided the required headers + if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])){ + $if_modified_since = stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']); + }else{ + $if_modified_since = false; + } + + if (isset($_SERVER['HTTP_IF_NONE_MATCH'])){ + $if_none_match = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']); + }else{ + $if_none_match = false; + } + + if (!$if_modified_since && !$if_none_match){ + return; + } + + // At least one of the headers is there - check them + if ($if_none_match && $if_none_match != $etag) { + return; // etag is there but doesn't match + } + + if ($if_modified_since && $if_modified_since != $last_modified) { + return; // if-modified-since is there but doesn't match + } + + // Nothing has changed since their last request - serve a 304 and exit + header('HTTP/1.0 304 Not Modified'); + exit; +} + +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/parser/handler.php b/plugins/dokuwiki/inc/parser/handler.php new file mode 100644 index 0000000..bd307d6 --- /dev/null +++ b/plugins/dokuwiki/inc/parser/handler.php @@ -0,0 +1,1653 @@ + FALSE, + 'section_edit_start' => -1, + 'section_edit_level' => 1, + 'section_edit_title' => '' + ); + + var $rewriteBlocks = TRUE; + + function __construct() { + $this->CallWriter = new Doku_Handler_CallWriter($this); + } + + function _addCall($handler, $args, $pos) { + $call = array($handler,$args, $pos); + $this->CallWriter->writeCall($call); + } + + function _finalize(){ + + $this->CallWriter->finalise(); + + if ( $this->status['section'] ) { + $last_call = end($this->calls); + array_push($this->calls,array('section_close',array(), $last_call[2])); + if ($this->status['section_edit_start']>1) { + // ignore last edit section if there is only one header + array_push($this->calls,array('section_edit',array($this->status['section_edit_start'], 0, $this->status['section_edit_level'], $this->status['section_edit_title']), $last_call[2])); + } + } + + if ( $this->rewriteBlocks ) { + $B = new Doku_Handler_Block(); + $this->calls = $B->process($this->calls); + } + + trigger_event('PARSER_HANDLER_DONE',$this); + + array_unshift($this->calls,array('document_start',array(),0)); + $last_call = end($this->calls); + array_push($this->calls,array('document_end',array(),$last_call[2])); + } + + function fetch() { + $call = each($this->calls); + if ( $call ) { + return $call['value']; + } + return FALSE; + } + + + /** + * Special plugin handler + * + * This handler is called for all modes starting with 'plugin_'. + * An additional parameter with the plugin name is passed + * + * @author Andreas Gohr + */ + function plugin($match, $state, $pos, $pluginname){ + $data = array($match); + $plugin =& plugin_load('syntax',$pluginname); + if($plugin != null){ + $data = $plugin->handle($match, $state, $pos, $this); + } + $this->_addCall('plugin',array($pluginname,$data,$state),$pos); + return TRUE; + } + + function base($match, $state, $pos) { + switch ( $state ) { + case DOKU_LEXER_UNMATCHED: + $this->_addCall('cdata',array($match), $pos); + return TRUE; + break; + + } + } + + function header($match, $state, $pos) { + global $conf; + + // get level and title + $title = trim($match); + $level = 7 - strspn($title,'='); + if($level < 1) $level = 1; + $title = trim($title,'='); + $title = trim($title); + + if ($this->status['section']) $this->_addCall('section_close',array(),$pos); + + if ($level<=$conf['maxseclevel']) { + $this->_addCall('section_edit',array($this->status['section_edit_start'], $pos-1, $this->status['section_edit_level'], $this->status['section_edit_title']), $pos); + $this->status['section_edit_start'] = $pos; + $this->status['section_edit_level'] = $level; + $this->status['section_edit_title'] = $title; + } + + $this->_addCall('header',array($title,$level,$pos), $pos); + + $this->_addCall('section_open',array($level),$pos); + $this->status['section'] = TRUE; + return TRUE; + } + + function notoc($match, $state, $pos) { + $this->_addCall('notoc',array(),$pos); + return TRUE; + } + + function nocache($match, $state, $pos) { + $this->_addCall('nocache',array(),$pos); + return TRUE; + } + + function linebreak($match, $state, $pos) { + $this->_addCall('linebreak',array(),$pos); + return TRUE; + } + + function eol($match, $state, $pos) { + $this->_addCall('eol',array(),$pos); + return TRUE; + } + + function hr($match, $state, $pos) { + $this->_addCall('hr',array(),$pos); + return TRUE; + } + + function _nestingTag($match, $state, $pos, $name) { + switch ( $state ) { + case DOKU_LEXER_ENTER: + $this->_addCall($name.'_open', array(), $pos); + break; + case DOKU_LEXER_EXIT: + $this->_addCall($name.'_close', array(), $pos); + break; + case DOKU_LEXER_UNMATCHED: + $this->_addCall('cdata',array($match), $pos); + break; + } + } + + function strong($match, $state, $pos) { + $this->_nestingTag($match, $state, $pos, 'strong'); + return TRUE; + } + + function emphasis($match, $state, $pos) { + $this->_nestingTag($match, $state, $pos, 'emphasis'); + return TRUE; + } + + function underline($match, $state, $pos) { + $this->_nestingTag($match, $state, $pos, 'underline'); + return TRUE; + } + + function monospace($match, $state, $pos) { + $this->_nestingTag($match, $state, $pos, 'monospace'); + return TRUE; + } + + function subscript($match, $state, $pos) { + $this->_nestingTag($match, $state, $pos, 'subscript'); + return TRUE; + } + + function superscript($match, $state, $pos) { + $this->_nestingTag($match, $state, $pos, 'superscript'); + return TRUE; + } + + function deleted($match, $state, $pos) { + $this->_nestingTag($match, $state, $pos, 'deleted'); + return TRUE; + } + + + function footnote($match, $state, $pos) { +// $this->_nestingTag($match, $state, $pos, 'footnote'); + if (!isset($this->_footnote)) $this->_footnote = false; + + switch ( $state ) { + case DOKU_LEXER_ENTER: + // footnotes can not be nested - however due to limitations in lexer it can't be prevented + // we will still enter a new footnote mode, we just do nothing + if ($this->_footnote) { + $this->_addCall('cdata',array($match), $pos); + break; + } + + $this->_footnote = true; + + $ReWriter = new Doku_Handler_Nest($this->CallWriter,'footnote_close'); + $this->CallWriter = & $ReWriter; + $this->_addCall('footnote_open', array(), $pos); + break; + case DOKU_LEXER_EXIT: + // check whether we have already exitted the footnote mode, can happen if the modes were nested + if (!$this->_footnote) { + $this->_addCall('cdata',array($match), $pos); + break; + } + + $this->_footnote = false; + + $this->_addCall('footnote_close', array(), $pos); + $this->CallWriter->process(); + $ReWriter = & $this->CallWriter; + $this->CallWriter = & $ReWriter->CallWriter; + break; + case DOKU_LEXER_UNMATCHED: + $this->_addCall('cdata', array($match), $pos); + break; + } + return TRUE; + } + + function listblock($match, $state, $pos) { + switch ( $state ) { + case DOKU_LEXER_ENTER: + $ReWriter = new Doku_Handler_List($this->CallWriter); + $this->CallWriter = & $ReWriter; + $this->_addCall('list_open', array($match), $pos); + break; + case DOKU_LEXER_EXIT: + $this->_addCall('list_close', array(), $pos); + $this->CallWriter->process(); + $ReWriter = & $this->CallWriter; + $this->CallWriter = & $ReWriter->CallWriter; + break; + case DOKU_LEXER_MATCHED: + $this->_addCall('list_item', array($match), $pos); + break; + case DOKU_LEXER_UNMATCHED: + $this->_addCall('cdata', array($match), $pos); + break; + } + return TRUE; + } + + function unformatted($match, $state, $pos) { + if ( $state == DOKU_LEXER_UNMATCHED ) { + $this->_addCall('unformatted',array($match), $pos); + } + return TRUE; + } + + function php($match, $state, $pos) { + global $conf; + if ( $state == DOKU_LEXER_UNMATCHED ) { + if ($conf['phpok']) { + $this->_addCall('php',array($match), $pos); + } else { + $this->_addCall('file',array($match), $pos); + } + } + return TRUE; + } + + function html($match, $state, $pos) { + global $conf; + if ( $state == DOKU_LEXER_UNMATCHED ) { + if($conf['htmlok']){ + $this->_addCall('html',array($match), $pos); + } else { + $this->_addCall('file',array($match), $pos); + } + } + return TRUE; + } + + function preformatted($match, $state, $pos) { + switch ( $state ) { + case DOKU_LEXER_ENTER: + $ReWriter = new Doku_Handler_Preformatted($this->CallWriter); + $this->CallWriter = & $ReWriter; + $this->_addCall('preformatted_start',array(), $pos); + break; + case DOKU_LEXER_EXIT: + $this->_addCall('preformatted_end',array(), $pos); + $this->CallWriter->process(); + $ReWriter = & $this->CallWriter; + $this->CallWriter = & $ReWriter->CallWriter; + break; + case DOKU_LEXER_MATCHED: + $this->_addCall('preformatted_newline',array(), $pos); + break; + case DOKU_LEXER_UNMATCHED: + $this->_addCall('preformatted_content',array($match), $pos); + break; + } + + return TRUE; + } + + function file($match, $state, $pos) { + if ( $state == DOKU_LEXER_UNMATCHED ) { + $this->_addCall('file',array($match), $pos); + } + return TRUE; + } + + function quote($match, $state, $pos) { + + switch ( $state ) { + + case DOKU_LEXER_ENTER: + $ReWriter = new Doku_Handler_Quote($this->CallWriter); + $this->CallWriter = & $ReWriter; + $this->_addCall('quote_start',array($match), $pos); + break; + + case DOKU_LEXER_EXIT: + $this->_addCall('quote_end',array(), $pos); + $this->CallWriter->process(); + $ReWriter = & $this->CallWriter; + $this->CallWriter = & $ReWriter->CallWriter; + break; + + case DOKU_LEXER_MATCHED: + $this->_addCall('quote_newline',array($match), $pos); + break; + + case DOKU_LEXER_UNMATCHED: + $this->_addCall('cdata',array($match), $pos); + break; + + } + + return TRUE; + } + + function code($match, $state, $pos) { + switch ( $state ) { + case DOKU_LEXER_UNMATCHED: + $matches = preg_split('/>/u',$match,2); + $matches[0] = trim($matches[0]); + if ( trim($matches[0]) == '' ) { + $matches[0] = NULL; + } + # $matches[0] contains name of programming language + # if available, We shortcut html here. + if($matches[0] == 'html') $matches[0] = 'html4strict'; + $this->_addCall( + 'code', + array($matches[1],$matches[0]), + $pos + ); + break; + } + return TRUE; + } + + function acronym($match, $state, $pos) { + $this->_addCall('acronym',array($match), $pos); + return TRUE; + } + + function smiley($match, $state, $pos) { + $this->_addCall('smiley',array($match), $pos); + return TRUE; + } + + function wordblock($match, $state, $pos) { + $this->_addCall('wordblock',array($match), $pos); + return TRUE; + } + + function entity($match, $state, $pos) { + $this->_addCall('entity',array($match), $pos); + return TRUE; + } + + function multiplyentity($match, $state, $pos) { + preg_match_all('/\d+/',$match,$matches); + $this->_addCall('multiplyentity',array($matches[0][0],$matches[0][1]), $pos); + return TRUE; + } + + function singlequoteopening($match, $state, $pos) { + $this->_addCall('singlequoteopening',array(), $pos); + return TRUE; + } + + function singlequoteclosing($match, $state, $pos) { + $this->_addCall('singlequoteclosing',array(), $pos); + return TRUE; + } + + function doublequoteopening($match, $state, $pos) { + $this->_addCall('doublequoteopening',array(), $pos); + return TRUE; + } + + function doublequoteclosing($match, $state, $pos) { + $this->_addCall('doublequoteclosing',array(), $pos); + return TRUE; + } + + function camelcaselink($match, $state, $pos) { + $this->_addCall('camelcaselink',array($match), $pos); + return TRUE; + } + + /* + */ + function internallink($match, $state, $pos) { + // Strip the opening and closing markup + $link = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match); + + // Split title from URL + $link = preg_split('/\|/u',$link,2); + if ( !isset($link[1]) ) { + $link[1] = NULL; + } else if ( preg_match('/^\{\{[^\}]+\}\}$/',$link[1]) ) { + // If the title is an image, convert it to an array containing the image details + $link[1] = Doku_Handler_Parse_Media($link[1]); + } + $link[0] = trim($link[0]); + + //decide which kind of link it is + + if ( preg_match('/^[a-zA-Z\.]+>{1}.*$/u',$link[0]) ) { + // Interwiki + $interwiki = preg_split('/>/u',$link[0]); + $this->_addCall( + 'interwikilink', + array($link[0],$link[1],strtolower($interwiki[0]),$interwiki[1]), + $pos + ); + }elseif ( preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$link[0]) ) { + // Windows Share + $this->_addCall( + 'windowssharelink', + array($link[0],$link[1]), + $pos + ); + }elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$link[0]) ) { + // external link (accepts all protocols) + $this->_addCall( + 'externallink', + array($link[0],$link[1]), + $pos + ); + }elseif ( preg_match('#([a-z0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i',$link[0]) ) { + // E-Mail + $this->_addCall( + 'emaillink', + array($link[0],$link[1]), + $pos + ); + }elseif ( preg_match('!^#.+!',$link[0]) ){ + // local link + $this->_addCall( + 'locallink', + array(substr($link[0],1),$link[1]), + $pos + ); + }else{ + // internal link + $this->_addCall( + 'internallink', + array($link[0],$link[1]), + $pos + ); + } + + return TRUE; + } + + function filelink($match, $state, $pos) { + $this->_addCall('filelink',array($match, NULL), $pos); + return TRUE; + } + + function windowssharelink($match, $state, $pos) { + $this->_addCall('windowssharelink',array($match, NULL), $pos); + return TRUE; + } + + function media($match, $state, $pos) { + $p = Doku_Handler_Parse_Media($match); + + $this->_addCall( + $p['type'], + array($p['src'], $p['title'], $p['align'], $p['width'], + $p['height'], $p['cache'], $p['linking']), + $pos + ); + return TRUE; + } + + function rss($match, $state, $pos) { + $link = preg_replace(array('/^\{\{rss>/','/\}\}$/'),'',$match); + + // get params + list($link,$params) = explode(' ',$link,2); + + $p = array(); + if(preg_match('/\b(\d+)\b/',$params,$match)){ + $p['max'] = $match[1]; + }else{ + $p['max'] = 8; + } + $p['reverse'] = (preg_match('/rev/',$params)); + $p['author'] = (preg_match('/\b(by|author)/',$params)); + $p['date'] = (preg_match('/\b(date)/',$params)); + $p['details'] = (preg_match('/\b(desc|detail)/',$params)); + + if (preg_match('/\b(\d+)([dhm])\b/',$params,$match)) { + $period = array('d' => 86400, 'h' => 3600, 'm' => 60); + $p['refresh'] = max(600,$match[1]*$period[$match[2]]); // n * period in seconds, minimum 10 minutes + } else { + $p['refresh'] = 14400; // default to 4 hours + } + + $this->_addCall('rss',array($link,$p),$pos); + return TRUE; + } + + function externallink($match, $state, $pos) { + // Prevent use of multibyte strings in URLs + // See: http://www.boingboing.net/2005/02/06/shmoo_group_exploit_.html + // Not worried about other charsets so long as page is output as UTF-8 + /*if ( strlen($match) != utf8_strlen($match) ) { + $this->_addCall('cdata',array($match), $pos); + } else {*/ + + $this->_addCall('externallink',array($match, NULL), $pos); + //} + return TRUE; + } + + function emaillink($match, $state, $pos) { + $email = preg_replace(array('/^$/'),'',$match); + $this->_addCall('emaillink',array($email, NULL), $pos); + return TRUE; + } + + function table($match, $state, $pos) { + switch ( $state ) { + + case DOKU_LEXER_ENTER: + + $ReWriter = new Doku_Handler_Table($this->CallWriter); + $this->CallWriter = & $ReWriter; + + $this->_addCall('table_start', array(), $pos); + //$this->_addCall('table_row', array(), $pos); + if ( trim($match) == '^' ) { + $this->_addCall('tableheader', array(), $pos); + } else { + $this->_addCall('tablecell', array(), $pos); + } + break; + + case DOKU_LEXER_EXIT: + $this->_addCall('table_end', array(), $pos); + $this->CallWriter->process(); + $ReWriter = & $this->CallWriter; + $this->CallWriter = & $ReWriter->CallWriter; + break; + + case DOKU_LEXER_UNMATCHED: + if ( trim($match) != '' ) { + $this->_addCall('cdata',array($match), $pos); + } + break; + + case DOKU_LEXER_MATCHED: + if ( $match == ' ' ){ + $this->_addCall('cdata', array($match), $pos); + } else if ( preg_match('/\t+/',$match) ) { + $this->_addCall('table_align', array($match), $pos); + } else if ( preg_match('/ {2,}/',$match) ) { + $this->_addCall('table_align', array($match), $pos); + } else if ( $match == "\n|" ) { + $this->_addCall('table_row', array(), $pos); + $this->_addCall('tablecell', array(), $pos); + } else if ( $match == "\n^" ) { + $this->_addCall('table_row', array(), $pos); + $this->_addCall('tableheader', array(), $pos); + } else if ( $match == '|' ) { + $this->_addCall('tablecell', array(), $pos); + } else if ( $match == '^' ) { + $this->_addCall('tableheader', array(), $pos); + } + break; + } + return TRUE; + } +} + +//------------------------------------------------------------------------ +function Doku_Handler_Parse_Media($match) { + + // Strip the opening and closing markup + $link = preg_replace(array('/^\{\{/','/\}\}$/u'),'',$match); + + // Split title from URL + $link = preg_split('/\|/u',$link,2); + + + // Check alignment + $ralign = (bool)preg_match('/^ /',$link[0]); + $lalign = (bool)preg_match('/ $/',$link[0]); + + // Logic = what's that ;)... + if ( $lalign & $ralign ) { + $align = 'center'; + } else if ( $ralign ) { + $align = 'right'; + } else if ( $lalign ) { + $align = 'left'; + } else { + $align = NULL; + } + + // The title... + if ( !isset($link[1]) ) { + $link[1] = NULL; + } + + //remove aligning spaces + $link[0] = trim($link[0]); + + //split into src and parameters (using the very last questionmark) + $pos = strrpos($link[0], '?'); + if($pos !== false){ + $src = substr($link[0],0,$pos); + $param = substr($link[0],$pos+1); + }else{ + $src = $link[0]; + $param = ''; + } + + //parse width and height + if(preg_match('#(\d+)(x(\d+))?#i',$param,$size)){ + ($size[1]) ? $w = $size[1] : $w = NULL; + ($size[3]) ? $h = $size[3] : $h = NULL; + } else { + $w = NULL; + $h = NULL; + } + + //get linking command + if(preg_match('/nolink/i',$param)){ + $linking = 'nolink'; + }else if(preg_match('/direct/i',$param)){ + $linking = 'direct'; + }else{ + $linking = 'details'; + } + + //get caching command + if (preg_match('/(nocache|recache)/i',$param,$cachemode)){ + $cache = $cachemode[1]; + }else{ + $cache = 'cache'; + } + + // Check whether this is a local or remote image + if ( preg_match('#^(https?|ftp)#i',$src) ) { + $call = 'externalmedia'; + } else { + $call = 'internalmedia'; + } + + $params = array( + 'type'=>$call, + 'src'=>$src, + 'title'=>$link[1], + 'align'=>$align, + 'width'=>$w, + 'height'=>$h, + 'cache'=>$cache, + 'linking'=>$linking, + ); + + return $params; +} + +//------------------------------------------------------------------------ +class Doku_Handler_CallWriter { + + var $Handler; + + function __construct(& $Handler) { + $this->Handler = & $Handler; + } + + function writeCall($call) { + $this->Handler->calls[] = $call; + } + + function writeCalls($calls) { + $this->Handler->calls = array_merge($this->Handler->calls, $calls); + } + + // function is required, but since this call writer is first/highest in + // the chain it is not required to do anything + function finalise() { + } +} + +//------------------------------------------------------------------------ +/** + * Generic call writer class to handle nesting of rendering instructions + * within a render instruction. Also see nest() method of renderer base class + * + * @author Chris Smith + */ +class Doku_Handler_Nest { + + var $CallWriter; + var $calls = array(); + + var $closingInstruction; + + /** + * constructor + * + * @param object $CallWriter the renderers current call writer + * @param string $close closing instruction name, this is required to properly terminate the + * syntax mode if the document ends without a closing pattern + */ + function __construct(& $CallWriter, $close="nest_close") { + $this->CallWriter = & $CallWriter; + + $this->closingInstruction = $close; + } + + function writeCall($call) { + $this->calls[] = $call; + } + + function writeCalls($calls) { + $this->calls = array_merge($this->calls, $calls); + } + + function finalise() { + $last_call = end($this->calls); + $this->writeCall(array($this->closingInstruction,array(), $last_call[2])); + + $this->process(); + $this->CallWriter->finalise(); + } + + function process() { + $first_call = reset($this->calls); + $this->CallWriter->writeCall(array("nest", array($this->calls), $first_call[2])); + } +} + +class Doku_Handler_List { + + var $CallWriter; + + var $calls = array(); + var $listCalls = array(); + var $listStack = array(); + + function __construct(& $CallWriter) { + $this->CallWriter = & $CallWriter; + } + + function writeCall($call) { + $this->calls[] = $call; + } + + // Probably not needed but just in case... + function writeCalls($calls) { + $this->calls = array_merge($this->calls, $calls); +# $this->CallWriter->writeCalls($this->calls); + } + + function finalise() { + $last_call = end($this->calls); + $this->writeCall(array('list_close',array(), $last_call[2])); + + $this->process(); + $this->CallWriter->finalise(); + } + + //------------------------------------------------------------------------ + function process() { + + foreach ( $this->calls as $call ) { + switch ($call[0]) { + case 'list_item': + $this->listOpen($call); + break; + case 'list_open': + $this->listStart($call); + break; + case 'list_close': + $this->listEnd($call); + break; + default: + $this->listContent($call); + break; + } + } + + $this->CallWriter->writeCalls($this->listCalls); + } + + //------------------------------------------------------------------------ + function listStart($call) { + $depth = $this->interpretSyntax($call[1][0], $listType); + + $this->initialDepth = $depth; + $this->listStack[] = array($listType, $depth); + + $this->listCalls[] = array('list'.$listType.'_open',array(),$call[2]); + $this->listCalls[] = array('listitem_open',array(1),$call[2]); + $this->listCalls[] = array('listcontent_open',array(),$call[2]); + } + + //------------------------------------------------------------------------ + function listEnd($call) { + $closeContent = TRUE; + + while ( $list = array_pop($this->listStack) ) { + if ( $closeContent ) { + $this->listCalls[] = array('listcontent_close',array(),$call[2]); + $closeContent = FALSE; + } + $this->listCalls[] = array('listitem_close',array(),$call[2]); + $this->listCalls[] = array('list'.$list[0].'_close', array(), $call[2]); + } + } + + //------------------------------------------------------------------------ + function listOpen($call) { + $depth = $this->interpretSyntax($call[1][0], $listType); + $end = end($this->listStack); + + // Not allowed to be shallower than initialDepth + if ( $depth < $this->initialDepth ) { + $depth = $this->initialDepth; + } + + //------------------------------------------------------------------------ + if ( $depth == $end[1] ) { + + // Just another item in the list... + if ( $listType == $end[0] ) { + $this->listCalls[] = array('listcontent_close',array(),$call[2]); + $this->listCalls[] = array('listitem_close',array(),$call[2]); + $this->listCalls[] = array('listitem_open',array($depth-1),$call[2]); + $this->listCalls[] = array('listcontent_open',array(),$call[2]); + + // Switched list type... + } else { + + $this->listCalls[] = array('listcontent_close',array(),$call[2]); + $this->listCalls[] = array('listitem_close',array(),$call[2]); + $this->listCalls[] = array('list'.$end[0].'_close', array(), $call[2]); + $this->listCalls[] = array('list'.$listType.'_open', array(), $call[2]); + $this->listCalls[] = array('listitem_open', array($depth-1), $call[2]); + $this->listCalls[] = array('listcontent_open',array(),$call[2]); + + array_pop($this->listStack); + $this->listStack[] = array($listType, $depth); + } + + //------------------------------------------------------------------------ + // Getting deeper... + } else if ( $depth > $end[1] ) { + + $this->listCalls[] = array('listcontent_close',array(),$call[2]); + $this->listCalls[] = array('list'.$listType.'_open', array(), $call[2]); + $this->listCalls[] = array('listitem_open', array($depth-1), $call[2]); + $this->listCalls[] = array('listcontent_open',array(),$call[2]); + + $this->listStack[] = array($listType, $depth); + + //------------------------------------------------------------------------ + // Getting shallower ( $depth < $end[1] ) + } else { + $this->listCalls[] = array('listcontent_close',array(),$call[2]); + $this->listCalls[] = array('listitem_close',array(),$call[2]); + $this->listCalls[] = array('list'.$end[0].'_close',array(),$call[2]); + + // Throw away the end - done + array_pop($this->listStack); + + while (1) { + $end = end($this->listStack); + + if ( $end[1] <= $depth ) { + + // Normalize depths + $depth = $end[1]; + + $this->listCalls[] = array('listitem_close',array(),$call[2]); + + if ( $end[0] == $listType ) { + $this->listCalls[] = array('listitem_open',array($depth-1),$call[2]); + $this->listCalls[] = array('listcontent_open',array(),$call[2]); + + } else { + // Switching list type... + $this->listCalls[] = array('list'.$end[0].'_close', array(), $call[2]); + $this->listCalls[] = array('list'.$listType.'_open', array(), $call[2]); + $this->listCalls[] = array('listitem_open', array($depth-1), $call[2]); + $this->listCalls[] = array('listcontent_open',array(),$call[2]); + + array_pop($this->listStack); + $this->listStack[] = array($listType, $depth); + } + + break; + + // Haven't dropped down far enough yet.... ( $end[1] > $depth ) + } else { + + $this->listCalls[] = array('listitem_close',array(),$call[2]); + $this->listCalls[] = array('list'.$end[0].'_close',array(),$call[2]); + + array_pop($this->listStack); + + } + + } + + } + } + + //------------------------------------------------------------------------ + function listContent($call) { + $this->listCalls[] = $call; + } + + //------------------------------------------------------------------------ + function interpretSyntax($match, & $type) { + if ( substr($match,-1) == '*' ) { + $type = 'u'; + } else { + $type = 'o'; + } + return count(explode(' ',str_replace("\t",' ',$match))); + } +} + +//------------------------------------------------------------------------ +class Doku_Handler_Preformatted { + + var $CallWriter; + + var $calls = array(); + var $pos; + var $text =''; + + + + function __construct(& $CallWriter) { + $this->CallWriter = & $CallWriter; + } + + function writeCall($call) { + $this->calls[] = $call; + } + + // Probably not needed but just in case... + function writeCalls($calls) { + $this->calls = array_merge($this->calls, $calls); +# $this->CallWriter->writeCalls($this->calls); + } + + function finalise() { + $last_call = end($this->calls); + $this->writeCall(array('preformatted_end',array(), $last_call[2])); + + $this->process(); + $this->CallWriter->finalise(); + } + + function process() { + foreach ( $this->calls as $call ) { + switch ($call[0]) { + case 'preformatted_start': + $this->pos = $call[2]; + break; + case 'preformatted_newline': + $this->text .= "\n"; + break; + case 'preformatted_content': + $this->text .= $call[1][0]; + break; + case 'preformatted_end': + $this->CallWriter->writeCall(array('preformatted',array($this->text),$this->pos)); + break; + } + } + } + +} + +//------------------------------------------------------------------------ +class Doku_Handler_Quote { + + var $CallWriter; + + var $calls = array(); + + var $quoteCalls = array(); + + function __construct(& $CallWriter) { + $this->CallWriter = & $CallWriter; + } + + function writeCall($call) { + $this->calls[] = $call; + } + + // Probably not needed but just in case... + function writeCalls($calls) { + $this->calls = array_merge($this->calls, $calls); +# $this->CallWriter->writeCalls($this->calls); + } + + function finalise() { + $last_call = end($this->calls); + $this->writeCall(array('quote_end',array(), $last_call[2])); + + $this->process(); + $this->CallWriter->finalise(); + } + + function process() { + + $quoteDepth = 1; + + foreach ( $this->calls as $call ) { + switch ($call[0]) { + + case 'quote_start': + + $this->quoteCalls[] = array('quote_open',array(),$call[2]); + + case 'quote_newline': + + $quoteLength = $this->getDepth($call[1][0]); + + if ( $quoteLength > $quoteDepth ) { + $quoteDiff = $quoteLength - $quoteDepth; + for ( $i = 1; $i <= $quoteDiff; $i++ ) { + $this->quoteCalls[] = array('quote_open',array(),$call[2]); + } + } else if ( $quoteLength < $quoteDepth ) { + $quoteDiff = $quoteDepth - $quoteLength; + for ( $i = 1; $i <= $quoteDiff; $i++ ) { + $this->quoteCalls[] = array('quote_close',array(),$call[2]); + } + } else { + if ($call[0] != 'quote_start') $this->quoteCalls[] = array('linebreak',array(),$call[2]); + } + + $quoteDepth = $quoteLength; + + break; + + case 'quote_end': + + if ( $quoteDepth > 1 ) { + $quoteDiff = $quoteDepth - 1; + for ( $i = 1; $i <= $quoteDiff; $i++ ) { + $this->quoteCalls[] = array('quote_close',array(),$call[2]); + } + } + + $this->quoteCalls[] = array('quote_close',array(),$call[2]); + + $this->CallWriter->writeCalls($this->quoteCalls); + break; + + default: + $this->quoteCalls[] = $call; + break; + } + } + } + + function getDepth($marker) { + preg_match('/>{1,}/', $marker, $matches); + $quoteLength = strlen($matches[0]); + return $quoteLength; + } +} + +//------------------------------------------------------------------------ +class Doku_Handler_Table { + + var $CallWriter; + + var $calls = array(); + var $tableCalls = array(); + var $maxCols = 0; + var $maxRows = 1; + var $currentCols = 0; + var $firstCell = FALSE; + var $lastCellType = 'tablecell'; + + function __construct(& $CallWriter) { + $this->CallWriter = & $CallWriter; + } + + function writeCall($call) { + $this->calls[] = $call; + } + + // Probably not needed but just in case... + function writeCalls($calls) { + $this->calls = array_merge($this->calls, $calls); +# $this->CallWriter->writeCalls($this->calls); + } + + function finalise() { + $last_call = end($this->calls); + $this->writeCall(array('table_end',array(), $last_call[2])); + + $this->process(); + $this->CallWriter->finalise(); + } + + //------------------------------------------------------------------------ + function process() { + foreach ( $this->calls as $call ) { + switch ( $call[0] ) { + case 'table_start': + $this->tableStart($call); + break; + case 'table_row': + $this->tableRowClose(array('tablerow_close',$call[1],$call[2])); + $this->tableRowOpen(array('tablerow_open',$call[1],$call[2])); + break; + case 'tableheader': + case 'tablecell': + $this->tableCell($call); + break; + case 'table_end': + $this->tableRowClose(array('tablerow_close',$call[1],$call[2])); + $this->tableEnd($call); + break; + default: + $this->tableDefault($call); + break; + } + } + $this->CallWriter->writeCalls($this->tableCalls); + } + + function tableStart($call) { + $this->tableCalls[] = array('table_open',array(),$call[2]); + $this->tableCalls[] = array('tablerow_open',array(),$call[2]); + $this->firstCell = TRUE; + } + + function tableEnd($call) { + $this->tableCalls[] = array('table_close',array(),$call[2]); + $this->finalizeTable(); + } + + function tableRowOpen($call) { + $this->tableCalls[] = $call; + $this->currentCols = 0; + $this->firstCell = TRUE; + $this->lastCellType = 'tablecell'; + $this->maxRows++; + } + + function tableRowClose($call) { + // Strip off final cell opening and anything after it + while ( $discard = array_pop($this->tableCalls ) ) { + + if ( $discard[0] == 'tablecell_open' || $discard[0] == 'tableheader_open') { + + // Its a spanning element - put it back and close it + if ( $discard[1][0] > 1 ) { + + $this->tableCalls[] = $discard; + if ( strstr($discard[0],'cell') ) { + $name = 'tablecell'; + } else { + $name = 'tableheader'; + } + $this->tableCalls[] = array($name.'_close',array(),$call[2]); + } + + break; + } + } + $this->tableCalls[] = $call; + + if ( $this->currentCols > $this->maxCols ) { + $this->maxCols = $this->currentCols; + } + } + + function tableCell($call) { + if ( !$this->firstCell ) { + + // Increase the span + $lastCall = end($this->tableCalls); + + // A cell call which follows an open cell means an empty cell so span + if ( $lastCall[0] == 'tablecell_open' || $lastCall[0] == 'tableheader_open' ) { + $this->tableCalls[] = array('colspan',array(),$call[2]); + + } + + $this->tableCalls[] = array($this->lastCellType.'_close',array(),$call[2]); + $this->tableCalls[] = array($call[0].'_open',array(1,NULL),$call[2]); + $this->lastCellType = $call[0]; + + } else { + + $this->tableCalls[] = array($call[0].'_open',array(1,NULL),$call[2]); + $this->lastCellType = $call[0]; + $this->firstCell = FALSE; + + } + + $this->currentCols++; + } + + function tableDefault($call) { + $this->tableCalls[] = $call; + } + + function finalizeTable() { + + // Add the max cols and rows to the table opening + if ( $this->tableCalls[0][0] == 'table_open' ) { + // Adjust to num cols not num col delimeters + $this->tableCalls[0][1][] = $this->maxCols - 1; + $this->tableCalls[0][1][] = $this->maxRows; + } else { + trigger_error('First element in table call list is not table_open'); + } + + $lastRow = 0; + $lastCell = 0; + $toDelete = array(); + + // Look for the colspan elements and increment the colspan on the + // previous non-empty opening cell. Once done, delete all the cells + // that contain colspans + foreach ( $this->tableCalls as $key => $call ) { + + if ( $call[0] == 'tablerow_open' ) { + + $lastRow = $key; + + } else if ( $call[0] == 'tablecell_open' || $call[0] == 'tableheader_open' ) { + + $lastCell = $key; + + } else if ( $call[0] == 'table_align' ) { + + // If the previous element was a cell open, align right + if ( $this->tableCalls[$key-1][0] == 'tablecell_open' || $this->tableCalls[$key-1][0] == 'tableheader_open' ) { + $this->tableCalls[$key-1][1][1] = 'right'; + + // If the next element if the close of an element, align either center or left + } else if ( $this->tableCalls[$key+1][0] == 'tablecell_close' || $this->tableCalls[$key+1][0] == 'tableheader_close' ) { + if ( $this->tableCalls[$lastCell][1][1] == 'right' ) { + $this->tableCalls[$lastCell][1][1] = 'center'; + } else { + $this->tableCalls[$lastCell][1][1] = 'left'; + } + + } + + // Now convert the whitespace back to cdata + $this->tableCalls[$key][0] = 'cdata'; + + } else if ( $call[0] == 'colspan' ) { + + $this->tableCalls[$key-1][1][0] = FALSE; + + for($i = $key-2; $i > $lastRow; $i--) { + + if ( $this->tableCalls[$i][0] == 'tablecell_open' || $this->tableCalls[$i][0] == 'tableheader_open' ) { + + if ( FALSE !== $this->tableCalls[$i][1][0] ) { + $this->tableCalls[$i][1][0]++; + break; + } + + + } + } + + $toDelete[] = $key-1; + $toDelete[] = $key; + $toDelete[] = $key+1; + } + } + + + // condense cdata + $cnt = count($this->tableCalls); + for( $key = 0; $key < $cnt; $key++){ + if($this->tableCalls[$key][0] == 'cdata'){ + $ckey = $key; + $key++; + while($this->tableCalls[$key][0] == 'cdata'){ + $this->tableCalls[$ckey][1][0] .= $this->tableCalls[$key][1][0]; + $toDelete[] = $key; + $key++; + } + continue; + } + } + + foreach ( $toDelete as $delete ) { + unset($this->tableCalls[$delete]); + } + $this->tableCalls = array_values($this->tableCalls); + } +} + +//------------------------------------------------------------------------ +class Doku_Handler_Section { + + function process($calls) { + + $sectionCalls = array(); + $inSection = FALSE; + + foreach ( $calls as $call ) { + + if ( $call[0] == 'header' ) { + + if ( $inSection ) { + $sectionCalls[] = array('section_close',array(), $call[2]); + } + + $sectionCalls[] = $call; + $sectionCalls[] = array('section_open',array($call[1][1]), $call[2]); + $inSection = TRUE; + + } else { + + if ($call[0] == 'section_open' ) { + $inSection = TRUE; + } else if ($call[0] == 'section_open' ) { + $inSection = FALSE; + } + $sectionCalls[] = $call; + } + } + + if ( $inSection ) { + $sectionCalls[] = array('section_close',array(), $call[2]); + } + + return $sectionCalls; + } + +} + +/** + * Handler for paragraphs + * + * @author Harry Fuecks + */ +class Doku_Handler_Block { + + var $calls = array(); + + var $blockStack = array(); + + var $inParagraph = FALSE; + var $atStart = TRUE; + var $skipEolKey = -1; + + // Blocks these should not be inside paragraphs + var $blockOpen = array( + 'header', + 'listu_open','listo_open','listitem_open','listcontent_open', + 'table_open','tablerow_open','tablecell_open','tableheader_open', + 'quote_open', + 'section_open', // Needed to prevent p_open between header and section_open + 'code','file','hr','preformatted','rss', + ); + + var $blockClose = array( + 'header', + 'listu_close','listo_close','listitem_close','listcontent_close', + 'table_close','tablerow_close','tablecell_close','tableheader_close', + 'quote_close', + 'section_close', // Needed to prevent p_close after section_close + 'code','file','hr','preformatted','rss', + ); + + // Stacks can contain paragraphs + var $stackOpen = array( + 'footnote_open','section_open', + ); + + var $stackClose = array( + 'footnote_close','section_close', + ); + + + /** + * Constructor. Adds loaded syntax plugins to the block and stack + * arrays + * + * @author Andreas Gohr + */ + function __construct(){ + global $DOKU_PLUGINS; + //check if syntax plugins were loaded + if(empty($DOKU_PLUGINS['syntax'])) return; + foreach($DOKU_PLUGINS['syntax'] as $n => $p){ + $ptype = $p->getPType(); + if($ptype == 'block'){ + $this->blockOpen[] = 'plugin_'.$n; + $this->blockClose[] = 'plugin_'.$n; + }elseif($ptype == 'stack'){ + $this->stackOpen[] = 'plugin_'.$n; + $this->stackClose[] = 'plugin_'.$n; + } + } + } + + /** + * Close a paragraph if needed + * + * This function makes sure there are no empty paragraphs on the stack + * + * @author Andreas Gohr + */ + function closeParagraph($pos){ + // look back if there was any content - we don't want empty paragraphs + $content = ''; + for($i=count($this->calls)-1; $i>=0; $i--){ + if($this->calls[$i][0] == 'p_open'){ + break; + }elseif($this->calls[$i][0] == 'cdata'){ + $content .= $this->calls[$i][1][0]; + }else{ + $content = 'found markup'; + break; + } + } + + if(trim($content)==''){ + //remove the whole paragraph + array_splice($this->calls,$i); + }else{ + if ($this->calls[count($this->calls)-1][0] == 'section_edit') { + $tmp = array_pop($this->calls); + $this->calls[] = array('p_close',array(), $pos); + $this->calls[] = $tmp; + } else { + $this->calls[] = array('p_close',array(), $pos); + } + } + + $this->inParagraph = FALSE; + } + + /** + * Processes the whole instruction stack to open and close paragraphs + * + * @author Harry Fuecks + * @author Andreas Gohr + * @todo This thing is really messy and should be rewritten + */ + function process($calls) { + foreach ( $calls as $key => $call ) { + $cname = $call[0]; + if($cname == 'plugin') { + $cname='plugin_'.$call[1][0]; + + $plugin = true; + $plugin_open = (($call[1][2] == DOKU_LEXER_ENTER) || ($call[1][2] == DOKU_LEXER_SPECIAL)); + $plugin_close = (($call[1][2] == DOKU_LEXER_EXIT) || ($call[1][2] == DOKU_LEXER_SPECIAL)); + } else { + $plugin = false; + } + + // Process blocks which are stack like... (contain linefeeds) + if ( in_array($cname,$this->stackOpen ) && (!$plugin || $plugin_open) ) { + + $this->calls[] = $call; + + // Hack - footnotes shouldn't immediately contain a p_open + if ( $cname != 'footnote_open' ) { + $this->addToStack(); + } else { + $this->addToStack(FALSE); + } + continue; + } + + if ( in_array($cname,$this->stackClose ) && (!$plugin || $plugin_close)) { + + if ( $this->inParagraph ) { + $this->closeParagraph($call[2]); + } + $this->calls[] = $call; + $this->removeFromStack(); + continue; + } + + if ( !$this->atStart ) { + + if ( $cname == 'eol' ) { + + // Check this isn't an eol instruction to skip... + if ( $this->skipEolKey != $key ) { + // Look to see if the next instruction is an EOL + if ( isset($calls[$key+1]) && $calls[$key+1][0] == 'eol' ) { + + if ( $this->inParagraph ) { + //$this->calls[] = array('p_close',array(), $call[2]); + $this->closeParagraph($call[2]); + } + + $this->calls[] = array('p_open',array(), $call[2]); + $this->inParagraph = TRUE; + + + // Mark the next instruction for skipping + $this->skipEolKey = $key+1; + + }else{ + //if this is just a single eol make a space from it + $this->calls[] = array('cdata',array(" "), $call[2]); + } + } + + + } else { + + $storeCall = TRUE; + if ( $this->inParagraph && (in_array($cname, $this->blockOpen) && (!$plugin || $plugin_open))) { + $this->closeParagraph($call[2]); + $this->calls[] = $call; + $storeCall = FALSE; + } + + if ( in_array($cname, $this->blockClose) && (!$plugin || $plugin_close)) { + if ( $this->inParagraph ) { + $this->closeParagraph($call[2]); + } + if ( $storeCall ) { + $this->calls[] = $call; + $storeCall = FALSE; + } + + // This really sucks and suggests this whole class sucks but... + if ( isset($calls[$key+1])) { + $cname_plusone = $calls[$key+1][0]; + if ($cname_plusone == 'plugin') { + $cname_plusone = 'plugin'.$calls[$key+1][1][0]; + + // plugin test, true if plugin has a state which precludes it requiring blockOpen or blockClose + $plugin_plusone = true; + $plugin_test = ($call[$key+1][1][2] == DOKU_LEXER_MATCHED) || ($call[$key+1][1][2] == DOKU_LEXER_MATCHED); + } else { + $plugin_plusone = false; + } + if ((!in_array($cname_plusone, $this->blockOpen) && !in_array($cname_plusone, $this->blockClose)) || + ($plugin_plusone && $plugin_test) + ) { + + $this->calls[] = array('p_open',array(), $call[2]); + $this->inParagraph = TRUE; + } + } + } + + if ( $storeCall ) { + $this->calls[] = $call; + } + + } + + + } else { + + // Unless there's already a block at the start, start a paragraph + if ( !in_array($cname,$this->blockOpen) ) { + $this->calls[] = array('p_open',array(), $call[2]); + if ( $call[0] != 'eol' ) { + $this->calls[] = $call; + } + $this->atStart = FALSE; + $this->inParagraph = TRUE; + } else { + $this->calls[] = $call; + $this->atStart = FALSE; + } + + } + + } + + if ( $this->inParagraph ) { + if ( $cname == 'p_open' ) { + // Ditch the last call + array_pop($this->calls); + } else if ( !in_array($cname, $this->blockClose) ) { + //$this->calls[] = array('p_close',array(), $call[2]); + $this->closeParagraph($call[2]); + } else { + $last_call = array_pop($this->calls); + //$this->calls[] = array('p_close',array(), $call[2]); + $this->closeParagraph($call[2]); + $this->calls[] = $last_call; + } + } + + return $this->calls; + } + + function addToStack($newStart = TRUE) { + $this->blockStack[] = array($this->atStart, $this->inParagraph); + $this->atStart = $newStart; + $this->inParagraph = FALSE; + } + + function removeFromStack() { + $state = array_pop($this->blockStack); + $this->atStart = $state[0]; + $this->inParagraph = $state[1]; + } +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/parser/lexer.php b/plugins/dokuwiki/inc/parser/lexer.php new file mode 100644 index 0000000..249048f --- /dev/null +++ b/plugins/dokuwiki/inc/parser/lexer.php @@ -0,0 +1,607 @@ +_case = $case; + $this->_patterns = array(); + $this->_labels = array(); + $this->_regex = null; + } + + /** + * Adds a pattern with an optional label. + * @param mixed $pattern Perl style regex. Must be UTF-8 + * encoded. If its a string, the (, ) + * lose their meaning unless they + * form part of a lookahead or + * lookbehind assertation. + * @param string $label Label of regex to be returned + * on a match. Label must be ASCII + * @access public + */ + function addPattern($pattern, $label = true) { + $duplicate = false; + // Nux: check if not duplicate + // Note! This prevents regexp overflow when viewing Flyspray issues with many comments + if (in_array($pattern, $this->_patterns)) { + $index = array_search($pattern, $this->_patterns, true); + // label also have to be the same + if (isset($this->_labels[$index]) && $this->_labels[$index] === $label) { + $duplicate = true; + } + } + // only add new pattern if not duplicate... + if (!$duplicate) { + $count = count($this->_patterns); + $this->_patterns[$count] = $pattern; + $this->_labels[$count] = $label; + } + $this->_regex = null; + } + + /** + * Attempts to match all patterns at once against + * a string. + * @param string $subject String to match against. + * @param string $match First matched portion of + * subject. + * @return boolean True on success. + * @access public + */ + function match($subject, &$match) { + if (count($this->_patterns) == 0) { + return false; + } + if (! preg_match($this->_getCompoundedRegex(), $subject, $matches)) { + $match = ""; + return false; + } + + $match = $matches[0]; + $size = count($matches); + for ($i = 1; $i < $size; $i++) { + if ($matches[$i] && isset($this->_labels[$i - 1])) { + return $this->_labels[$i - 1]; + } + } + return true; + } + + /** + * Attempts to split the string against all patterns at once + * + * @param string $subject String to match against. + * @param array $split The split result: array containing, pre-match, match & post-match strings + * @return boolean True on success. + * @access public + * + * @author Christopher Smith + */ + function explode($subject, &$split) { + if (count($this->_patterns) == 0) { + return false; + } + + if (! preg_match($this->_getCompoundedRegex(), $subject, $matches)) { + $split = array($subject, "", ""); + return false; + } + + $idx = count($matches)-2; + + list($pre, $post) = preg_split($this->_patterns[$idx].$this->_getPerlMatchingFlags(), $subject, 2); + + $split = array($pre, $matches[0], $post); + return isset($this->_labels[$idx]) ? $this->_labels[$idx] : true; + } + + /** + * Compounds the patterns into a single + * regular expression separated with the + * "or" operator. Caches the regex. + * Will automatically escape (, ) and / tokens. + * @param array $patterns List of patterns in order. + * @access private + */ + function _getCompoundedRegex() { + if ($this->_regex == null) { + $cnt = count($this->_patterns); + for ($i = 0; $i < $cnt; $i++) { + + // Replace lookaheads / lookbehinds with marker + $m = "\1\1"; + $pattern = preg_replace( + array ( + '/\(\?(i|m|s|x|U)\)/U', + '/\(\?(\-[i|m|s|x|U])\)/U', + '/\(\?\=(.*)\)/sU', + '/\(\?\!(.*)\)/sU', + '/\(\?\<\=(.*)\)/sU', + '/\(\?\<\!(.*)\)/sU', + '/\(\?\:(.*)\)/sU', + ), + array ( + $m.'SO:\\1'.$m, + $m.'SOR:\\1'.$m, + $m.'LA:IS:\\1'.$m, + $m.'LA:NOT:\\1'.$m, + $m.'LB:IS:\\1'.$m, + $m.'LB:NOT:\\1'.$m, + $m.'GRP:\\1'.$m, + ), + $this->_patterns[$i] + ); + // Quote the rest + $pattern = str_replace( + array('/', '(', ')'), + array('\/', '\(', '\)'), + $pattern + ); + + // Restore lookaheads / lookbehinds + $pattern = preg_replace( + array ( + '/'.$m.'SO:(.{1})'.$m.'/', + '/'.$m.'SOR:(.{2})'.$m.'/', + '/'.$m.'LA:IS:(.*)'.$m.'/sU', + '/'.$m.'LA:NOT:(.*)'.$m.'/sU', + '/'.$m.'LB:IS:(.*)'.$m.'/sU', + '/'.$m.'LB:NOT:(.*)'.$m.'/sU', + '/'.$m.'GRP:(.*)'.$m.'/sU', + ), + array ( + '(?\\1)', + '(?\\1)', + '(?=\\1)', + '(?!\\1)', + '(?<=\\1)', + '(?_patterns[$i] = '('.$pattern.')'; + } + $this->_regex = "/" . implode("|", $this->_patterns) . "/" . $this->_getPerlMatchingFlags(); + } + return $this->_regex; + } + + /** + * Accessor for perl regex mode flags to use. + * @return string Perl regex flags. + * @access private + */ + function _getPerlMatchingFlags() { + return ($this->_case ? "msS" : "msSi"); + } +} + +/** + * States for a stack machine. + * @package Lexer + * @subpackage Lexer + */ +class Doku_LexerStateStack { + var $_stack; + + /** + * Constructor. Starts in named state. + * @param string $start Starting state name. + * @access public + */ + function __construct($start) { + $this->_stack = array($start); + } + + /** + * Accessor for current state. + * @return string State. + * @access public + */ + function getCurrent() { + return $this->_stack[count($this->_stack) - 1]; + } + + /** + * Adds a state to the stack and sets it + * to be the current state. + * @param string $state New state. + * @access public + */ + function enter($state) { + array_push($this->_stack, $state); + } + + /** + * Leaves the current state and reverts + * to the previous one. + * @return boolean False if we drop off + * the bottom of the list. + * @access public + */ + function leave() { + if (count($this->_stack) == 1) { + return false; + } + array_pop($this->_stack); + return true; + } +} + +/** + * Accepts text and breaks it into tokens. + * Some optimisation to make the sure the + * content is only scanned by the PHP regex + * parser once. Lexer modes must not start + * with leading underscores. + * @package Doku + * @subpackage Lexer + */ +class Doku_Lexer { + var $_regexes; + var $_parser; + var $_mode; + var $_mode_handlers; + var $_case; + + /** + * Sets up the lexer in case insensitive matching + * by default. + * @param Doku_Parser $parser Handling strategy by + * reference. + * @param string $start Starting handler. + * @param boolean $case True for case sensitive. + * @access public + */ + function __construct(&$parser, $start = "accept", $case = false) { + $this->_case = $case; + $this->_regexes = array(); + $this->_parser = &$parser; + $this->_mode = new Doku_LexerStateStack($start); + $this->_mode_handlers = array(); + } + + /** + * Adds a token search pattern for a particular + * parsing mode. The pattern does not change the + * current mode. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @access public + */ + function addPattern($pattern, $mode = "accept") { + if (! isset($this->_regexes[$mode])) { + $this->_regexes[$mode] = new Doku_LexerParallelRegex($this->_case); + } + $this->_regexes[$mode]->addPattern($pattern); + } + + /** + * Adds a pattern that will enter a new parsing + * mode. Useful for entering parenthesis, strings, + * tags, etc. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @param string $new_mode Change parsing to this new + * nested mode. + * @access public + */ + function addEntryPattern($pattern, $mode, $new_mode) { + if (! isset($this->_regexes[$mode])) { + $this->_regexes[$mode] = new Doku_LexerParallelRegex($this->_case); + } + $this->_regexes[$mode]->addPattern($pattern, $new_mode); + } + + /** + * Adds a pattern that will exit the current mode + * and re-enter the previous one. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Mode to leave. + * @access public + */ + function addExitPattern($pattern, $mode) { + if (! isset($this->_regexes[$mode])) { + $this->_regexes[$mode] = new Doku_LexerParallelRegex($this->_case); + } + $this->_regexes[$mode]->addPattern($pattern, "__exit"); + } + + /** + * Adds a pattern that has a special mode. Acts as an entry + * and exit pattern in one go, effectively calling a special + * parser handler for this token only. + * @param string $pattern Perl style regex, but ( and ) + * lose the usual meaning. + * @param string $mode Should only apply this + * pattern when dealing with + * this type of input. + * @param string $special Use this mode for this one token. + * @access public + */ + function addSpecialPattern($pattern, $mode, $special) { + if (! isset($this->_regexes[$mode])) { + $this->_regexes[$mode] = new Doku_LexerParallelRegex($this->_case); + } + $this->_regexes[$mode]->addPattern($pattern, "_$special"); + } + + /** + * Adds a mapping from a mode to another handler. + * @param string $mode Mode to be remapped. + * @param string $handler New target handler. + * @access public + */ + function mapHandler($mode, $handler) { + $this->_mode_handlers[$mode] = $handler; + } + + /** + * Splits the page text into tokens. Will fail + * if the handlers report an error or if no + * content is consumed. If successful then each + * unparsed and parsed token invokes a call to the + * held listener. + * @param string $raw Raw HTML text. + * @return boolean True on success, else false. + * @access public + */ + function parse($raw) { + if (! isset($this->_parser)) { + return false; + } + $initialLength = strlen($raw); + $length = $initialLength; + $pos = 0; + while (is_array($parsed = $this->_reduce($raw))) { + list($unmatched, $matched, $mode) = $parsed; + $currentLength = strlen($raw); + $matchPos = $initialLength - $currentLength - strlen($matched); + if (! $this->_dispatchTokens($unmatched, $matched, $mode, $pos, $matchPos)) { + return false; + } + if ($currentLength == $length) { + return false; + } + $length = $currentLength; + $pos = $initialLength - $currentLength; + } + if (!$parsed) { + return false; + } + return $this->_invokeParser($raw, DOKU_LEXER_UNMATCHED, $pos); + } + + /** + * Sends the matched token and any leading unmatched + * text to the parser changing the lexer to a new + * mode if one is listed. + * @param string $unmatched Unmatched leading portion. + * @param string $matched Actual token match. + * @param string $mode Mode after match. A boolean + * false mode causes no change. + * @param int $pos Current byte index location in raw doc + * thats being parsed + * @return boolean False if there was any error + * from the parser. + * @access private + */ + function _dispatchTokens($unmatched, $matched, $mode = false, $initialPos, $matchPos) { + if (! $this->_invokeParser($unmatched, DOKU_LEXER_UNMATCHED, $initialPos) ){ + return false; + } + if ($this->_isModeEnd($mode)) { + if (! $this->_invokeParser($matched, DOKU_LEXER_EXIT, $matchPos)) { + return false; + } + return $this->_mode->leave(); + } + if ($this->_isSpecialMode($mode)) { + $this->_mode->enter($this->_decodeSpecial($mode)); + if (! $this->_invokeParser($matched, DOKU_LEXER_SPECIAL, $matchPos)) { + return false; + } + return $this->_mode->leave(); + } + if (is_string($mode)) { + $this->_mode->enter($mode); + return $this->_invokeParser($matched, DOKU_LEXER_ENTER, $matchPos); + } + return $this->_invokeParser($matched, DOKU_LEXER_MATCHED, $matchPos); + } + + /** + * Tests to see if the new mode is actually to leave + * the current mode and pop an item from the matching + * mode stack. + * @param string $mode Mode to test. + * @return boolean True if this is the exit mode. + * @access private + */ + function _isModeEnd($mode) { + return ($mode === "__exit"); + } + + /** + * Test to see if the mode is one where this mode + * is entered for this token only and automatically + * leaves immediately afterwoods. + * @param string $mode Mode to test. + * @return boolean True if this is the exit mode. + * @access private + */ + function _isSpecialMode($mode) { + return (strncmp($mode, "_", 1) == 0); + } + + /** + * Strips the magic underscore marking single token + * modes. + * @param string $mode Mode to decode. + * @return string Underlying mode name. + * @access private + */ + function _decodeSpecial($mode) { + return substr($mode, 1); + } + + /** + * Calls the parser method named after the current + * mode. Empty content will be ignored. The lexer + * has a parser handler for each mode in the lexer. + * @param string $content Text parsed. + * @param boolean $is_match Token is recognised rather + * than unparsed data. + * @param int $pos Current byte index location in raw doc + * thats being parsed + * @access private + */ + function _invokeParser($content, $is_match, $pos) { + if (($content === "") || ($content === false)) { + return true; + } + $handler = $this->_mode->getCurrent(); + if (isset($this->_mode_handlers[$handler])) { + $handler = $this->_mode_handlers[$handler]; + } + + // modes starting with plugin_ are all handled by the same + // handler but with an additional parameter + if(substr($handler,0,7)=='plugin_'){ + list($handler,$plugin) = explode('_',$handler,2); + return $this->_parser->$handler($content, $is_match, $pos, $plugin); + } + + return $this->_parser->$handler($content, $is_match, $pos); + } + + /** + * Tries to match a chunk of text and if successful + * removes the recognised chunk and any leading + * unparsed data. Empty strings will not be matched. + * @param string $raw The subject to parse. This is the + * content that will be eaten. + * @return array Three item list of unparsed + * content followed by the + * recognised token and finally the + * action the parser is to take. + * True if no match, false if there + * is a parsing error. + * @access private + */ + function _reduce(&$raw) { + if (! isset($this->_regexes[$this->_mode->getCurrent()])) { + return false; + } + if ($raw === "") { + return true; + } + if ($action = $this->_regexes[$this->_mode->getCurrent()]->explode($raw, $split)) { + list($unparsed, $match, $raw) = $split; + return array($unparsed, $match, $action); + } + return true; + } +} + +/** +* Escapes regex characters other than (, ) and / +* @TODO +*/ +function Doku_Lexer_Escape($str) { + //$str = addslashes($str); + $chars = array( + '/\\\\/', + '/\./', + '/\+/', + '/\*/', + '/\?/', + '/\[/', + '/\^/', + '/\]/', + '/\$/', + '/\{/', + '/\}/', + '/\=/', + '/\!/', + '/\/', + '/\|/', + '/\:/' + ); + + $escaped = array( + '\\\\\\\\', + '\.', + '\+', + '\*', + '\?', + '\[', + '\^', + '\]', + '\$', + '\{', + '\}', + '\=', + '\!', + '\<', + '\>', + '\|', + '\:' + ); + return preg_replace($chars, $escaped, $str); +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/parser/parser.php b/plugins/dokuwiki/inc/parser/parser.php new file mode 100644 index 0000000..b77af88 --- /dev/null +++ b/plugins/dokuwiki/inc/parser/parser.php @@ -0,0 +1,932 @@ + array('listblock','table','quote','hr'), + + // some mode are allowed inside the base mode only + 'baseonly' => array('header'), + + // modes for styling text -- footnote behaves similar to styling + 'formatting' => array('strong', 'emphasis', 'underline', 'monospace', + 'subscript', 'superscript', 'deleted', 'footnote'), + + // modes where the token is simply replaced - they can not contain any + // other modes + 'substition' => array('acronym','smiley','wordblock','entity', + 'camelcaselink', 'internallink','media', + 'externallink','linebreak','emaillink', + 'windowssharelink','filelink','notoc', + 'nocache','multiplyentity','quotes','rss'), + + // modes which have a start and end token but inside which + // no other modes should be applied + 'protected' => array('preformatted','code','file','php','html'), + + // inside this mode no wiki markup should be applied but lineendings + // and whitespace isn't preserved + 'disabled' => array('unformatted'), + + // used to mark paragraph boundaries + 'paragraphs' => array('eol') +); + +//------------------------------------------------------------------- + +/** +* Sets up the Lexer with modes and points it to the Handler +* For an intro to the Lexer see: wiki:parser +*/ +class Doku_Parser { + + var $Handler; + + var $Lexer; + + var $modes = array(); + + var $connected = FALSE; + + function addBaseMode(& $BaseMode) { + $this->modes['base'] = & $BaseMode; + if ( !$this->Lexer ) { + $this->Lexer = new Doku_Lexer($this->Handler,'base', TRUE); + } + $this->modes['base']->Lexer = & $this->Lexer; + } + + /** + * PHP preserves order of associative elements + * Mode sequence is important + */ + function addMode($name, & $Mode) { + if ( !isset($this->modes['base']) ) { + $this->addBaseMode(new Doku_Parser_Mode_base()); + } + $Mode->Lexer = & $this->Lexer; + $this->modes[$name] = & $Mode; + } + + function connectModes() { + + if ( $this->connected ) { + return; + } + + foreach ( array_keys($this->modes) as $mode ) { + + // Base isn't connected to anything + if ( $mode == 'base' ) { + continue; + } + + $this->modes[$mode]->preConnect(); + + foreach ( array_keys($this->modes) as $cm ) { + + if ( $this->modes[$cm]->accepts($mode) ) { + $this->modes[$mode]->connectTo($cm); + } + + } + + $this->modes[$mode]->postConnect(); + } + + $this->connected = TRUE; + } + + function parse($doc) { + if ( $this->Lexer ) { + $this->connectModes(); + // Normalize CRs and pad doc + $doc = "\n".str_replace("\r\n","\n",$doc)."\n"; + $this->Lexer->parse($doc); + $this->Handler->_finalize(); + return $this->Handler->calls; + } else { + return FALSE; + } + } + +} + +//------------------------------------------------------------------- +/** + * This class and all the subclasses below are + * used to reduce the effort required to register + * modes with the Lexer. For performance these + * could all be eliminated later perhaps, or + * the Parser could be serialized to a file once + * all modes are registered + * + * @author Harry Fuecks +*/ +class Doku_Parser_Mode { + + var $Lexer; + + var $allowedModes = array(); + + // returns a number used to determine in which order modes are added + function getSort() { + trigger_error('getSort() not implemented in '.get_class($this), E_USER_WARNING); + } + + // Called before any calls to connectTo + function preConnect() {} + + // Connects the mode + function connectTo($mode) {} + + // Called after all calls to connectTo + function postConnect() {} + + function accepts($mode) { + return in_array($mode, $this->allowedModes ); + } + +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_base extends Doku_Parser_Mode { + + function __construct() { + global $PARSER_MODES; + + $this->allowedModes = array_merge ( + $PARSER_MODES['container'], + $PARSER_MODES['baseonly'], + $PARSER_MODES['paragraphs'], + $PARSER_MODES['formatting'], + $PARSER_MODES['substition'], + $PARSER_MODES['protected'], + $PARSER_MODES['disabled'] + ); + } + + function getSort() { + return 0; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_footnote extends Doku_Parser_Mode { + + function __construct() { + global $PARSER_MODES; + + $this->allowedModes = array_merge ( + $PARSER_MODES['container'], + $PARSER_MODES['formatting'], + $PARSER_MODES['substition'], + $PARSER_MODES['protected'], + $PARSER_MODES['disabled'] + ); + + unset($this->allowedModes[array_search('footnote', $this->allowedModes)]); + } + + function connectTo($mode) { + $this->Lexer->addEntryPattern( + '\x28\x28(?=.*\x29\x29)',$mode,'footnote' + ); + } + + function postConnect() { + $this->Lexer->addExitPattern( + '\x29\x29','footnote' + ); + } + + function getSort() { + return 150; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_header extends Doku_Parser_Mode { + + function preConnect() { + //we're not picky about the closing ones, two are enough + $this->Lexer->addSpecialPattern( + '[ \t]*={2,}[^\n]+={2,}[ \t]*(?=\n)', + 'base', + 'header' + ); + } + + function getSort() { + return 50; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_notoc extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addSpecialPattern('~~NOTOC~~',$mode,'notoc'); + } + + function getSort() { + return 30; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_nocache extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addSpecialPattern('~~NOCACHE~~',$mode,'nocache'); + } + + function getSort() { + return 40; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_linebreak extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addSpecialPattern('\x5C{2}(?=\s)',$mode,'linebreak'); + } + + function getSort() { + return 140; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_eol extends Doku_Parser_Mode { + + function connectTo($mode) { + $badModes = array('listblock','table'); + if ( in_array($mode, $badModes) ) { + return; + } + $this->Lexer->addSpecialPattern('\n',$mode,'eol'); + } + + function getSort() { + return 370; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_hr extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addSpecialPattern('\n[ \t]*-{4,}[ \t]*(?=\n)',$mode,'hr'); + } + + function getSort() { + return 160; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_formatting extends Doku_Parser_Mode { + var $type; + + var $formatting = array ( + 'strong' => array ( + 'entry'=>'\*\*(?=.*\*\*)', + 'exit'=>'\*\*', + 'sort'=>70 + ), + + 'emphasis'=> array ( + 'entry'=>'//(?=[^\x00]*[^:]//)', //hack for bug #384 + 'exit'=>'//', + 'sort'=>80 + ), + + 'underline'=> array ( + 'entry'=>'__(?=.*__)', + 'exit'=>'__', + 'sort'=>90 + ), + + 'monospace'=> array ( + 'entry'=>'\x27\x27(?=.*\x27\x27)', + 'exit'=>'\x27\x27', + 'sort'=>100 + ), + + 'subscript'=> array ( + 'entry'=>'(?=.*)', + 'exit'=>'', + 'sort'=>110 + ), + + 'superscript'=> array ( + 'entry'=>'(?=.*)', + 'exit'=>'', + 'sort'=>120 + ), + + 'deleted'=> array ( + 'entry'=>'(?=.*)', + 'exit'=>'', + 'sort'=>130 + ), + ); + + function __construct($type) { + global $PARSER_MODES; + + if ( !array_key_exists($type, $this->formatting) ) { + trigger_error('Invalid formatting type '.$type, E_USER_WARNING); + } + + $this->type = $type; + + // formatting may contain other formatting but not it self + $modes = $PARSER_MODES['formatting']; + $key = array_search($type, $modes); + if ( is_int($key) ) { + unset($modes[$key]); + } + + $this->allowedModes = array_merge ( + $modes, + $PARSER_MODES['substition'], + $PARSER_MODES['disabled'] + ); + } + + function connectTo($mode) { + + // Can't nest formatting in itself + if ( $mode == $this->type ) { + return; + } + + $this->Lexer->addEntryPattern( + $this->formatting[$this->type]['entry'], + $mode, + $this->type + ); + } + + function postConnect() { + + $this->Lexer->addExitPattern( + $this->formatting[$this->type]['exit'], + $this->type + ); + + } + + function getSort() { + return $this->formatting[$this->type]['sort']; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_listblock extends Doku_Parser_Mode { + + function __construct() { + global $PARSER_MODES; + + $this->allowedModes = array_merge ( + $PARSER_MODES['formatting'], + $PARSER_MODES['substition'], + $PARSER_MODES['disabled'], + $PARSER_MODES['protected'] #XXX new + ); + + // $this->allowedModes[] = 'footnote'; + } + + function connectTo($mode) { + $this->Lexer->addEntryPattern('\n {2,}[\-\*]',$mode,'listblock'); + $this->Lexer->addEntryPattern('\n\t{1,}[\-\*]',$mode,'listblock'); + + $this->Lexer->addPattern('\n {2,}[\-\*]','listblock'); + $this->Lexer->addPattern('\n\t{1,}[\-\*]','listblock'); + + } + + function postConnect() { + $this->Lexer->addExitPattern('\n','listblock'); + } + + function getSort() { + return 10; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_table extends Doku_Parser_Mode { + + function __construct() { + global $PARSER_MODES; + + $this->allowedModes = array_merge ( + $PARSER_MODES['formatting'], + $PARSER_MODES['substition'], + $PARSER_MODES['disabled'], + $PARSER_MODES['protected'] + ); + } + + function connectTo($mode) { + $this->Lexer->addEntryPattern('\n\^',$mode,'table'); + $this->Lexer->addEntryPattern('\n\|',$mode,'table'); + } + + function postConnect() { + $this->Lexer->addPattern('\n\^','table'); + $this->Lexer->addPattern('\n\|','table'); + #$this->Lexer->addPattern(' {2,}','table'); + $this->Lexer->addPattern('[\t ]+','table'); + $this->Lexer->addPattern('\^','table'); + $this->Lexer->addPattern('\|','table'); + $this->Lexer->addExitPattern('\n','table'); + } + + function getSort() { + return 60; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_unformatted extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addEntryPattern('(?=.*)',$mode,'unformatted'); + $this->Lexer->addEntryPattern('%%(?=.*%%)',$mode,'unformattedalt'); + } + + function postConnect() { + $this->Lexer->addExitPattern('','unformatted'); + $this->Lexer->addExitPattern('%%','unformattedalt'); + $this->Lexer->mapHandler('unformattedalt','unformatted'); + } + + function getSort() { + return 170; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_php extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addEntryPattern('(?=.*)',$mode,'php'); + } + + function postConnect() { + $this->Lexer->addExitPattern('','php'); + } + + function getSort() { + return 180; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_html extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addEntryPattern('(?=.*)',$mode,'html'); + } + + function postConnect() { + $this->Lexer->addExitPattern('','html'); + } + + function getSort() { + return 190; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_preformatted extends Doku_Parser_Mode { + + function connectTo($mode) { + // Has hard coded awareness of lists... + $this->Lexer->addEntryPattern('\n (?![\*\-])',$mode,'preformatted'); + $this->Lexer->addEntryPattern('\n\t(?![\*\-])',$mode,'preformatted'); + + // How to effect a sub pattern with the Lexer! + $this->Lexer->addPattern('\n ','preformatted'); + $this->Lexer->addPattern('\n\t','preformatted'); + + } + + function postConnect() { + $this->Lexer->addExitPattern('\n','preformatted'); + } + + function getSort() { + return 20; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_code extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addEntryPattern(')',$mode,'code'); + } + + function postConnect() { + $this->Lexer->addExitPattern('','code'); + } + + function getSort() { + return 200; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_file extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addEntryPattern('(?=.*)',$mode,'file'); + } + + function postConnect() { + $this->Lexer->addExitPattern('','file'); + } + + function getSort() { + return 210; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_quote extends Doku_Parser_Mode { + + function __construct() { + global $PARSER_MODES; + + $this->allowedModes = array_merge ( + $PARSER_MODES['formatting'], + $PARSER_MODES['substition'], + $PARSER_MODES['disabled'], + $PARSER_MODES['protected'] #XXX new + ); + #$this->allowedModes[] = 'footnote'; + #$this->allowedModes[] = 'preformatted'; + #$this->allowedModes[] = 'unformatted'; + } + + function connectTo($mode) { + $this->Lexer->addEntryPattern('\n>{1,}',$mode,'quote'); + } + + function postConnect() { + $this->Lexer->addPattern('\n>{1,}','quote'); + $this->Lexer->addExitPattern('\n','quote'); + } + + function getSort() { + return 220; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_acronym extends Doku_Parser_Mode { + // A list + var $acronyms = array(); + var $pattern = ''; + + function __construct($acronyms) { + $this->acronyms = $acronyms; + } + + function preConnect() { + if(!count($this->acronyms)) return; + + $bound = '[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]'; + $acronyms = array_map('Doku_Lexer_Escape',$this->acronyms); + $this->pattern = '(?<=^|'.$bound.')(?:'.join('|',$acronyms).')(?='.$bound.')'; + } + + function connectTo($mode) { + if(!count($this->acronyms)) return; + + if ( strlen($this->pattern) > 0 ) { + $this->Lexer->addSpecialPattern($this->pattern,$mode,'acronym'); + } + } + + function getSort() { + return 240; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_smiley extends Doku_Parser_Mode { + // A list + var $smileys = array(); + var $pattern = ''; + + function __construct($smileys) { + $this->smileys = $smileys; + } + + function preConnect() { + if(!count($this->smileys)) return; + + $sep = ''; + // Nux: fix for potential pattern overflow... + $this->pattern = ''; + foreach ( $this->smileys as $smiley ) { + $this->pattern .= $sep.Doku_Lexer_Escape($smiley); + $sep = '|'; + } + } + + function connectTo($mode) { + if(!count($this->smileys)) return; + + if ( strlen($this->pattern) > 0 ) { + $this->Lexer->addSpecialPattern($this->pattern,$mode,'smiley'); + } + } + + function getSort() { + return 230; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_wordblock extends Doku_Parser_Mode { + // A list + var $badwords = array(); + var $pattern = ''; + + function __construct($badwords) { + $this->badwords = $badwords; + } + + function preConnect() { + + if ( count($this->badwords) == 0 ) { + return; + } + + $sep = ''; + // Nux: fix for potential pattern overflow... + $this->pattern = ''; + foreach ( $this->badwords as $badword ) { + $this->pattern .= $sep.'(?<=\b)(?i)'.Doku_Lexer_Escape($badword).'(?-i)(?=\b)'; + $sep = '|'; + } + + } + + function connectTo($mode) { + if ( strlen($this->pattern) > 0 ) { + $this->Lexer->addSpecialPattern($this->pattern,$mode,'wordblock'); + } + } + + function getSort() { + return 250; + } +} + +//------------------------------------------------------------------- +/** +* @TODO Quotes and 640x480 are not supported - just straight replacements here +*/ +class Doku_Parser_Mode_entity extends Doku_Parser_Mode { + // A list + var $entities = array(); + var $pattern = ''; + + function __construct($entities) { + $this->entities = $entities; + } + + function preConnect() { + if(!count($this->entities)) return; + + $sep = ''; + // Nux: fix for potential pattern overflow... + $this->pattern = ''; + foreach ( $this->entities as $entity ) { + $this->pattern .= $sep.Doku_Lexer_Escape($entity); + $sep = '|'; + } + } + + function connectTo($mode) { + if(!count($this->entities)) return; + + if ( strlen($this->pattern) > 0 ) { + $this->Lexer->addSpecialPattern($this->pattern,$mode,'entity'); + } + } + + function getSort() { + return 260; + } +} + +//------------------------------------------------------------------- +// Implements the 640x480 replacement +class Doku_Parser_Mode_multiplyentity extends Doku_Parser_Mode { + + function connectTo($mode) { + + $this->Lexer->addSpecialPattern( + '(?<=\b)\d+[xX]\d+(?=\b)',$mode,'multiplyentity' + ); + + } + + function getSort() { + return 270; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_quotes extends Doku_Parser_Mode { + + function connectTo($mode) { + + $this->Lexer->addSpecialPattern( + '(?<=^|\s)\'(?=\S)',$mode,'singlequoteopening' + ); + $this->Lexer->addSpecialPattern( + '(?<=^|\S)\'',$mode,'singlequoteclosing' + ); + $this->Lexer->addSpecialPattern( + '(?<=^|\s)"(?=\S)',$mode,'doublequoteopening' + ); + $this->Lexer->addSpecialPattern( + '(?<=^|\S)"',$mode,'doublequoteclosing' + ); + + } + + function getSort() { + return 280; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_camelcaselink extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addSpecialPattern( + '\b[A-Z]+[a-z]+[A-Z][A-Za-z]*\b',$mode,'camelcaselink' + ); + } + + function getSort() { + return 290; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_internallink extends Doku_Parser_Mode { + + function connectTo($mode) { + // Word boundaries? + $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'internallink'); + } + + function getSort() { + return 300; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_media extends Doku_Parser_Mode { + + function connectTo($mode) { + // Word boundaries? + $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'media'); + } + + function getSort() { + return 320; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_rss extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addSpecialPattern("\{\{rss>[^\}]+\}\}",$mode,'rss'); + } + + function getSort() { + return 310; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_externallink extends Doku_Parser_Mode { + var $schemes = array('http','https','telnet','gopher','wais','ftp','ed2k','irc','ldap'); + var $patterns = array(); + + function preConnect() { + + $ltrs = '\w'; + $gunk = '/\#~:.?+=&%@!\-'; + $punc = '.:?\-;,'; + $host = $ltrs.$punc; + $any = $ltrs.$gunk.$punc; + + foreach ( $this->schemes as $scheme ) { + $this->patterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; + } + + $this->patterns[] = '\b(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; + $this->patterns[] = '\b(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; + + } + + function connectTo($mode) { + foreach ( $this->patterns as $pattern ) { + $this->Lexer->addSpecialPattern($pattern,$mode,'externallink'); + } + } + + function getSort() { + return 330; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_filelink extends Doku_Parser_Mode { + + var $pattern; + + function preConnect() { + + $ltrs = '\w'; + $gunk = '/\#~:.?+=&%@!\-'; + $punc = '.:?\-;,'; + $host = $ltrs.$punc; + $any = $ltrs.$gunk.$punc; + + $this->pattern = '\b(?i)file(?-i)://['.$any.']+?['. + $punc.']*[^'.$any.']'; + } + + function connectTo($mode) { + $this->Lexer->addSpecialPattern( + $this->pattern,$mode,'filelink'); + } + + function getSort() { + return 360; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_windowssharelink extends Doku_Parser_Mode { + + var $pattern; + + function preConnect() { + $this->pattern = "\\\\\\\\\w+?(?:\\\\[\w$]+)+"; + } + + function connectTo($mode) { + $this->Lexer->addSpecialPattern( + $this->pattern,$mode,'windowssharelink'); + } + + function getSort() { + return 350; + } +} + +//------------------------------------------------------------------- +class Doku_Parser_Mode_emaillink extends Doku_Parser_Mode { + + function connectTo($mode) { + $this->Lexer->addSpecialPattern("<[\w0-9\-_.]+?@[\w\-]+\.[\w\-\.]+\.*[\w]+>",$mode,'emaillink'); + } + + function getSort() { + return 340; + } +} + + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/parser/renderer.php b/plugins/dokuwiki/inc/parser/renderer.php new file mode 100644 index 0000000..f9dcaab --- /dev/null +++ b/plugins/dokuwiki/inc/parser/renderer.php @@ -0,0 +1,212 @@ + + * @author Andreas Gohr + */ +if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); + +require_once DOKU_INC . 'inc/parser/renderer.php'; +require_once DOKU_INC . 'inc/pluginutils.php'; + +class Doku_Renderer { + var $info = array( + 'cache' => TRUE, // may the rendered result cached? + 'toc' => TRUE, // render the TOC? + ); + + + function nocache() { + $this->info['cache'] = FALSE; + } + + function notoc() { + $this->info['toc'] = FALSE; + } + + //handle plugin rendering + function plugin($name,$data){ + $plugin =& plugin_load('syntax',$name); + if($plugin != null){ + // determine mode from renderer class name - format = "Doku_Renderer_" + $mode = substr(get_class($this), 14); + $plugin->render($mode,$this,$data); + } + } + + /** + * handle nested render instructions + * this method (and nest_close method) should not be overloaded in actual renderer output classes + */ + function nest($instructions) { + + foreach ( $instructions as $instruction ) { + // execute the callback against ourself + call_user_func_array(array(&$this, $instruction[0]),$instruction[1]); + } + } + + // dummy closing instruction issued by Doku_Handler_Nest, normally the syntax mode should + // override this instruction when instantiating Doku_Handler_Nest - however plugins will not + // be able to - as their instructions require data. + function nest_close() {} + + function document_start() {} + + function document_end() {} + + function render_TOC() { return ''; } + + function header($text, $level, $pos) {} + + function section_edit($start, $end, $level, $name) {} + + function section_open($level) {} + + function section_close() {} + + function cdata($text) {} + + function p_open() {} + + function p_close() {} + + function linebreak() {} + + function hr() {} + + function strong_open() {} + + function strong_close() {} + + function emphasis_open() {} + + function emphasis_close() {} + + function underline_open() {} + + function underline_close() {} + + function monospace_open() {} + + function monospace_close() {} + + function subscript_open() {} + + function subscript_close() {} + + function superscript_open() {} + + function superscript_close() {} + + function deleted_open() {} + + function deleted_close() {} + + function footnote_open() {} + + function footnote_close() {} + + function listu_open() {} + + function listu_close() {} + + function listo_open() {} + + function listo_close() {} + + function listitem_open($level) {} + + function listitem_close() {} + + function listcontent_open() {} + + function listcontent_close() {} + + function unformatted($text) {} + + function php($text) {} + + function html($text) {} + + function preformatted($text) {} + + function file($text) {} + + function quote_open() {} + + function quote_close() {} + + function code($text, $lang = NULL) {} + + function acronym($acronym) {} + + function smiley($smiley) {} + + function wordblock($word) {} + + function entity($entity) {} + + // 640x480 ($x=640, $y=480) + function multiplyentity($x, $y) {} + + function singlequoteopening() {} + + function singlequoteclosing() {} + + function doublequoteopening() {} + + function doublequoteclosing() {} + + // $link like 'SomePage' + function camelcaselink($link) {} + + // $link like 'wiki:syntax', $title could be an array (media) + function internallink($link, $title = NULL) {} + + // $link is full URL with scheme, $title could be an array (media) + function externallink($link, $title = NULL) {} + + // $link is the original link - probably not much use + // $wikiName is an indentifier for the wiki + // $wikiUri is the URL fragment to append to some known URL + function interwikilink($link, $title = NULL, $wikiName, $wikiUri) {} + + // Link to file on users OS, $title could be an array (media) + function filelink($link, $title = NULL) {} + + // Link to a Windows share, , $title could be an array (media) + function windowssharelink($link, $title = NULL) {} + +// function email($address, $title = NULL) {} + function emaillink($address, $name = NULL) {} + + function internalmedialink ( + $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL + ) {} + + function externalmedialink( + $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL + ) {} + + function table_open($maxcols = NULL, $numrows = NULL){} + + function table_close(){} + + function tablerow_open(){} + + function tablerow_close(){} + + function tableheader_open($colspan = 1, $align = NULL){} + + function tableheader_close(){} + + function tablecell_open($colspan = 1, $align = NULL){} + + function tablecell_close(){} + +} + + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/parser/xhtml.php b/plugins/dokuwiki/inc/parser/xhtml.php new file mode 100644 index 0000000..a220819 --- /dev/null +++ b/plugins/dokuwiki/inc/parser/xhtml.php @@ -0,0 +1,1097 @@ + + * @author Andreas Gohr + */ + +if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); + +if ( !defined('DOKU_LF') ) { + // Some whitespace to help View > Source + define ('DOKU_LF',"\n"); +} + +if ( !defined('DOKU_TAB') ) { + // Some whitespace to help View > Source + define ('DOKU_TAB',"\t"); +} + +require_once DOKU_INC . 'inc/parser/renderer.php'; +require_once DOKU_INC . 'inc/html.php'; + +/** + * The Renderer + */ +class Doku_Renderer_xhtml extends Doku_Renderer { + + // @access public + var $doc = ''; // will contain the whole document + var $toc = array(); // will contain the Table of Contents + + + var $headers = array(); + + var $footnotes = array(); + + var $acronyms = array(); + var $smileys = array(); + var $badwords = array(); + var $entities = array(); + var $interwiki = array(); + + var $lastsec = 0; + + var $store = ''; + + function document_start() { + //reset some internals + $this->toc = array(); + $this->headers = array(); + } + + function document_end() { + if ( count ($this->footnotes) > 0 ) { + $this->doc .= '
    '.DOKU_LF; + + $id = 0; + foreach ( $this->footnotes as $footnote ) { + $id++; // the number of the current footnote + + // check its not a placeholder that indicates actual footnote text is elsewhere + if (substr($footnote, 0, 5) != "@@FNT") { + + // open the footnote and set the anchor and backlink + $this->doc .= '
    '; + $this->doc .= ''; + $this->doc .= $id.') '.DOKU_LF; + + // get any other footnotes that use the same markup + $alt = array_keys($this->footnotes, "@@FNT$id"); + + if (count($alt)) { + foreach ($alt as $ref) { + // set anchor and backlink for the other footnotes + $this->doc .= ', '; + $this->doc .= ($ref+1).') '.DOKU_LF; + } + } + + // add footnote markup and close this footnote + $this->doc .= $footnote; + $this->doc .= '
    ' . DOKU_LF; + } + } + $this->doc .= '
    '.DOKU_LF; + } + + // prepend the TOC + if($this->info['toc']){ + $this->doc = $this->render_TOC().$this->doc; + } + + // make sure there are no empty paragraphs + $this->doc = preg_replace('#

    \s*

    #','',$this->doc); + } + + /** + * Return the TOC rendered to XHTML + * + * @author Andreas Gohr + */ + function render_TOC(){ + if(count($this->toc) < 3) return ''; + global $lang; + $out = '
    '.DOKU_LF; + $out .= '
    '; + $out .= $lang['toc']; + $out .= '
    '.DOKU_LF; + $out .= '
    '.DOKU_LF; + $out .= html_buildlist($this->toc,'toc',array($this,'_tocitem')); + $out .= '
    '.DOKU_LF.'
    '.DOKU_LF; + return $out; + } + + /** + * Callback for html_buildlist + */ + function _tocitem($item){ + return ''. + $this->_xmlEntities($item['title']).''; + } + + function header($text, $level, $pos) { + global $conf; + + // create a unique header id + $hid = $this->_headerToLink($text,'true'); + + //handle TOC + if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']){ + // the TOC is one of our standard ul list arrays ;-) + $this->toc[] = array( 'hid' => $hid, + 'title' => $text, + 'type' => 'ul', + 'level' => $level-$conf['toptoclevel']+1); + } + + // write the header + $this->doc .= DOKU_LF.''.$this->_xmlEntities($text)."".DOKU_LF; + } + + /** + * Section edit marker is replaced by an edit button when + * the page is editable. Replacement done in 'inc/html.php#html_secedit' + * + * @author Andreas Gohr + * @author Ben Coburn + */ + function section_edit($start, $end, $level, $name) { + global $conf; + + if ($start!=-1 && $level<=$conf['maxseclevel']) { + $name = str_replace('"', '', $name); + $this->doc .= ''; + } + } + + function section_open($level) { + $this->doc .= "
    ".DOKU_LF; + } + + function section_close() { + $this->doc .= DOKU_LF.'
    '.DOKU_LF; + } + + function cdata($text) { + $this->doc .= $this->_xmlEntities($text); + } + + function p_open() { + $this->doc .= DOKU_LF.'

    '.DOKU_LF; + } + + function p_close() { + $this->doc .= DOKU_LF.'

    '.DOKU_LF; + } + + function linebreak() { + $this->doc .= '
    '.DOKU_LF; + } + + function hr() { + $this->doc .= '
    '.DOKU_LF; + } + + function strong_open() { + $this->doc .= ''; + } + + function strong_close() { + $this->doc .= ''; + } + + function emphasis_open() { + $this->doc .= ''; + } + + function emphasis_close() { + $this->doc .= ''; + } + + function underline_open() { + $this->doc .= ''; + } + + function underline_close() { + $this->doc .= ''; + } + + function monospace_open() { + $this->doc .= ''; + } + + function monospace_close() { + $this->doc .= ''; + } + + function subscript_open() { + $this->doc .= ''; + } + + function subscript_close() { + $this->doc .= ''; + } + + function superscript_open() { + $this->doc .= ''; + } + + function superscript_close() { + $this->doc .= ''; + } + + function deleted_open() { + $this->doc .= ''; + } + + function deleted_close() { + $this->doc .= ''; + } + + /** + * Callback for footnote start syntax + * + * All following content will go to the footnote instead of + * the document. To achieve this the previous rendered content + * is moved to $store and $doc is cleared + * + * @author Andreas Gohr + */ + function footnote_open() { + + // move current content to store and record footnote + $this->store = $this->doc; + $this->doc = ''; + } + + /** + * Callback for footnote end syntax + * + * All rendered content is moved to the $footnotes array and the old + * content is restored from $store again + * + * @author Andreas Gohr + */ + function footnote_close() { + + // recover footnote into the stack and restore old content + $footnote = $this->doc; + $this->doc = $this->store; + $this->store = ''; + + // check to see if this footnote has been seen before + $i = array_search($footnote, $this->footnotes); + + if ($i === false) { + // its a new footnote, add it to the $footnotes array + $id = count($this->footnotes)+1; + $this->footnotes[count($this->footnotes)] = $footnote; + } else { + // seen this one before, translate the index to an id and save a placeholder + $i++; + $id = count($this->footnotes)+1; + $this->footnotes[count($this->footnotes)] = "@@FNT".($i); + } + + // output the footnote reference and link, incl. onmouseover for insitu footnote popup + $this->doc .= ''.$id.')'; + } + + function listu_open() { + $this->doc .= '
      '.DOKU_LF; + } + + function listu_close() { + $this->doc .= '
    '.DOKU_LF; + } + + function listo_open() { + $this->doc .= '
      '.DOKU_LF; + } + + function listo_close() { + $this->doc .= '
    '.DOKU_LF; + } + + function listitem_open($level) { + $this->doc .= '
  • '; + } + + function listitem_close() { + $this->doc .= '
  • '.DOKU_LF; + } + + function listcontent_open() { + $this->doc .= '
    '; + } + + function listcontent_close() { + $this->doc .= '
    '.DOKU_LF; + } + + function unformatted($text) { + $this->doc .= $this->_xmlEntities($text); + } + + /** + * Execute PHP code if allowed + * + * @author Andreas Gohr + */ + function php($text) { + global $conf; + if($conf['phpok']){ + ob_start(); + eval($text); + $this->doc .= ob_get_contents(); + ob_end_clean(); + }else{ + $this->file($text); + } + } + + /** + * Insert HTML if allowed + * + * @author Andreas Gohr + */ + function html($text) { + global $conf; + if($conf['htmlok']){ + $this->doc .= $text; + }else{ + $this->file($text); + } + } + + function preformatted($text) { + $this->doc .= '
    ' . $this->_xmlEntities($text) . '
    '. DOKU_LF; + } + + function file($text) { + $this->doc .= '
    ' . $this->_xmlEntities($text). '
    '. DOKU_LF; + } + + function quote_open() { + $this->doc .= '
    '.DOKU_LF; + } + + function quote_close() { + $this->doc .= '
    '.DOKU_LF; + } + + /** + * Callback for code text + * + * Uses GeSHi to highlight language syntax + * + * @author Andreas Gohr + */ + function code($text, $language = NULL) { + global $conf; + + if ( is_null($language) ) { + $this->preformatted($text); + } else { + //strip leading and trailing blank line + $text = preg_replace('/^\s*?\n/','',$text); + $text = preg_replace('/\s*?\n$/','',$text); + $this->doc .= p_xhtml_cached_geshi($text, $language); + } + } + + function geshi_cached($text = '') { + $this->doc .= $text; + } + + function acronym($acronym) { + + if ( array_key_exists($acronym, $this->acronyms) ) { + + $title = $this->_xmlEntities($this->acronyms[$acronym]); + + $this->doc .= ''.$this->_xmlEntities($acronym).''; + + } else { + $this->doc .= $this->_xmlEntities($acronym); + } + } + + function smiley($smiley) { + if ( array_key_exists($smiley, $this->smileys) ) { + $title = $this->_xmlEntities($this->smileys[$smiley]); + $this->doc .= ''.
+                    $this->_xmlEntities($smiley).''; + } else { + $this->doc .= $this->_xmlEntities($smiley); + } + } + + /* + * not used + function wordblock($word) { + if ( array_key_exists($word, $this->badwords) ) { + $this->doc .= '** BLEEP **'; + } else { + $this->doc .= $this->_xmlEntities($word); + } + } + */ + + function entity($entity) { + if ( array_key_exists($entity, $this->entities) ) { + $this->doc .= $this->entities[$entity]; + } else { + $this->doc .= $this->_xmlEntities($entity); + } + } + + function multiplyentity($x, $y) { + $this->doc .= "$x×$y"; + } + + function singlequoteopening() { + $this->doc .= "‘"; + } + + function singlequoteclosing() { + $this->doc .= "’"; + } + + function doublequoteopening() { + $this->doc .= "“"; + } + + function doublequoteclosing() { + $this->doc .= "”"; + } + + /** + */ + function camelcaselink($link) { + $this->internallink($link,$link); + } + + + function locallink($hash, $name = NULL){ + global $ID; + $name = $this->_getLinkTitle($name, $hash, $isImage); + $hash = $this->_headerToLink($hash); + $title = $ID.' ↵'; + $this->doc .= ''; + $this->doc .= $name; + $this->doc .= ''; + } + + /** + * Render an internal Wiki Link + * + * $search and $returnonly are not for the renderer but are used + * elsewhere - no need to implement them in other renderers + * + * @author Andreas Gohr + */ + function internallink($id, $name = NULL, $search=NULL,$returnonly=false) { + global $conf; + global $ID; + // default name is based on $id as given + $default = $this->_simpleTitle($id); + // now first resolve and clean up the $id + resolve_pageid(getNS($ID),$id,$exists); + $name = $this->_getLinkTitle($name, $default, $isImage, $id); + if ( !$isImage ) { + if ( $exists ) { + $class='wikilink1'; + } else { + $class='wikilink2'; + } + } else { + $class='media'; + } + + //keep hash anchor + list($id,$hash) = explode('#',$id,2); + + //prepare for formating + $link['target'] = $conf['target']['wiki']; + $link['style'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + // highlight link to current page + if ($id == $ID) { + $link['pre'] = ''; + $link['suf'] = ''; + } + $link['more'] = ''; + $link['class'] = $class; + $link['url'] = wl($id); + $link['name'] = $name; + $link['title'] = $id; + //add search string + if($search){ + ($conf['userewrite']) ? $link['url'].='?s=' : $link['url'].='&s='; + $link['url'] .= rawurlencode($search); + } + + //keep hash + if($hash) $link['url'].='#'.$hash; + + //output formatted + if($returnonly){ + return $this->_formatLink($link); + }else{ + $this->doc .= $this->_formatLink($link); + } + } + + function externallink($url, $name = NULL) { + global $conf; + + $name = $this->_getLinkTitle($name, $url, $isImage); + + // add protocol on simple short URLs + if(substr($url,0,3) == 'ftp' && (substr($url,0,6) != 'ftp://')) $url = 'ftp://'.$url; + if(substr($url,0,3) == 'www') $url = 'http://'.$url; + + if ( !$isImage ) { + $class='urlextern'; + } else { + $class='media'; + } + + //prepare for formating + $link['target'] = $conf['target']['extern']; + $link['style'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = ''; + $link['class'] = $class; + $link['url'] = $url; + + $link['name'] = $name; + $link['title'] = $this->_xmlEntities($url); + if($conf['relnofollow']) $link['more'] .= ' rel="nofollow"'; + + //output formatted + $this->doc .= $this->_formatLink($link); + } + + /** + */ + function interwikilink($match, $name = NULL, $wikiName, $wikiUri) { + global $conf; + + $link = array(); + $link['target'] = $conf['target']['interwiki']; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = ''; + $link['name'] = $this->_getLinkTitle($name, $wikiUri, $isImage); + + //get interwiki URL + if ( isset($this->interwiki[$wikiName]) ) { + $url = $this->interwiki[$wikiName]; + } else { + // Default to Google I'm feeling lucky + $url = 'http://www.google.com/search?q={URL}&btnI=lucky'; + $wikiName = 'go'; + } + + if ( !$isImage ) { + $class = preg_replace('/[^_\-a-z0-9]+/i','_',$wikiName); + $link['class'] = "interwiki iw_$class"; + } else { + $link['class'] = 'media'; + } + + //do we stay at the same server? Use local target + if( strpos($url,DOKU_URL) === 0 ){ + $link['target'] = $conf['target']['wiki']; + } + + //split into hash and url part + list($wikiUri,$hash) = explode('#',$wikiUri,2); + + //replace placeholder + if(preg_match('#\{(URL|NAME|SCHEME|HOST|PORT|PATH|QUERY)\}#',$url)){ + //use placeholders + $url = str_replace('{URL}',rawurlencode($wikiUri),$url); + $url = str_replace('{NAME}',$wikiUri,$url); + $parsed = parse_url($wikiUri); + if(!$parsed['port']) $parsed['port'] = 80; + $url = str_replace('{SCHEME}',$parsed['scheme'],$url); + $url = str_replace('{HOST}',$parsed['host'],$url); + $url = str_replace('{PORT}',$parsed['port'],$url); + $url = str_replace('{PATH}',$parsed['path'],$url); + $url = str_replace('{QUERY}',$parsed['query'],$url); + $link['url'] = $url; + }else{ + //default + $link['url'] = $url.rawurlencode($wikiUri); + } + if($hash) $link['url'] .= '#'.rawurlencode($hash); + + $link['title'] = htmlspecialchars($link['url']); + + //output formatted + $this->doc .= $this->_formatLink($link); + } + + /** + */ + function windowssharelink($url, $name = NULL) { + global $conf; + global $lang; + //simple setup + $link['target'] = $conf['target']['windows']; + $link['pre'] = ''; + $link['suf'] = ''; + $link['style'] = ''; + //Display error on browsers other than IE + $link['more'] = 'onclick="if(document.all == null){alert(\''. + $this->_xmlEntities($lang['nosmblinks'],ENT_QUOTES). + '\');}" onkeypress="if(document.all == null){alert(\''. + $this->_xmlEntities($lang['nosmblinks'],ENT_QUOTES).'\');}"'; + + $link['name'] = $this->_getLinkTitle($name, $url, $isImage); + if ( !$isImage ) { + $link['class'] = 'windows'; + } else { + $link['class'] = 'media'; + } + + + $link['title'] = $this->_xmlEntities($url); + $url = str_replace('\\','/',$url); + $url = 'file:///'.$url; + $link['url'] = $url; + + //output formatted + $this->doc .= $this->_formatLink($link); + } + + function emaillink($address, $name = NULL) { + global $conf; + //simple setup + $link = array(); + $link['target'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['style'] = ''; + $link['more'] = ''; + + $name = $this->_getLinkTitle($name, $address, $isImage); + if ( !$isImage ) { + $link['class']='mail JSnocheck'; + } else { + $link['class']='media JSnocheck'; + } + + $address = $this->_xmlEntities($address); + $address = obfuscate($address); + $title = $address; + + if(empty($name)){ + $name = $address; + } +#elseif($isImage{ +# $name = $this->_xmlEntities($name); +# } + + if($conf['mailguard'] == 'visible') $address = rawurlencode($address); + + $link['url'] = 'mailto:'.$address; + $link['name'] = $name; + $link['title'] = $title; + + //output formatted + $this->doc .= $this->_formatLink($link); + } + + function internalmedia ($src, $title=NULL, $align=NULL, $width=NULL, + $height=NULL, $cache=NULL, $linking=NULL) { + global $conf; + global $ID; + resolve_mediaid(getNS($ID),$src, $exists); + + $link = array(); + $link['class'] = 'media'; + $link['style'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = ''; + $link['target'] = $conf['target']['media']; + $noLink = false; + + $link['title'] = $this->_xmlEntities($src); + list($ext,$mime) = mimetype($src); + if(substr($mime,0,5) == 'image'){ + $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache),($linking=='direct')); + }elseif($mime == 'application/x-shockwave-flash'){ + // don't link flash movies + $noLink = TRUE; + }else{ + // add file icons + $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext); + $link['class'] .= ' mediafile mf_'.$class; + $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache),true); + } + $link['name'] = $this->_media ($src, $title, $align, $width, $height, $cache); + + //output formatted + if ($linking == 'nolink' || $noLink) $this->doc .= $link['name']; + else $this->doc .= $this->_formatLink($link); + } + + /** + * @todo don't add link for flash + */ + function externalmedia ($src, $title=NULL, $align=NULL, $width=NULL, + $height=NULL, $cache=NULL, $linking=NULL) { + global $conf; + + $link = array(); + $link['class'] = 'media'; + $link['style'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = ''; + $link['target'] = $conf['target']['media']; + + $link['title'] = $this->_xmlEntities($src); + $link['url'] = ml($src,array('cache'=>$cache)); + $link['name'] = $this->_media ($src, $title, $align, $width, $height, $cache); + $noLink = false; + + list($ext,$mime) = mimetype($src); + if(substr($mime,0,5) == 'image'){ + // link only jpeg images + // if ($ext != 'jpg' && $ext != 'jpeg') $noLink = TRUE; + }elseif($mime == 'application/x-shockwave-flash'){ + // don't link flash movies + $noLink = TRUE; + }else{ + // add file icons + $link['class'] .= ' mediafile mf_'.$ext; + } + + //output formatted + if ($linking == 'nolink' || $noLink) $this->doc .= $link['name']; + else $this->doc .= $this->_formatLink($link); + } + + /** + * Renders an RSS feed + * + * @author Andreas Gohr + */ + function rss ($url,$params){ + global $lang; + global $conf; + + require_once(DOKU_INC.'inc/FeedParser.php'); + $feed = new FeedParser(); + $feed->feed_url($url); + + //disable warning while fetching + if (!defined('DOKU_E_LEVEL')) { $elvl = error_reporting(E_ERROR); } + $rc = $feed->init(); + if (!defined('DOKU_E_LEVEL')) { error_reporting($elvl); } + + //decide on start and end + if($params['reverse']){ + $mod = -1; + $start = $feed->get_item_quantity()-1; + $end = $start - ($params['max']); + $end = ($end < -1) ? -1 : $end; + }else{ + $mod = 1; + $start = 0; + $end = $feed->get_item_quantity(); + $end = ($end > $params['max']) ? $params['max'] : $end;; + } + + $this->doc .= '
      '; + if($rc){ + for ($x = $start; $x != $end; $x += $mod) { + $item = $feed->get_item($x); + $this->doc .= '
    • '; + $this->externallink($item->get_permalink(), + $item->get_title()); + if($params['author']){ + $author = $item->get_author(0); + if($author){ + $name = $author->get_name(); + if(!$name) $name = $author->get_email(); + if($name) $this->doc .= ' '.$lang['by'].' '.$name; + } + } + if($params['date']){ + $this->doc .= ' ('.$item->get_date($conf['dformat']).')'; + } + if($params['details']){ + $this->doc .= '
      '; + if($htmlok){ + $this->doc .= $item->get_description(); + }else{ + $this->doc .= strip_tags($item->get_description()); + } + $this->doc .= '
      '; + } + + $this->doc .= '
    • '; + } + }else{ + $this->doc .= '
    • '; + $this->doc .= ''.$lang['rssfailed'].''; + $this->externallink($url); + $this->doc .= '
    • '; + } + $this->doc .= '
    '; + } + + // $numrows not yet implemented + function table_open($maxcols = NULL, $numrows = NULL){ + $this->doc .= ''.DOKU_LF; + } + + function table_close(){ + $this->doc .= '
    '.DOKU_LF; + } + + function tablerow_open(){ + $this->doc .= DOKU_TAB . '' . DOKU_LF . DOKU_TAB . DOKU_TAB; + } + + function tablerow_close(){ + $this->doc .= DOKU_LF . DOKU_TAB . '' . DOKU_LF; + } + + function tableheader_open($colspan = 1, $align = NULL){ + $this->doc .= 'doc .= ' class="'.$align.'align"'; + } + if ( $colspan > 1 ) { + $this->doc .= ' colspan="'.$colspan.'"'; + } + $this->doc .= '>'; + } + + function tableheader_close(){ + $this->doc .= ''; + } + + function tablecell_open($colspan = 1, $align = NULL){ + $this->doc .= 'doc .= ' class="'.$align.'align"'; + } + if ( $colspan > 1 ) { + $this->doc .= ' colspan="'.$colspan.'"'; + } + $this->doc .= '>'; + } + + function tablecell_close(){ + $this->doc .= ''; + } + + //---------------------------------------------------------- + // Utils + + /** + * Build a link + * + * Assembles all parts defined in $link returns HTML for the link + * + * @author Andreas Gohr + */ + function _formatLink($link){ + //make sure the url is XHTML compliant (skip mailto) + if(substr($link['url'],0,7) != 'mailto:'){ + $link['url'] = str_replace('&','&',$link['url']); + $link['url'] = str_replace('&amp;','&',$link['url']); + } + //remove double encodings in titles + $link['title'] = str_replace('&amp;','&',$link['title']); + + // be sure there are no bad chars in url or title + // (we can't do this for name because it can contain an img tag) + $link['url'] = strtr($link['url'],array('>'=>'%3E','<'=>'%3C','"'=>'%22')); + $link['title'] = strtr($link['title'],array('>'=>'>','<'=>'<','"'=>'"')); + + $ret = ''; + $ret .= $link['pre']; + $ret .= ' + */ + function _simpleTitle($name){ + global $conf; + + //if there is a hash we use the ancor name only + list($name,$hash) = explode('#',$name,2); + if($hash) return $hash; + + //trim colons of a namespace link + $name = rtrim($name,':'); + + if($conf['useslash']){ + $nssep = '[:;/]'; + }else{ + $nssep = '[:;]'; + } + $name = preg_replace('!.*'.$nssep.'!','',$name); + + if(!$name) return $this->_simpleTitle($conf['start']); + return $name; + } + + /** + * Renders internal and external media + * + * @author Andreas Gohr + */ + function _media ($src, $title=NULL, $align=NULL, $width=NULL, + $height=NULL, $cache=NULL) { + + $ret = ''; + + list($ext,$mime) = mimetype($src); + if(substr($mime,0,5) == 'image'){ + //add image tag + $ret .= '_xmlEntities($title).'"'; + $ret .= ' alt="'.$this->_xmlEntities($title).'"'; + }elseif($ext == 'jpg' || $ext == 'jpeg'){ + //try to use the caption from IPTC/EXIF + require_once(DOKU_INC.'inc/JpegMeta.php'); + $jpeg = new JpegMeta(mediaFN($src)); + if($jpeg !== false) $cap = $jpeg->getTitle(); + if($cap){ + $ret .= ' title="'.$this->_xmlEntities($cap).'"'; + $ret .= ' alt="'.$this->_xmlEntities($cap).'"'; + } + }else{ + $ret .= ' alt=""'; + } + + if ( !is_null($width) ) + $ret .= ' width="'.$this->_xmlEntities($width).'"'; + + if ( !is_null($height) ) + $ret .= ' height="'.$this->_xmlEntities($height).'"'; + + $ret .= ' />'; + + }elseif($mime == 'application/x-shockwave-flash'){ + $ret .= '_xmlEntities($width).'"'; + if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"'; + $ret .= '>'.DOKU_LF; + $ret .= ''.DOKU_LF; + $ret .= ''.DOKU_LF; + $ret .= '_xmlEntities($width).'"'; + if ( !is_null($height) ) $ret .= ' height="'.$this->_xmlEntities($height).'"'; + $ret .= ' type="application/x-shockwave-flash"'. + ' pluginspage="http://www.macromedia.com/go/getflashplayer">'.DOKU_LF; + $ret .= ''.DOKU_LF; + + }elseif(!is_null($title)){ + // well at least we have a title to display + $ret .= $this->_xmlEntities($title); + }else{ + // just show the sourcename + $ret .= $this->_xmlEntities(noNS($src)); + } + + return $ret; + } + + function _xmlEntities($string) { + return htmlspecialchars($string); + } + + /** + * Creates a linkid from a headline + * + * @param string $title The headline title + * @param boolean $create Create a new unique ID? + * @author Andreas Gohr + */ + function _headerToLink($title,$create=false) { + $title = str_replace(':','',cleanID($title)); + $title = ltrim($title,'0123456789._-'); + if(empty($title)) $title='section'; + + if($create){ + // make sure tiles are unique + $num = ''; + while(in_array($title.$num,$this->headers)){ + ($num) ? $num++ : $num = 1; + } + $title = $title.$num; + $this->headers[] = $title; + } + + return $title; + } + + /** + * Construct a title and handle images in titles + * + * @author Harry Fuecks + */ + function _getLinkTitle($title, $default, & $isImage, $id=NULL) { + global $conf; + + $isImage = FALSE; + if ( is_null($title) ) { + if ($conf['useheading'] && $id) { + $heading = p_get_first_heading($id); + if ($heading) { + return $this->_xmlEntities($heading); + } + } + return $this->_xmlEntities($default); + } else if ( is_string($title) ) { + return $this->_xmlEntities($title); + } else if ( is_array($title) ) { + $isImage = TRUE; + return $this->_imageTitle($title); + } + } + + /** + * Returns an HTML code for images used in link titles + * + * @todo Resolve namespace on internal images + * @author Andreas Gohr + */ + function _imageTitle($img) { + return $this->_media($img['src'], + $img['title'], + $img['align'], + $img['width'], + $img['height'], + $img['cache']); + } +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/parserutils.php b/plugins/dokuwiki/inc/parserutils.php new file mode 100644 index 0000000..41fa1c3 --- /dev/null +++ b/plugins/dokuwiki/inc/parserutils.php @@ -0,0 +1,524 @@ + + * @author Andreas Gohr + */ + + if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); + + require_once(DOKU_INC.'inc/confutils.php'); + require_once(DOKU_INC.'inc/pageutils.php'); + require_once(DOKU_INC.'inc/pluginutils.php'); + require_once(DOKU_INC.'inc/cache.php'); + +/** + * Returns the parsed Wikitext in XHTML for the given id and revision. + * + * If $excuse is true an explanation is returned if the file + * wasn't found + * + * @author Andreas Gohr + */ +function p_wiki_xhtml($id, $rev='', $excuse=true){ + $file = wikiFN($id,$rev); + $ret = ''; + + //ensure $id is in global $ID (needed for parsing) + global $ID; + $keep = $ID; + $ID = $id; + + if($rev){ + if(@file_exists($file)){ + $ret = p_render('xhtml',p_get_instructions(io_readfile($file)),$info); //no caching on old revisions + }elseif($excuse){ + $ret = p_locale_xhtml('norev'); + } + }else{ + if(@file_exists($file)){ + $ret = p_cached_output($file,'xhtml',$id); + }elseif($excuse){ + $ret = p_locale_xhtml('newpage'); + } + } + + //restore ID (just in case) + $ID = $keep; + + return $ret; +} + +/** + * Returns starting summary for a page (e.g. the first few + * paragraphs), marked up in XHTML. + * + * If $excuse is true an explanation is returned if the file + * wasn't found + * + * @param string wiki page id + * @param reference populated with page title from heading or page id + * @deprecated + * @author Harry Fuecks + */ +function p_wiki_xhtml_summary($id, &$title, $rev='', $excuse=true){ + $file = wikiFN($id,$rev); + $ret = ''; + + //ensure $id is in global $ID (needed for parsing) + global $ID; + $keep = $ID; + $ID = $id; + + if($rev){ + if(@file_exists($file)){ + //no caching on old revisions + $ins = p_get_instructions(io_readfile($file)); + }elseif($excuse){ + $ret = p_locale_xhtml('norev'); + //restore ID (just in case) + $ID = $keep; + return $ret; + } + + }else{ + + if(@file_exists($file)){ + // The XHTML for a summary is not cached so use the instruction cache + $ins = p_cached_instructions($file); + }elseif($excuse){ + $ret = p_locale_xhtml('newpage'); + //restore ID (just in case) + $ID = $keep; + return $ret; + } + } + + $ret = p_render('xhtmlsummary',$ins,$info); + + if ( $info['sum_pagetitle'] ) { + $title = $info['sum_pagetitle']; + } else { + $title = $id; + } + + $ID = $keep; + return $ret; +} + +/** + * Returns the specified local text in parsed format + * + * @author Andreas Gohr + */ +function p_locale_xhtml($id){ + //fetch parsed locale + $html = p_cached_output(localeFN($id)); + return $html; +} + +/** + * *** DEPRECATED *** + * + * use p_cached_output() + * + * Returns the given file parsed to XHTML + * + * Uses and creates a cachefile + * + * @deprecated + * @author Andreas Gohr + * @todo rewrite to use mode instead of hardcoded XHTML + */ +function p_cached_xhtml($file){ + return p_cached_output($file); +} + +/** + * Returns the given file parsed into the requested output format + * + * @author Andreas Gohr + * @author Chris Smith + */ +function p_cached_output($file, $format='xhtml', $id='') { + global $conf; + + $cache = new cache_renderer($id, $file, $format); + if ($cache->useCache()) { + $parsed = $cache->retrieveCache(); + if($conf['allowdebug']) $parsed .= "\n\n"; + } else { + $parsed = p_render($format, p_cached_instructions($file,false,$id), $info); + + if ($info['cache']) { + $cache->storeCache($parsed); //save cachefile + if($conf['allowdebug']) $parsed .= "\n\n"; + }else{ + $cache->removeCache(); //try to delete cachefile + if($conf['allowdebug']) $parsed .= "\n\n"; + } + } + + return $parsed; +} + +/** + * Returns the render instructions for a file + * + * Uses and creates a serialized cache file + * + * @author Andreas Gohr + */ +function p_cached_instructions($file,$cacheonly=false,$id='') { + global $conf; + + $cache = new cache_instructions($id, $file); + + if ($cacheonly || $cache->useCache()) { + return $cache->retrieveCache(); + } else if (@file_exists($file)) { + // no cache - do some work + $ins = p_get_instructions(io_readfile($file)); + $cache->storeCache($ins); + return $ins; + } + + return NULL; +} + +/** + * turns a page into a list of instructions + * + * @author Harry Fuecks + * @author Andreas Gohr + */ +function p_get_instructions($text){ + + $modes = p_get_parsermodes(); + + // Create the parser + $Parser = new Doku_Parser(); + + // Add the Handler + $Parser->Handler = new Doku_Handler(); + + //add modes to parser + foreach($modes as $mode){ + $Parser->addMode($mode['mode'],$mode['obj']); + } + + // Do the parsing + trigger_event('PARSER_WIKITEXT_PREPROCESS', $text); + $p = $Parser->parse($text); +// dbg($p); + return $p; +} + +/** + * returns the metadata of a page + * + * @author Esther Brunner + */ +function p_get_metadata($id, $key=false, $render=false){ + global $INFO; + + if ($id == $INFO['id'] && !empty($INFO['meta'])) { + $meta = $INFO['meta']; + } else { + $file = metaFN($id, '.meta'); + + if (@file_exists($file)) $meta = unserialize(io_readFile($file, false)); + else $meta = array(); + + // metadata has never been rendered before - do it! + if ($render && !$meta['description']['abstract']){ + $meta = p_render_metadata($id, $meta); + io_saveFile($file, serialize($meta)); + } + } + + // filter by $key + if ($key){ + list($key, $subkey) = explode(' ', $key, 2); + if (trim($subkey)) return $meta[$key][$subkey]; + else return $meta[$key]; + } + + return $meta; +} + +/** + * sets metadata elements of a page + * + * @author Esther Brunner + */ +function p_set_metadata($id, $data, $render=false){ + if (!is_array($data)) return false; + + $orig = p_get_metadata($id); + + // render metadata first? + if ($render) $meta = p_render_metadata($id, $orig); + else $meta = $orig; + + // now add the passed metadata + $protected = array('description', 'date', 'contributor'); + foreach ($data as $key => $value){ + + // be careful with sub-arrays of $meta['relation'] + if ($key == 'relation'){ + foreach ($value as $subkey => $subvalue){ + $meta[$key][$subkey] = array_merge($meta[$key][$subkey], $subvalue); + } + + // be careful with some senisitive arrays of $meta + } elseif (in_array($key, $protected)){ + if (is_array($value)){ + #FIXME not sure if this is the intended thing: + if(!is_array($meta[$key])) $meta[$key] = array($meta[$key]); + $meta[$key] = array_merge($meta[$key], $value); + } + + // no special treatment for the rest + } else { + $meta[$key] = $value; + } + } + + // save only if metadata changed + if ($meta == $orig) return true; + + // check if current page metadata has been altered - if so sync the changes + global $INFO; + if ($id == $INFO['id'] && isset($INFO['meta'])) { + $INFO['meta'] = $meta; + } + + return io_saveFile(metaFN($id, '.meta'), serialize($meta)); +} + +/** + * renders the metadata of a page + * + * @author Esther Brunner + */ +function p_render_metadata($id, $orig){ + require_once DOKU_INC."inc/parser/metadata.php"; + + // get instructions + $instructions = p_cached_instructions(wikiFN($id),false,$id); + + // set up the renderer + $renderer = new Doku_Renderer_metadata(); + $renderer->meta = $orig; + + // loop through the instructions + foreach ($instructions as $instruction){ + // execute the callback against the renderer + call_user_func_array(array(&$renderer, $instruction[0]), $instruction[1]); + } + + return $renderer->meta; +} + +/** + * returns all available parser syntax modes in correct order + * + * @author Andreas Gohr + */ +function p_get_parsermodes(){ + global $conf; + + //reuse old data + static $modes = null; + if($modes != null){ + return $modes; + } + + //import parser classes and mode definitions + require_once DOKU_INC . 'inc/parser/parser.php'; + + // we now collect all syntax modes and their objects, then they will + // be sorted and added to the parser in correct order + $modes = array(); + + // add syntax plugins + $pluginlist = plugin_list('syntax'); + if(count($pluginlist)){ + global $PARSER_MODES; + $obj = null; + foreach($pluginlist as $p){ + if(!$obj =& plugin_load('syntax',$p)) continue; //attempt to load plugin into $obj + $PARSER_MODES[$obj->getType()][] = "plugin_$p"; //register mode type + //add to modes + $modes[] = array( + 'sort' => $obj->getSort(), + 'mode' => "plugin_$p", + 'obj' => $obj, + ); + unset($obj); //remove the reference + } + } + + // add default modes + $std_modes = array('listblock','preformatted','notoc','nocache', + 'header','table','linebreak','footnote','hr', + 'unformatted','php','html','code','file','quote', + 'internallink','rss','media','externallink', + 'emaillink','windowssharelink','eol'); + if($conf['typography']){ + $std_modes[] = 'quotes'; + $std_modes[] = 'multiplyentity'; + } + foreach($std_modes as $m){ + $class = "Doku_Parser_Mode_$m"; + $obj = new $class(); + $modes[] = array( + 'sort' => $obj->getSort(), + 'mode' => $m, + 'obj' => $obj + ); + } + + // add formatting modes + $fmt_modes = array('strong','emphasis','underline','monospace', + 'subscript','superscript','deleted'); + foreach($fmt_modes as $m){ + $obj = new Doku_Parser_Mode_formatting($m); + $modes[] = array( + 'sort' => $obj->getSort(), + 'mode' => $m, + 'obj' => $obj + ); + } + + // add modes which need files + $obj = new Doku_Parser_Mode_smiley(array_keys(getSmileys())); + $modes[] = array('sort' => $obj->getSort(), 'mode' => 'smiley','obj' => $obj ); + $obj = new Doku_Parser_Mode_acronym(array_keys(getAcronyms())); + $modes[] = array('sort' => $obj->getSort(), 'mode' => 'acronym','obj' => $obj ); + $obj = new Doku_Parser_Mode_entity(array_keys(getEntities())); + $modes[] = array('sort' => $obj->getSort(), 'mode' => 'entity','obj' => $obj ); + + + // add optional camelcase mode + if($conf['camelcase']){ + $obj = new Doku_Parser_Mode_camelcaselink(); + $modes[] = array('sort' => $obj->getSort(), 'mode' => 'camelcaselink','obj' => $obj ); + } + + //sort modes + usort($modes,'p_sort_modes'); + + return $modes; +} + +/** + * Callback function for usort + * + * @author Andreas Gohr + */ +function p_sort_modes($a, $b){ + if($a['sort'] == $b['sort']) return 0; + return ($a['sort'] < $b['sort']) ? -1 : 1; +} + +/** + * Renders a list of instruction to the specified output mode + * + * In the $info array are informations from the renderer returned + * + * @author Harry Fuecks + * @author Andreas Gohr + */ +function p_render($mode,$instructions,& $info){ + if(is_null($instructions)) return ''; + + if ($mode=='wiki') { msg("Renderer for $mode not valid",-1); return null; } //FIXME!! remove this line when inc/parser/wiki.php works. + + // Create the renderer + if(!@file_exists(DOKU_INC."inc/parser/$mode.php")){ + msg("No renderer for $mode found",-1); + return null; + } + + require_once DOKU_INC."inc/parser/$mode.php"; + $rclass = "Doku_Renderer_$mode"; + if ( !class_exists($rclass) ) { + trigger_error("Unable to resolve render class $rclass",E_USER_WARNING); + msg("Renderer for $mode not valid",-1); + return null; + } + $Renderer = new $rclass(); #FIXME any way to check for class existance? + + $Renderer->smileys = getSmileys(); + $Renderer->entities = getEntities(); + $Renderer->acronyms = getAcronyms(); + $Renderer->interwiki = getInterwiki(); + #$Renderer->badwords = getBadWords(); + + // Loop through the instructions + foreach ( $instructions as $instruction ) { + // Execute the callback against the Renderer + call_user_func_array(array(&$Renderer, $instruction[0]),$instruction[1]); + } + + //set info array + $info = $Renderer->info; + + // Post process and return the output + $data = array($mode,& $Renderer->doc); + trigger_event('RENDERER_CONTENT_POSTPROCESS',$data); + return $Renderer->doc; +} + +/** + * Gets the first heading from a file + * + * @author Andreas Gohr + */ +function p_get_first_heading($id){ + global $conf; + return $conf['useheading'] ? p_get_metadata($id,'title') : null; +} + +/** + * Wrapper for GeSHi Code Highlighter, provides caching of its output + * + * @author Christopher Smith + */ +function p_xhtml_cached_geshi($code, $language) { + $cache = getCacheName($language.$code,".code"); + + if (@file_exists($cache) && !$_REQUEST['purge'] && + (filemtime($cache) > filemtime(DOKU_INC . 'inc/geshi.php'))) { + + $highlighted_code = io_readFile($cache, false); + @touch($cache); + + } else { + + require_once(DOKU_INC . 'inc/geshi.php'); + + $geshi = new GeSHi($code, strtolower($language), DOKU_INC . 'inc/geshi'); + $geshi->set_encoding('utf-8'); + $geshi->enable_classes(); + $geshi->set_header_type(GESHI_HEADER_PRE); + + #$geshi->set_overall_class("code $language"); + # geshi 1.0.8.* now adds the language first + $geshi->set_overall_class("code"); + + $geshi->set_link_target($conf['target']['extern']); + + $highlighted_code = $geshi->parse_code(); + + io_saveFile($cache,$highlighted_code); + } + + return $highlighted_code; +} + +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/plugins/dokuwiki/inc/pluginutils.php b/plugins/dokuwiki/inc/pluginutils.php new file mode 100644 index 0000000..183e222 --- /dev/null +++ b/plugins/dokuwiki/inc/pluginutils.php @@ -0,0 +1,95 @@ + + */ + +// plugin related constants +if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); +$plugin_types = array('admin','syntax','action'); + +/** + * Returns a list of available plugins of given type + * + * @param $type string, plugin_type name; + * the type of plugin to return, + * use empty string for all types + * @param $all bool; + * false to only return enabled plugins, + * true to return both enabled and disabled plugins + * + * @return array of plugin names + * + * @author Andreas Gohr + */ +function plugin_list($type='',$all=false){ + $plugins = array(); + if ($dh = opendir(DOKU_PLUGIN)) { + while (false !== ($plugin = readdir($dh))) { + if ($plugin == '.' || $plugin == '..' || $plugin == 'tmp') continue; + if (is_file(DOKU_PLUGIN.$plugin)) continue; + + // if required, skip disabled plugins + if (!$all && plugin_isdisabled($plugin)) continue; + + if ($type=='' || @file_exists(DOKU_PLUGIN."$plugin/$type.php")){ + $plugins[] = $plugin; + } else { + if ($dp = @opendir(DOKU_PLUGIN."$plugin/$type/")) { + while (false !== ($component = readdir($dp))) { + if ($component == '.' || $component == '..' || strtolower(substr($component, -4)) != ".php") continue; + if (is_file(DOKU_PLUGIN."$plugin/$type/$component")) { + $plugins[] = $plugin.'_'.substr($component, 0, -4); + } + } + closedir($dp); + } + } + } + closedir($dh); + } + return $plugins; +} + +/** + * Loads the given plugin and creates an object of it + * + * @author Andreas Gohr + * + * @param $type string type of plugin to load + * @param $name string name of the plugin to load + * @return objectreference the plugin object or null on failure + */ +function &plugin_load($type,$name){ + //we keep all loaded plugins available in global scope for reuse + global $DOKU_PLUGINS; + + + //plugin already loaded? + if(!empty($DOKU_PLUGINS[$type][$name])){ + return $DOKU_PLUGINS[$type][$name]; + } + + //try to load the wanted plugin file + if (@file_exists(DOKU_PLUGIN."$name/$type.php")){ + include_once(DOKU_PLUGIN."$name/$type.php"); + }else{ + list($plugin, $component) = preg_split("/_/",$name, 2); + if (!$component || !include_once(DOKU_PLUGIN."$plugin/$type/$component.php")) { + return null; + } + } + + //construct class and instantiate + $class = $type.'_plugin_'.$name; + if (!class_exists($class)) return null; + + $DOKU_PLUGINS[$type][$name] = new $class; + return $DOKU_PLUGINS[$type][$name]; +} + +function plugin_isdisabled($name) { return @file_exists(DOKU_PLUGIN.$name.'/disabled'); } +function plugin_enable($name) { return @unlink(DOKU_PLUGIN.$name.'/disabled'); } +function plugin_disable($name) { return @touch(DOKU_PLUGIN.$name.'/disabled'); } diff --git a/plugins/dokuwiki/inc/utf8.php b/plugins/dokuwiki/inc/utf8.php new file mode 100644 index 0000000..bdcf365 --- /dev/null +++ b/plugins/dokuwiki/inc/utf8.php @@ -0,0 +1,1276 @@ + + */ + +/** + * check for mb_string support + */ +if(!defined('UTF8_MBSTRING')){ + if(function_exists('mb_substr') && !defined('UTF8_NOMBSTRING')){ + define('UTF8_MBSTRING',1); + }else{ + define('UTF8_MBSTRING',0); + } +} + +if(UTF8_MBSTRING){ mb_internal_encoding('UTF-8'); } + + +/** + * URL-Encode a filename to allow unicodecharacters + * + * Slashes are not encoded + * + * When the second parameter is true the string will + * be encoded only if non ASCII characters are detected - + * This makes it safe to run it multiple times on the + * same string (default is true) + * + * @author Andreas Gohr + * @see urlencode + */ +if (!function_exists('utf8_encodeFN')){ +function utf8_encodeFN($file,$safe=true){ + if($safe && preg_match('#^[a-zA-Z0-9/_\-.%]+$#',$file)){ + return $file; + } + $file = urlencode($file); + $file = str_replace('%2F','/',$file); + return $file; +} +} + +/** + * URL-Decode a filename + * + * This is just a wrapper around urldecode + * + * @author Andreas Gohr + * @see urldecode + */ +if (!function_exists('utf8_decodeFN')){ +function utf8_decodeFN($file){ + $file = urldecode($file); + return $file; +} +} + +/** + * Checks if a string contains 7bit ASCII only + * + * @author Andreas Gohr + */ +if (!function_exists('utf8_isASCII')){ +function utf8_isASCII($str){ + for($i=0; $i127) return false; + } + return true; +} +} + +/** + * Strips all highbyte chars + * + * Returns a pure ASCII7 string + * + * @author Andreas Gohr + */ +if (!function_exists('utf8_strip')){ +function utf8_strip($str){ + $ascii = ''; + for($i=0; $i + * @link http://www.php.net/manual/en/function.utf8-encode.php + */ +if (!function_exists('utf8_check')){ +function utf8_check($Str) { + for ($i=0; $i + * @see strlen() + * @see utf8_decode() + */ +if(!function_exists('utf8_strlen')){ +function utf8_strlen($string){ + return strlen(utf8_decode($string)); +} +} + +/** + * UTF-8 aware alternative to substr + * + * Return part of a string given character offset (and optionally length) + * + * @author Harry Fuecks + * @author Chris Smith + * @param string + * @param integer number of UTF-8 characters offset (from left) + * @param integer (optional) length in UTF-8 characters from offset + * @return mixed string or FALSE if failure + */ +if(!function_exists('utf8_substr')){ +function utf8_substr($str, $offset, $length = null) { + if(UTF8_MBSTRING){ + if( $length === null ){ + return mb_substr($str, $offset); + }else{ + return mb_substr($str, $offset, $length); + } + } + + /* + * Notes: + * + * no mb string support, so we'll use pcre regex's with 'u' flag + * pcre only supports repetitions of less than 65536, in order to accept up to MAXINT values for + * offset and length, we'll repeat a group of 65535 characters when needed (ok, up to MAXINT-65536) + * + * substr documentation states false can be returned in some cases (e.g. offset > string length) + * mb_substr never returns false, it will return an empty string instead. + * + * calculating the number of characters in the string is a relatively expensive operation, so + * we only carry it out when necessary. It isn't necessary for +ve offsets and no specified length + */ + + // cast parameters to appropriate types to avoid multiple notices/warnings + $str = (string)$str; // generates E_NOTICE for PHP4 objects, but not PHP5 objects + $offset = (int)$offset; + if (!is_null($length)) $length = (int)$length; + + // handle trivial cases + if ($length === 0) return ''; + if ($offset < 0 && $length < 0 && $length < $offset) return ''; + + $offset_pattern = ''; + $length_pattern = ''; + + // normalise -ve offsets (we could use a tail anchored pattern, but they are horribly slow!) + if ($offset < 0) { + $strlen = strlen(utf8_decode($str)); // see notes + $offset = $strlen + $offset; + if ($offset < 0) $offset = 0; + } + + // establish a pattern for offset, a non-captured group equal in length to offset + if ($offset > 0) { + $Ox = (int)($offset/65535); + $Oy = $offset%65535; + + if ($Ox) $offset_pattern = '(?:.{65535}){'.$Ox.'}'; + $offset_pattern = '^(?:'.$offset_pattern.'.{'.$Oy.'})'; + } else { + $offset_pattern = '^'; // offset == 0; just anchor the pattern + } + + // establish a pattern for length + if (is_null($length)) { + $length_pattern = '(.*)$'; // the rest of the string + } else { + + if (!isset($strlen)) $strlen = strlen(utf8_decode($str)); // see notes + if ($offset > $strlen) return ''; // another trivial case + + if ($length > 0) { + + $length = min($strlen-$offset, $length); // reduce any length that would go passed the end of the string + + $Lx = (int)($length/65535); + $Ly = $length%65535; + + // +ve length requires ... a captured group of length characters + if ($Lx) $length_pattern = '(?:.{65535}){'.$Lx.'}'; + $length_pattern = '('.$length_pattern.'.{'.$Ly.'})'; + + } else if ($length < 0) { + + if ($length < ($offset - $strlen)) return ''; + + $Lx = (int)((-$length)/65535); + $Ly = (-$length)%65535; + + // -ve length requires ... capture everything except a group of -length characters + // anchored at the tail-end of the string + if ($Lx) $length_pattern = '(?:.{65535}){'.$Lx.'}'; + $length_pattern = '(.*)(?:'.$length_pattern.'.{'.$Ly.'})$'; + } + } + + if (!preg_match('#'.$offset_pattern.$length_pattern.'#us',$str,$match)) return ''; + return $match[1]; +} +} + +/** + * Unicode aware replacement for substr_replace() + * + * @author Andreas Gohr + * @see substr_replace() + */ +if (!function_exists('utf8_substr_replace')){ +function utf8_substr_replace($string, $replacement, $start , $length=0 ){ + $ret = ''; + if($start>0) $ret .= utf8_substr($string, 0, $start); + $ret .= $replacement; + $ret .= utf8_substr($string, $start+$length); + return $ret; +} +} + +/** + * Unicode aware replacement for explode + * + * @TODO support third limit arg + * @author Harry Fuecks + * @see explode(); + */ +if (!function_exists('utf8_explode')){ +function utf8_explode($sep, $str) { + if ( $sep == '' ) { + trigger_error('Empty delimiter',E_USER_WARNING); + return FALSE; + } + + return preg_split('!'.preg_quote($sep,'!').'!u',$str); +} +} + +/** + * Unicode aware replacement for strrepalce() + * + * @todo support PHP5 count (fourth arg) + * @author Harry Fuecks + * @see strreplace(); + */ +if (!function_exists('utf8_str_replace')){ +function utf8_str_replace($s,$r,$str){ + if(!is_array($s)){ + $s = '!'.preg_quote($s,'!').'!u'; + }else{ + foreach ($s as $k => $v) { + $s[$k] = '!'.preg_quote($v).'!u'; + } + } + return preg_replace($s,$r,$str); +} +} + +/** + * Unicode aware replacement for ltrim() + * + * @author Andreas Gohr + * @see ltrim() + * @return string + */ +if (!function_exists('utf8_ltrim')){ +function utf8_ltrim($str,$charlist=''){ + if($charlist == '') return ltrim($str); + + //quote charlist for use in a characterclass + $charlist = preg_replace('!([\\\\\\-\\]\\[/])!','\\\${1}',$charlist); + + return preg_replace('/^['.$charlist.']+/u','',$str); +} +} + +/** + * Unicode aware replacement for rtrim() + * + * @author Andreas Gohr + * @see rtrim() + * @return string + */ +if (!function_exists('utf8_rtrim')){ +function utf8_rtrim($str,$charlist=''){ + if($charlist == '') return rtrim($str); + + //quote charlist for use in a characterclass + $charlist = preg_replace('!([\\\\\\-\\]\\[/])!','\\\${1}',$charlist); + + return preg_replace('/['.$charlist.']+$/u','',$str); +} +} + +/** + * Unicode aware replacement for trim() + * + * @author Andreas Gohr + * @see trim() + * @return string + */ +if (!function_exists('utf8_trim')){ +function utf8_trim($str,$charlist='') { + if($charlist == '') return trim($str); + + return utf8_ltrim(utf8_rtrim($str)); +} +} + + +/** + * This is a unicode aware replacement for strtolower() + * + * Uses mb_string extension if available + * + * @author Andreas Gohr + * @see strtolower() + * @see utf8_strtoupper() + */ +if(!function_exists('utf8_strtolower')){ +function utf8_strtolower($string){ + if(UTF8_MBSTRING) return mb_strtolower($string,'utf-8'); + + global $UTF8_UPPER_TO_LOWER; + $uni = utf8_to_unicode($string); + $cnt = count($uni); + for ($i=0; $i < $cnt; $i++){ + if($UTF8_UPPER_TO_LOWER[$uni[$i]]){ + $uni[$i] = $UTF8_UPPER_TO_LOWER[$uni[$i]]; + } + } + return unicode_to_utf8($uni); +} +} + +/** + * This is a unicode aware replacement for strtoupper() + * + * Uses mb_string extension if available + * + * @author Andreas Gohr + * @see strtoupper() + * @see utf8_strtoupper() + */ +if (!function_exists('utf8_strtoupper')){ +function utf8_strtoupper($string){ + if(UTF8_MBSTRING) return mb_strtoupper($string,'utf-8'); + + global $UTF8_LOWER_TO_UPPER; + $uni = utf8_to_unicode($string); + $cnt = count($uni); + for ($i=0; $i < $cnt; $i++){ + if($UTF8_LOWER_TO_UPPER[$uni[$i]]){ + $uni[$i] = $UTF8_LOWER_TO_UPPER[$uni[$i]]; + } + } + return unicode_to_utf8($uni); +} +} + +/** + * Replace accented UTF-8 characters by unaccented ASCII-7 equivalents + * + * Use the optional parameter to just deaccent lower ($case = -1) or upper ($case = 1) + * letters. Default is to deaccent both cases ($case = 0) + * + * @author Andreas Gohr + */ +if (!function_exists('utf8_deaccent')){ +function utf8_deaccent($string,$case=0){ + if($case <= 0){ + global $UTF8_LOWER_ACCENTS; + $string = str_replace(array_keys($UTF8_LOWER_ACCENTS),array_values($UTF8_LOWER_ACCENTS),$string); + } + if($case >= 0){ + global $UTF8_UPPER_ACCENTS; + $string = str_replace(array_keys($UTF8_UPPER_ACCENTS),array_values($UTF8_UPPER_ACCENTS),$string); + } + return $string; +} +} + +/** + * Romanize a non-latin string + * + * @author Andreas Gohr + */ +if (!function_exists('utf8_romanize')){ +function utf8_romanize($string){ + if(utf8_isASCII($string)) return $string; //nothing to do + + global $UTF8_ROMANIZATION; + return strtr($string,$UTF8_ROMANIZATION); +} +} + +/** + * Removes special characters (nonalphanumeric) from a UTF-8 string + * + * This function adds the controlchars 0x00 to 0x19 to the array of + * stripped chars (they are not included in $UTF8_SPECIAL_CHARS) + * + * @author Andreas Gohr + * @param string $string The UTF8 string to strip of special chars + * @param string $repl Replace special with this string + * @param string $additional Additional chars to strip (used in regexp char class) + */ +if (!function_exists('utf8_stripspecials')){ +function utf8_stripspecials($string,$repl='',$additional=''){ + global $UTF8_SPECIAL_CHARS; + global $UTF8_SPECIAL_CHARS2; + + static $specials = null; + if(is_null($specials)){ +# $specials = preg_quote(unicode_to_utf8($UTF8_SPECIAL_CHARS), '/'); + $specials = preg_quote($UTF8_SPECIAL_CHARS2, '/'); + } + + return preg_replace('/['.$additional.'\x00-\x19'.$specials.']/u',$repl,$string); +} +} + +/** + * This is an Unicode aware replacement for strpos + * + * Uses mb_string extension if available + * + * @author Harry Fuecks + * @see strpos() + */ +if (!function_exists('utf8_strpos')){ +function utf8_strpos($haystack, $needle,$offset=0) { + if(UTF8_MBSTRING) return mb_strpos($haystack,$needle,$offset,'utf-8'); + + if(!$offset){ + $ar = utf8_explode($needle, $haystack); + if ( count($ar) > 1 ) { + return utf8_strlen($ar[0]); + } + return false; + }else{ + if ( !is_int($offset) ) { + trigger_error('Offset must be an integer',E_USER_WARNING); + return false; + } + + $haystack = utf8_substr($haystack, $offset); + + if ( false !== ($pos = utf8_strpos($haystack,$needle))){ + return $pos + $offset; + } + return false; + } +} +} + +/** + * Encodes UTF-8 characters to HTML entities + * + * @author + * @link http://www.php.net/manual/en/function.utf8-decode.php + */ +if (!function_exists('utf8_tohtml')){ +function utf8_tohtml ($str) { + $ret = ''; + $max = strlen($str); + $last = 0; // keeps the index of the last regular character + for ($i=0; $i<$max; $i++) { + $c = $str{$i}; + $c1 = ord($c); + if ($c1>>5 == 6) { // 110x xxxx, 110 prefix for 2 bytes unicode + $ret .= substr($str, $last, $i-$last); // append all the regular characters we've passed + $c1 &= 31; // remove the 3 bit two bytes prefix + $c2 = ord($str{++$i}); // the next byte + $c2 &= 63; // remove the 2 bit trailing byte prefix + $c2 |= (($c1 & 3) << 6); // last 2 bits of c1 become first 2 of c2 + $c1 >>= 2; // c1 shifts 2 to the right + $ret .= '&#' . ($c1 * 100 + $c2) . ';'; // this is the fastest string concatenation + $last = $i+1; + } + } + return $ret . substr($str, $last, $i); // append the last batch of regular characters +} +} + +/** + * Takes an UTF-8 string and returns an array of ints representing the + * Unicode characters. Astral planes are supported ie. the ints in the + * output can be > 0xFFFF. Occurrances of the BOM are ignored. Surrogates + * are not allowed. + * + * If $strict is set to true the function returns false if the input + * string isn't a valid UTF-8 octet sequence and raises a PHP error at + * level E_USER_WARNING + * + * Note: this function has been modified slightly in this library to + * trigger errors on encountering bad bytes + * + * @author + * @author Harry Fuecks + * @param string UTF-8 encoded string + * @param boolean Check for invalid sequences? + * @return mixed array of unicode code points or FALSE if UTF-8 invalid + * @see unicode_to_utf8 + * @link http://hsivonen.iki.fi/php-utf8/ + * @link http://sourceforge.net/projects/phputf8/ + */ +if (!function_exists('utf8_to_unicode')){ +function utf8_to_unicode($str,$strict=false) { + $mState = 0; // cached expected number of octets after the current octet + // until the beginning of the next UTF8 character sequence + $mUcs4 = 0; // cached Unicode character + $mBytes = 1; // cached expected number of octets in the current sequence + + $out = array(); + + $len = strlen($str); + + for($i = 0; $i < $len; $i++) { + + $in = ord($str{$i}); + + if ( $mState == 0) { + + // When mState is zero we expect either a US-ASCII character or a + // multi-octet sequence. + if (0 == (0x80 & ($in))) { + // US-ASCII, pass straight through. + $out[] = $in; + $mBytes = 1; + + } else if (0xC0 == (0xE0 & ($in))) { + // First octet of 2 octet sequence + $mUcs4 = ($in); + $mUcs4 = ($mUcs4 & 0x1F) << 6; + $mState = 1; + $mBytes = 2; + + } else if (0xE0 == (0xF0 & ($in))) { + // First octet of 3 octet sequence + $mUcs4 = ($in); + $mUcs4 = ($mUcs4 & 0x0F) << 12; + $mState = 2; + $mBytes = 3; + + } else if (0xF0 == (0xF8 & ($in))) { + // First octet of 4 octet sequence + $mUcs4 = ($in); + $mUcs4 = ($mUcs4 & 0x07) << 18; + $mState = 3; + $mBytes = 4; + + } else if (0xF8 == (0xFC & ($in))) { + /* First octet of 5 octet sequence. + * + * This is illegal because the encoded codepoint must be either + * (a) not the shortest form or + * (b) outside the Unicode range of 0-0x10FFFF. + * Rather than trying to resynchronize, we will carry on until the end + * of the sequence and let the later error handling code catch it. + */ + $mUcs4 = ($in); + $mUcs4 = ($mUcs4 & 0x03) << 24; + $mState = 4; + $mBytes = 5; + + } else if (0xFC == (0xFE & ($in))) { + // First octet of 6 octet sequence, see comments for 5 octet sequence. + $mUcs4 = ($in); + $mUcs4 = ($mUcs4 & 1) << 30; + $mState = 5; + $mBytes = 6; + + } elseif($strict) { + /* Current octet is neither in the US-ASCII range nor a legal first + * octet of a multi-octet sequence. + */ + trigger_error( + 'utf8_to_unicode: Illegal sequence identifier '. + 'in UTF-8 at byte '.$i, + E_USER_WARNING + ); + return FALSE; + + } + + } else { + + // When mState is non-zero, we expect a continuation of the multi-octet + // sequence + if (0x80 == (0xC0 & ($in))) { + + // Legal continuation. + $shift = ($mState - 1) * 6; + $tmp = $in; + $tmp = ($tmp & 0x0000003F) << $shift; + $mUcs4 |= $tmp; + + /** + * End of the multi-octet sequence. mUcs4 now contains the final + * Unicode codepoint to be output + */ + if (0 == --$mState) { + + /* + * Check for illegal sequences and codepoints. + */ + // From Unicode 3.1, non-shortest form is illegal + if (((2 == $mBytes) && ($mUcs4 < 0x0080)) || + ((3 == $mBytes) && ($mUcs4 < 0x0800)) || + ((4 == $mBytes) && ($mUcs4 < 0x10000)) || + (4 < $mBytes) || + // From Unicode 3.2, surrogate characters are illegal + (($mUcs4 & 0xFFFFF800) == 0xD800) || + // Codepoints outside the Unicode range are illegal + ($mUcs4 > 0x10FFFF)) { + + if($strict){ + trigger_error( + 'utf8_to_unicode: Illegal sequence or codepoint '. + 'in UTF-8 at byte '.$i, + E_USER_WARNING + ); + + return FALSE; + } + + } + + if (0xFEFF != $mUcs4) { + // BOM is legal but we don't want to output it + $out[] = $mUcs4; + } + + //initialize UTF8 cache + $mState = 0; + $mUcs4 = 0; + $mBytes = 1; + } + + } elseif($strict) { + /** + *((0xC0 & (*in) != 0x80) && (mState != 0)) + * Incomplete multi-octet sequence. + */ + trigger_error( + 'utf8_to_unicode: Incomplete multi-octet '. + ' sequence in UTF-8 at byte '.$i, + E_USER_WARNING + ); + + return FALSE; + } + } + } + return $out; +} +} + +/** + * Takes an array of ints representing the Unicode characters and returns + * a UTF-8 string. Astral planes are supported ie. the ints in the + * input can be > 0xFFFF. Occurrances of the BOM are ignored. Surrogates + * are not allowed. + * + * If $strict is set to true the function returns false if the input + * array contains ints that represent surrogates or are outside the + * Unicode range and raises a PHP error at level E_USER_WARNING + * + * Note: this function has been modified slightly in this library to use + * output buffering to concatenate the UTF-8 string (faster) as well as + * reference the array by it's keys + * + * @param array of unicode code points representing a string + * @param boolean Check for invalid sequences? + * @return mixed UTF-8 string or FALSE if array contains invalid code points + * @author + * @author Harry Fuecks + * @see utf8_to_unicode + * @link http://hsivonen.iki.fi/php-utf8/ + * @link http://sourceforge.net/projects/phputf8/ + */ +if (!function_exists('unicode_to_utf8')){ +function unicode_to_utf8($arr,$strict=false) { + if (!is_array($arr)) return ''; + ob_start(); + + foreach (array_keys($arr) as $k) { + + # ASCII range (including control chars) + if ( ($arr[$k] >= 0) && ($arr[$k] <= 0x007f) ) { + + echo chr($arr[$k]); + + # 2 byte sequence + } else if ($arr[$k] <= 0x07ff) { + + echo chr(0xc0 | ($arr[$k] >> 6)); + echo chr(0x80 | ($arr[$k] & 0x003f)); + + # Byte order mark (skip) + } else if($arr[$k] == 0xFEFF) { + + // nop -- zap the BOM + + # Test for illegal surrogates + } else if ($arr[$k] >= 0xD800 && $arr[$k] <= 0xDFFF) { + + // found a surrogate + if($strict){ + trigger_error( + 'unicode_to_utf8: Illegal surrogate '. + 'at index: '.$k.', value: '.$arr[$k], + E_USER_WARNING + ); + return FALSE; + } + + # 3 byte sequence + } else if ($arr[$k] <= 0xffff) { + + echo chr(0xe0 | ($arr[$k] >> 12)); + echo chr(0x80 | (($arr[$k] >> 6) & 0x003f)); + echo chr(0x80 | ($arr[$k] & 0x003f)); + + # 4 byte sequence + } else if ($arr[$k] <= 0x10ffff) { + + echo chr(0xf0 | ($arr[$k] >> 18)); + echo chr(0x80 | (($arr[$k] >> 12) & 0x3f)); + echo chr(0x80 | (($arr[$k] >> 6) & 0x3f)); + echo chr(0x80 | ($arr[$k] & 0x3f)); + + } elseif($strict) { + + trigger_error( + 'unicode_to_utf8: Codepoint out of Unicode range '. + 'at index: '.$k.', value: '.$arr[$k], + E_USER_WARNING + ); + + // out of range + return FALSE; + } + } + + $result = ob_get_contents(); + ob_end_clean(); + return $result; +} +} + +/** + * UTF-8 to UTF-16BE conversion. + * + * Maybe really UCS-2 without mb_string due to utf8_to_unicode limits + */ +if (!function_exists('utf8_to_utf16be')){ +function utf8_to_utf16be(&$str, $bom = false) { + $out = $bom ? "\xFE\xFF" : ''; + if(UTF8_MBSTRING) return $out.mb_convert_encoding($str,'UTF-16BE','UTF-8'); + + $uni = utf8_to_unicode($str); + foreach($uni as $cp){ + $out .= pack('n',$cp); + } + return $out; +} +} + +/** + * UTF-8 to UTF-16BE conversion. + * + * Maybe really UCS-2 without mb_string due to utf8_to_unicode limits + */ +if (!function_exists('utf16be_to_utf8')){ +function utf16be_to_utf8(&$str) { + $uni = unpack('n*',$str); + return unicode_to_utf8($uni); +} +} + +/** + * Replace bad bytes with an alternative character + * + * ASCII character is recommended for replacement char + * + * PCRE Pattern to locate bad bytes in a UTF-8 string + * Comes from W3 FAQ: Multilingual Forms + * Note: modified to include full ASCII range including control chars + * + * @author Harry Fuecks + * @see http://www.w3.org/International/questions/qa-forms-utf-8 + * @param string to search + * @param string to replace bad bytes with (defaults to '?') - use ASCII + * @return string + */ +if (!function_exists('utf8_bad_replace')){ +function utf8_bad_replace($str, $replace = '') { + $UTF8_BAD = + '([\x00-\x7F]'. # ASCII (including control chars) + '|[\xC2-\xDF][\x80-\xBF]'. # non-overlong 2-byte + '|\xE0[\xA0-\xBF][\x80-\xBF]'. # excluding overlongs + '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}'. # straight 3-byte + '|\xED[\x80-\x9F][\x80-\xBF]'. # excluding surrogates + '|\xF0[\x90-\xBF][\x80-\xBF]{2}'. # planes 1-3 + '|[\xF1-\xF3][\x80-\xBF]{3}'. # planes 4-15 + '|\xF4[\x80-\x8F][\x80-\xBF]{2}'. # plane 16 + '|(.{1}))'; # invalid byte + ob_start(); + while (preg_match('/'.$UTF8_BAD.'/S', $str, $matches)) { + if ( !isset($matches[2])) { + echo $matches[0]; + } else { + echo $replace; + } + $str = substr($str,strlen($matches[0])); + } + $result = ob_get_contents(); + ob_end_clean(); + return $result; +} +} + +/** + * adjust a byte index into a utf8 string to a utf8 character boundary + * + * @param $str string utf8 character string + * @param $i int byte index into $str + * @param $next bool direction to search for boundary, + * false = up (current character) + * true = down (next character) + * + * @return int byte index into $str now pointing to a utf8 character boundary + * + * @author chris smith + */ +if (!function_exists('utf8_correctIdx')){ +function utf8_correctIdx(&$str,$i,$next=false) { + + if ($i <= 0) return 0; + + $limit = strlen($str); + if ($i>=$limit) return $limit; + + if ($next) { + while (($i<$limit) && ((ord($str[$i]) & 0xC0) == 0x80)) $i++; + } else { + while ($i && ((ord($str[$i]) & 0xC0) == 0x80)) $i--; + } + + return $i; +} +} + +// only needed if no mb_string available +if(!UTF8_MBSTRING){ + + /** + * UTF-8 Case lookup table + * + * This lookuptable defines the upper case letters to their correspponding + * lower case letter in UTF-8 + * + * @author Andreas Gohr + */ + global $UTF8_LOWER_TO_UPPER; + $UTF8_LOWER_TO_UPPER = array( + 0x0061=>0x0041, 0x03C6=>0x03A6, 0x0163=>0x0162, 0x00E5=>0x00C5, 0x0062=>0x0042, + 0x013A=>0x0139, 0x00E1=>0x00C1, 0x0142=>0x0141, 0x03CD=>0x038E, 0x0101=>0x0100, + 0x0491=>0x0490, 0x03B4=>0x0394, 0x015B=>0x015A, 0x0064=>0x0044, 0x03B3=>0x0393, + 0x00F4=>0x00D4, 0x044A=>0x042A, 0x0439=>0x0419, 0x0113=>0x0112, 0x043C=>0x041C, + 0x015F=>0x015E, 0x0144=>0x0143, 0x00EE=>0x00CE, 0x045E=>0x040E, 0x044F=>0x042F, + 0x03BA=>0x039A, 0x0155=>0x0154, 0x0069=>0x0049, 0x0073=>0x0053, 0x1E1F=>0x1E1E, + 0x0135=>0x0134, 0x0447=>0x0427, 0x03C0=>0x03A0, 0x0438=>0x0418, 0x00F3=>0x00D3, + 0x0440=>0x0420, 0x0454=>0x0404, 0x0435=>0x0415, 0x0449=>0x0429, 0x014B=>0x014A, + 0x0431=>0x0411, 0x0459=>0x0409, 0x1E03=>0x1E02, 0x00F6=>0x00D6, 0x00F9=>0x00D9, + 0x006E=>0x004E, 0x0451=>0x0401, 0x03C4=>0x03A4, 0x0443=>0x0423, 0x015D=>0x015C, + 0x0453=>0x0403, 0x03C8=>0x03A8, 0x0159=>0x0158, 0x0067=>0x0047, 0x00E4=>0x00C4, + 0x03AC=>0x0386, 0x03AE=>0x0389, 0x0167=>0x0166, 0x03BE=>0x039E, 0x0165=>0x0164, + 0x0117=>0x0116, 0x0109=>0x0108, 0x0076=>0x0056, 0x00FE=>0x00DE, 0x0157=>0x0156, + 0x00FA=>0x00DA, 0x1E61=>0x1E60, 0x1E83=>0x1E82, 0x00E2=>0x00C2, 0x0119=>0x0118, + 0x0146=>0x0145, 0x0070=>0x0050, 0x0151=>0x0150, 0x044E=>0x042E, 0x0129=>0x0128, + 0x03C7=>0x03A7, 0x013E=>0x013D, 0x0442=>0x0422, 0x007A=>0x005A, 0x0448=>0x0428, + 0x03C1=>0x03A1, 0x1E81=>0x1E80, 0x016D=>0x016C, 0x00F5=>0x00D5, 0x0075=>0x0055, + 0x0177=>0x0176, 0x00FC=>0x00DC, 0x1E57=>0x1E56, 0x03C3=>0x03A3, 0x043A=>0x041A, + 0x006D=>0x004D, 0x016B=>0x016A, 0x0171=>0x0170, 0x0444=>0x0424, 0x00EC=>0x00CC, + 0x0169=>0x0168, 0x03BF=>0x039F, 0x006B=>0x004B, 0x00F2=>0x00D2, 0x00E0=>0x00C0, + 0x0434=>0x0414, 0x03C9=>0x03A9, 0x1E6B=>0x1E6A, 0x00E3=>0x00C3, 0x044D=>0x042D, + 0x0436=>0x0416, 0x01A1=>0x01A0, 0x010D=>0x010C, 0x011D=>0x011C, 0x00F0=>0x00D0, + 0x013C=>0x013B, 0x045F=>0x040F, 0x045A=>0x040A, 0x00E8=>0x00C8, 0x03C5=>0x03A5, + 0x0066=>0x0046, 0x00FD=>0x00DD, 0x0063=>0x0043, 0x021B=>0x021A, 0x00EA=>0x00CA, + 0x03B9=>0x0399, 0x017A=>0x0179, 0x00EF=>0x00CF, 0x01B0=>0x01AF, 0x0065=>0x0045, + 0x03BB=>0x039B, 0x03B8=>0x0398, 0x03BC=>0x039C, 0x045C=>0x040C, 0x043F=>0x041F, + 0x044C=>0x042C, 0x00FE=>0x00DE, 0x00F0=>0x00D0, 0x1EF3=>0x1EF2, 0x0068=>0x0048, + 0x00EB=>0x00CB, 0x0111=>0x0110, 0x0433=>0x0413, 0x012F=>0x012E, 0x00E6=>0x00C6, + 0x0078=>0x0058, 0x0161=>0x0160, 0x016F=>0x016E, 0x03B1=>0x0391, 0x0457=>0x0407, + 0x0173=>0x0172, 0x00FF=>0x0178, 0x006F=>0x004F, 0x043B=>0x041B, 0x03B5=>0x0395, + 0x0445=>0x0425, 0x0121=>0x0120, 0x017E=>0x017D, 0x017C=>0x017B, 0x03B6=>0x0396, + 0x03B2=>0x0392, 0x03AD=>0x0388, 0x1E85=>0x1E84, 0x0175=>0x0174, 0x0071=>0x0051, + 0x0437=>0x0417, 0x1E0B=>0x1E0A, 0x0148=>0x0147, 0x0105=>0x0104, 0x0458=>0x0408, + 0x014D=>0x014C, 0x00ED=>0x00CD, 0x0079=>0x0059, 0x010B=>0x010A, 0x03CE=>0x038F, + 0x0072=>0x0052, 0x0430=>0x0410, 0x0455=>0x0405, 0x0452=>0x0402, 0x0127=>0x0126, + 0x0137=>0x0136, 0x012B=>0x012A, 0x03AF=>0x038A, 0x044B=>0x042B, 0x006C=>0x004C, + 0x03B7=>0x0397, 0x0125=>0x0124, 0x0219=>0x0218, 0x00FB=>0x00DB, 0x011F=>0x011E, + 0x043E=>0x041E, 0x1E41=>0x1E40, 0x03BD=>0x039D, 0x0107=>0x0106, 0x03CB=>0x03AB, + 0x0446=>0x0426, 0x00FE=>0x00DE, 0x00E7=>0x00C7, 0x03CA=>0x03AA, 0x0441=>0x0421, + 0x0432=>0x0412, 0x010F=>0x010E, 0x00F8=>0x00D8, 0x0077=>0x0057, 0x011B=>0x011A, + 0x0074=>0x0054, 0x006A=>0x004A, 0x045B=>0x040B, 0x0456=>0x0406, 0x0103=>0x0102, + 0x03BB=>0x039B, 0x00F1=>0x00D1, 0x043D=>0x041D, 0x03CC=>0x038C, 0x00E9=>0x00C9, + 0x00F0=>0x00D0, 0x0457=>0x0407, 0x0123=>0x0122, + ); + + /** + * UTF-8 Case lookup table + * + * This lookuptable defines the lower case letters to their correspponding + * upper case letter in UTF-8 (it does so by flipping $UTF8_LOWER_TO_UPPER) + * + * @author Andreas Gohr + */ + global $UTF8_UPPER_TO_LOWER; + $UTF8_UPPER_TO_LOWER = @array_flip($UTF8_LOWER_TO_UPPER); + +} // end of case lookup tables + + +/** + * UTF-8 lookup table for lower case accented letters + * + * This lookuptable defines replacements for accented characters from the ASCII-7 + * range. This are lower case letters only. + * + * @author Andreas Gohr + * @see utf8_deaccent() + */ +global $UTF8_LOWER_ACCENTS; +$UTF8_LOWER_ACCENTS = array( + 'à' => 'a', 'ô' => 'o', 'ď' => 'd', 'ḟ' => 'f', 'ë' => 'e', 'š' => 's', 'ơ' => 'o', + 'ß' => 'ss', 'ă' => 'a', 'ř' => 'r', 'ț' => 't', 'ň' => 'n', 'ā' => 'a', 'ķ' => 'k', + 'ŝ' => 's', 'ỳ' => 'y', 'ņ' => 'n', 'ĺ' => 'l', 'ħ' => 'h', 'ṗ' => 'p', 'ó' => 'o', + 'ú' => 'u', 'ě' => 'e', 'é' => 'e', 'ç' => 'c', 'ẁ' => 'w', 'ċ' => 'c', 'õ' => 'o', + 'ṡ' => 's', 'ø' => 'o', 'ģ' => 'g', 'ŧ' => 't', 'ș' => 's', 'ė' => 'e', 'ĉ' => 'c', + 'ś' => 's', 'î' => 'i', 'ű' => 'u', 'ć' => 'c', 'ę' => 'e', 'ŵ' => 'w', 'ṫ' => 't', + 'ū' => 'u', 'č' => 'c', 'ö' => 'oe', 'è' => 'e', 'ŷ' => 'y', 'ą' => 'a', 'ł' => 'l', + 'ų' => 'u', 'ů' => 'u', 'ş' => 's', 'ğ' => 'g', 'ļ' => 'l', 'ƒ' => 'f', 'ž' => 'z', + 'ẃ' => 'w', 'ḃ' => 'b', 'å' => 'a', 'ì' => 'i', 'ï' => 'i', 'ḋ' => 'd', 'ť' => 't', + 'ŗ' => 'r', 'ä' => 'ae', 'í' => 'i', 'ŕ' => 'r', 'ê' => 'e', 'ü' => 'ue', 'ò' => 'o', + 'ē' => 'e', 'ñ' => 'n', 'ń' => 'n', 'ĥ' => 'h', 'ĝ' => 'g', 'đ' => 'd', 'ĵ' => 'j', + 'ÿ' => 'y', 'ũ' => 'u', 'ŭ' => 'u', 'ư' => 'u', 'ţ' => 't', 'ý' => 'y', 'ő' => 'o', + 'â' => 'a', 'ľ' => 'l', 'ẅ' => 'w', 'ż' => 'z', 'ī' => 'i', 'ã' => 'a', 'ġ' => 'g', + 'ṁ' => 'm', 'ō' => 'o', 'ĩ' => 'i', 'ù' => 'u', 'į' => 'i', 'ź' => 'z', 'á' => 'a', + 'û' => 'u', 'þ' => 'th', 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u', 'ĕ' => 'e', +); + +/** + * UTF-8 lookup table for upper case accented letters + * + * This lookuptable defines replacements for accented characters from the ASCII-7 + * range. This are upper case letters only. + * + * @author Andreas Gohr + * @see utf8_deaccent() + */ +global $UTF8_UPPER_ACCENTS; +$UTF8_UPPER_ACCENTS = array( + 'À' => 'A', 'Ô' => 'O', 'Ď' => 'D', 'Ḟ' => 'F', 'Ë' => 'E', 'Š' => 'S', 'Ơ' => 'O', + 'Ă' => 'A', 'Ř' => 'R', 'Ț' => 'T', 'Ň' => 'N', 'Ā' => 'A', 'Ķ' => 'K', + 'Ŝ' => 'S', 'Ỳ' => 'Y', 'Ņ' => 'N', 'Ĺ' => 'L', 'Ħ' => 'H', 'Ṗ' => 'P', 'Ó' => 'O', + 'Ú' => 'U', 'Ě' => 'E', 'É' => 'E', 'Ç' => 'C', 'Ẁ' => 'W', 'Ċ' => 'C', 'Õ' => 'O', + 'Ṡ' => 'S', 'Ø' => 'O', 'Ģ' => 'G', 'Ŧ' => 'T', 'Ș' => 'S', 'Ė' => 'E', 'Ĉ' => 'C', + 'Ś' => 'S', 'Î' => 'I', 'Ű' => 'U', 'Ć' => 'C', 'Ę' => 'E', 'Ŵ' => 'W', 'Ṫ' => 'T', + 'Ū' => 'U', 'Č' => 'C', 'Ö' => 'Oe', 'È' => 'E', 'Ŷ' => 'Y', 'Ą' => 'A', 'Ł' => 'L', + 'Ų' => 'U', 'Ů' => 'U', 'Ş' => 'S', 'Ğ' => 'G', 'Ļ' => 'L', 'Ƒ' => 'F', 'Ž' => 'Z', + 'Ẃ' => 'W', 'Ḃ' => 'B', 'Å' => 'A', 'Ì' => 'I', 'Ï' => 'I', 'Ḋ' => 'D', 'Ť' => 'T', + 'Ŗ' => 'R', 'Ä' => 'Ae', 'Í' => 'I', 'Ŕ' => 'R', 'Ê' => 'E', 'Ü' => 'Ue', 'Ò' => 'O', + 'Ē' => 'E', 'Ñ' => 'N', 'Ń' => 'N', 'Ĥ' => 'H', 'Ĝ' => 'G', 'Đ' => 'D', 'Ĵ' => 'J', + 'Ÿ' => 'Y', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ư' => 'U', 'Ţ' => 'T', 'Ý' => 'Y', 'Ő' => 'O', + 'Â' => 'A', 'Ľ' => 'L', 'Ẅ' => 'W', 'Ż' => 'Z', 'Ī' => 'I', 'Ã' => 'A', 'Ġ' => 'G', + 'Ṁ' => 'M', 'Ō' => 'O', 'Ĩ' => 'I', 'Ù' => 'U', 'Į' => 'I', 'Ź' => 'Z', 'Á' => 'A', + 'Û' => 'U', 'Þ' => 'Th', 'Ð' => 'Dh', 'Æ' => 'Ae', 'Ĕ' => 'E', +); + +/** + * UTF-8 array of common special characters + * + * This array should contain all special characters (not a letter or digit) + * defined in the various local charsets - it's not a complete list of non-alphanum + * characters in UTF-8. It's not perfect but should match most cases of special + * chars. + * + * The controlchars 0x00 to 0x19 are _not_ included in this array. The space 0x20 is! + * These chars are _not_ in the array either: _ (0x5f), : 0x3a, . 0x2e, - 0x2d, * 0x2a + * + * @author Andreas Gohr + * @see utf8_stripspecials() + */ +global $UTF8_SPECIAL_CHARS; +$UTF8_SPECIAL_CHARS = array( + 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002b, 0x002c, + 0x002f, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x005b, + 0x005c, 0x005d, 0x005e, 0x0060, 0x007b, 0x007c, 0x007d, 0x007e, + 0x007f, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, + 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091, 0x0092, + 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, + 0x009d, 0x009e, 0x009f, 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, + 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, 0x00b0, + 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, + 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, 0x00d7, 0x00f7, 0x02c7, 0x02d8, 0x02d9, + 0x02da, 0x02db, 0x02dc, 0x02dd, 0x0300, 0x0301, 0x0303, 0x0309, 0x0323, 0x0384, + 0x0385, 0x0387, 0x03b2, 0x03c6, 0x03d1, 0x03d2, 0x03d5, 0x03d6, 0x05b0, 0x05b1, + 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7, 0x05b8, 0x05b9, 0x05bb, 0x05bc, + 0x05bd, 0x05be, 0x05bf, 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f3, 0x05f4, 0x060c, + 0x061b, 0x061f, 0x0640, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, 0x0650, 0x0651, + 0x0652, 0x066a, 0x0e3f, 0x200c, 0x200d, 0x200e, 0x200f, 0x2013, 0x2014, 0x2015, + 0x2017, 0x2018, 0x2019, 0x201a, 0x201c, 0x201d, 0x201e, 0x2020, 0x2021, 0x2022, + 0x2026, 0x2030, 0x2032, 0x2033, 0x2039, 0x203a, 0x2044, 0x20a7, 0x20aa, 0x20ab, + 0x20ac, 0x2116, 0x2118, 0x2122, 0x2126, 0x2135, 0x2190, 0x2191, 0x2192, 0x2193, + 0x2194, 0x2195, 0x21b5, 0x21d0, 0x21d1, 0x21d2, 0x21d3, 0x21d4, 0x2200, 0x2202, + 0x2203, 0x2205, 0x2206, 0x2207, 0x2208, 0x2209, 0x220b, 0x220f, 0x2211, 0x2212, + 0x2215, 0x2217, 0x2219, 0x221a, 0x221d, 0x221e, 0x2220, 0x2227, 0x2228, 0x2229, + 0x222a, 0x222b, 0x2234, 0x223c, 0x2245, 0x2248, 0x2260, 0x2261, 0x2264, 0x2265, + 0x2282, 0x2283, 0x2284, 0x2286, 0x2287, 0x2295, 0x2297, 0x22a5, 0x22c5, 0x2310, + 0x2320, 0x2321, 0x2329, 0x232a, 0x2469, 0x2500, 0x2502, 0x250c, 0x2510, 0x2514, + 0x2518, 0x251c, 0x2524, 0x252c, 0x2534, 0x253c, 0x2550, 0x2551, 0x2552, 0x2553, + 0x2554, 0x2555, 0x2556, 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, + 0x255e, 0x255f, 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, + 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x2580, 0x2584, 0x2588, 0x258c, 0x2590, + 0x2591, 0x2592, 0x2593, 0x25a0, 0x25b2, 0x25bc, 0x25c6, 0x25ca, 0x25cf, 0x25d7, + 0x2605, 0x260e, 0x261b, 0x261e, 0x2660, 0x2663, 0x2665, 0x2666, 0x2701, 0x2702, + 0x2703, 0x2704, 0x2706, 0x2707, 0x2708, 0x2709, 0x270c, 0x270d, 0x270e, 0x270f, + 0x2710, 0x2711, 0x2712, 0x2713, 0x2714, 0x2715, 0x2716, 0x2717, 0x2718, 0x2719, + 0x271a, 0x271b, 0x271c, 0x271d, 0x271e, 0x271f, 0x2720, 0x2721, 0x2722, 0x2723, + 0x2724, 0x2725, 0x2726, 0x2727, 0x2729, 0x272a, 0x272b, 0x272c, 0x272d, 0x272e, + 0x272f, 0x2730, 0x2731, 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, + 0x2739, 0x273a, 0x273b, 0x273c, 0x273d, 0x273e, 0x273f, 0x2740, 0x2741, 0x2742, + 0x2743, 0x2744, 0x2745, 0x2746, 0x2747, 0x2748, 0x2749, 0x274a, 0x274b, 0x274d, + 0x274f, 0x2750, 0x2751, 0x2752, 0x2756, 0x2758, 0x2759, 0x275a, 0x275b, 0x275c, + 0x275d, 0x275e, 0x2761, 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x277f, + 0x2789, 0x2793, 0x2794, 0x2798, 0x2799, 0x279a, 0x279b, 0x279c, 0x279d, 0x279e, + 0x279f, 0x27a0, 0x27a1, 0x27a2, 0x27a3, 0x27a4, 0x27a5, 0x27a6, 0x27a7, 0x27a8, + 0x27a9, 0x27aa, 0x27ab, 0x27ac, 0x27ad, 0x27ae, 0x27af, 0x27b1, 0x27b2, 0x27b3, + 0x27b4, 0x27b5, 0x27b6, 0x27b7, 0x27b8, 0x27b9, 0x27ba, 0x27bb, 0x27bc, 0x27bd, + 0x27be, 0xf6d9, 0xf6da, 0xf6db, 0xf8d7, 0xf8d8, 0xf8d9, 0xf8da, 0xf8db, 0xf8dc, + 0xf8dd, 0xf8de, 0xf8df, 0xf8e0, 0xf8e1, 0xf8e2, 0xf8e3, 0xf8e4, 0xf8e5, 0xf8e6, + 0xf8e7, 0xf8e8, 0xf8e9, 0xf8ea, 0xf8eb, 0xf8ec, 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, + 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4, 0xf8f5, 0xf8f6, 0xf8f7, 0xf8f8, 0xf8f9, 0xf8fa, + 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0xfe7c, 0xfe7d, +); + +// utf8 version of above data +global $UTF8_SPECIAL_CHARS2; +$UTF8_SPECIAL_CHARS2 = + ' !"#$%&\'()+,/;<=>?@[\]^`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•�'. + '�—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½�'. + '�¿×÷ˇ˘˙˚˛˜˝̣̀́̃̉΄΅·βφϑϒϕϖְֱֲֳִֵֶַָֹֻּֽ־ֿ�'. + '�ׁׂ׃׳״،؛؟ـًٌٍَُِّْ٪฿‌‍‎‏–—―‗‘’‚“”�'. + '��†‡•…‰′″‹›⁄₧₪₫€№℘™Ωℵ←↑→↓↔↕↵'. + '⇐⇑⇒⇓⇔∀∂∃∅∆∇∈∉∋∏∑−∕∗∙√∝∞∠∧∨�'. + '�∪∫∴∼≅≈≠≡≤≥⊂⊃⊄⊆⊇⊕⊗⊥⋅⌐⌠⌡〈〉⑩─�'. + '��┌┐└┘├┤┬┴┼═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠'. + '╡╢╣╤╥╦╧╨╩╪╫╬▀▄█▌▐░▒▓■▲▼◆◊●�'. + '�★☎☛☞♠♣♥♦✁✂✃✄✆✇✈✉✌✍✎✏✐✑✒✓✔✕�'. + '��✗✘✙✚✛✜✝✞✟✠✡✢✣✤✥✦✧✩✪✫✬✭✮✯✰✱'. + '✲✳✴✵✶✷✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋�'. + '�❏❐❑❒❖❘❙❚❛❜❝❞❡❢❣❤❥❦❧❿➉➓➔➘➙➚�'. + '��➜➝➞➟➠➡➢➣➤➥➦➧➨➩➪➫➬➭➮➯➱➲➳➴➵➶'. + '➷➸➹➺➻➼➽➾�'. + '�ﹼﹽ'; + +/** + * Romanization lookup table + * + * This lookup tables provides a way to transform strings written in a language + * different from the ones based upon latin letters into plain ASCII. + * + * Please note: this is not a scientific transliteration table. It only works + * oneway from nonlatin to ASCII and it works by simple character replacement + * only. Specialities of each language are not supported. + * + * @author Andreas Gohr + * @author Vitaly Blokhin + * @link http://www.uconv.com/translit.htm + * @author Bisqwit + * @link http://kanjidict.stc.cx/hiragana.php?src=2 + * @link http://www.translatum.gr/converter/greek-transliteration.htm + * @link http://en.wikipedia.org/wiki/Royal_Thai_General_System_of_Transcription + * @link http://www.btranslations.com/resources/romanization/korean.asp + */ +global $UTF8_ROMANIZATION; +$UTF8_ROMANIZATION = array( + //russian cyrillic + 'а'=>'a','А'=>'A','б'=>'b','Б'=>'B','в'=>'v','В'=>'V','г'=>'g','Г'=>'G', + 'д'=>'d','Д'=>'D','е'=>'e','Е'=>'E','ё'=>'jo','Ё'=>'Jo','ж'=>'zh','Ж'=>'Zh', + 'з'=>'z','З'=>'Z','и'=>'i','И'=>'I','й'=>'j','Й'=>'J','к'=>'k','К'=>'K', + 'л'=>'l','Л'=>'L','м'=>'m','М'=>'M','н'=>'n','Н'=>'N','о'=>'o','О'=>'O', + 'п'=>'p','П'=>'P','р'=>'r','Р'=>'R','с'=>'s','С'=>'S','т'=>'t','Т'=>'T', + 'у'=>'u','У'=>'U','ф'=>'f','Ф'=>'F','х'=>'x','Х'=>'X','ц'=>'c','Ц'=>'C', + 'ч'=>'ch','Ч'=>'Ch','ш'=>'sh','Ш'=>'Sh','щ'=>'sch','Щ'=>'Sch','ъ'=>'', + 'Ъ'=>'','ы'=>'y','Ы'=>'Y','ь'=>'','Ь'=>'','э'=>'eh','Э'=>'Eh','ю'=>'ju', + 'Ю'=>'Ju','я'=>'ja','Я'=>'Ja', + // Ukrainian cyrillic + 'Ґ'=>'Gh','ґ'=>'gh','Є'=>'Je','є'=>'je','І'=>'I','і'=>'i','Ї'=>'Ji','ї'=>'ji', + // Georgian + 'ა'=>'a','ბ'=>'b','გ'=>'g','დ'=>'d','ე'=>'e','ვ'=>'v','ზ'=>'z','თ'=>'th', + 'ი'=>'i','კ'=>'p','ლ'=>'l','მ'=>'m','ნ'=>'n','ო'=>'o','პ'=>'p','ჟ'=>'zh', + 'რ'=>'r','ს'=>'s','ტ'=>'t','უ'=>'u','ფ'=>'ph','ქ'=>'kh','ღ'=>'gh','ყ'=>'q', + 'შ'=>'sh','ჩ'=>'ch','ც'=>'c','ძ'=>'dh','წ'=>'w','ჭ'=>'j','ხ'=>'x','ჯ'=>'jh', + 'ჰ'=>'xh', + //Sanskrit + 'अ'=>'a','आ'=>'ah','इ'=>'i','ई'=>'ih','उ'=>'u','ऊ'=>'uh','ऋ'=>'ry', + 'ॠ'=>'ryh','ऌ'=>'ly','ॡ'=>'lyh','ए'=>'e','ऐ'=>'ay','ओ'=>'o','औ'=>'aw', + 'अं'=>'amh','अः'=>'aq','क'=>'k','ख'=>'kh','ग'=>'g','घ'=>'gh','ङ'=>'nh', + 'च'=>'c','छ'=>'ch','ज'=>'j','झ'=>'jh','ञ'=>'ny','ट'=>'tq','ठ'=>'tqh', + 'ड'=>'dq','ढ'=>'dqh','ण'=>'nq','त'=>'t','थ'=>'th','द'=>'d','ध'=>'dh', + 'न'=>'n','प'=>'p','फ'=>'ph','ब'=>'b','भ'=>'bh','म'=>'m','य'=>'z','र'=>'r', + 'ल'=>'l','व'=>'v','श'=>'sh','ष'=>'sqh','स'=>'s','ह'=>'x', + //Hebrew + 'א'=>'a', 'ב'=>'b','ג'=>'g','ד'=>'d','ה'=>'h','ו'=>'v','ז'=>'z','ח'=>'kh','ט'=>'th', + 'י'=>'y','ך'=>'h','כ'=>'k','ל'=>'l','ם'=>'m','מ'=>'m','ן'=>'n','נ'=>'n', + 'ס'=>'s','ע'=>'ah','ף'=>'f','פ'=>'p','ץ'=>'c','צ'=>'c','ק'=>'q','ר'=>'r', + 'ש'=>'sh','ת'=>'t', + //Arabic + 'ا'=>'a','ب'=>'b','ت'=>'t','ث'=>'th','ج'=>'g','ح'=>'xh','خ'=>'x','د'=>'d', + 'ذ'=>'dh','ر'=>'r','ز'=>'z','س'=>'s','ش'=>'sh','ص'=>'s\'','ض'=>'d\'', + 'ط'=>'t\'','ظ'=>'z\'','ع'=>'y','غ'=>'gh','ف'=>'f','ق'=>'q','ك'=>'k', + 'ل'=>'l','م'=>'m','ن'=>'n','ه'=>'x\'','و'=>'u','ي'=>'i', + + // Japanese hiragana + 'あ'=>'a','え'=>'e','い'=>'i','お'=>'o','う'=>'u','ば'=>'ba','べ'=>'be', + 'び'=>'bi','ぼ'=>'bo','ぶ'=>'bu','し'=>'ci','だ'=>'da','で'=>'de','ぢ'=>'di', + 'ど'=>'do','づ'=>'du','ふぁ'=>'fa','ふぇ'=>'fe','ふぃ'=>'fi','ふぉ'=>'fo', + 'ふ'=>'fu','が'=>'ga','げ'=>'ge','ぎ'=>'gi','ご'=>'go','ぐ'=>'gu','は'=>'ha', + 'へ'=>'he','ひ'=>'hi','ほ'=>'ho','ふ'=>'hu','じゃ'=>'ja','じぇ'=>'je', + 'じ'=>'ji','じょ'=>'jo','じゅ'=>'ju','か'=>'ka','け'=>'ke','き'=>'ki', + 'こ'=>'ko','く'=>'ku','ら'=>'la','れ'=>'le','り'=>'li','ろ'=>'lo','る'=>'lu', + 'ま'=>'ma','め'=>'me','み'=>'mi','も'=>'mo','む'=>'mu','な'=>'na','ね'=>'ne', + 'に'=>'ni','の'=>'no','ぬ'=>'nu','ぱ'=>'pa','ぺ'=>'pe','ぴ'=>'pi','ぽ'=>'po', + 'ぷ'=>'pu','ら'=>'ra','れ'=>'re','り'=>'ri','ろ'=>'ro','る'=>'ru','さ'=>'sa', + 'せ'=>'se','し'=>'si','そ'=>'so','す'=>'su','た'=>'ta','て'=>'te','ち'=>'ti', + 'と'=>'to','つ'=>'tu','ヴぁ'=>'va','ヴぇ'=>'ve','ヴぃ'=>'vi','ヴぉ'=>'vo', + 'ヴ'=>'vu','わ'=>'wa','うぇ'=>'we','うぃ'=>'wi','を'=>'wo','や'=>'ya','いぇ'=>'ye', + 'い'=>'yi','よ'=>'yo','ゆ'=>'yu','ざ'=>'za','ぜ'=>'ze','じ'=>'zi','ぞ'=>'zo', + 'ず'=>'zu','びゃ'=>'bya','びぇ'=>'bye','びぃ'=>'byi','びょ'=>'byo','びゅ'=>'byu', + 'ちゃ'=>'cha','ちぇ'=>'che','ち'=>'chi','ちょ'=>'cho','ちゅ'=>'chu','ちゃ'=>'cya', + 'ちぇ'=>'cye','ちぃ'=>'cyi','ちょ'=>'cyo','ちゅ'=>'cyu','でゃ'=>'dha','でぇ'=>'dhe', + 'でぃ'=>'dhi','でょ'=>'dho','でゅ'=>'dhu','どぁ'=>'dwa','どぇ'=>'dwe','どぃ'=>'dwi', + 'どぉ'=>'dwo','どぅ'=>'dwu','ぢゃ'=>'dya','ぢぇ'=>'dye','ぢぃ'=>'dyi','ぢょ'=>'dyo', + 'ぢゅ'=>'dyu','ぢ'=>'dzi','ふぁ'=>'fwa','ふぇ'=>'fwe','ふぃ'=>'fwi','ふぉ'=>'fwo', + 'ふぅ'=>'fwu','ふゃ'=>'fya','ふぇ'=>'fye','ふぃ'=>'fyi','ふょ'=>'fyo','ふゅ'=>'fyu', + 'ぎゃ'=>'gya','ぎぇ'=>'gye','ぎぃ'=>'gyi','ぎょ'=>'gyo','ぎゅ'=>'gyu','ひゃ'=>'hya', + 'ひぇ'=>'hye','ひぃ'=>'hyi','ひょ'=>'hyo','ひゅ'=>'hyu','じゃ'=>'jya','じぇ'=>'jye', + 'じぃ'=>'jyi','じょ'=>'jyo','じゅ'=>'jyu','きゃ'=>'kya','きぇ'=>'kye','きぃ'=>'kyi', + 'きょ'=>'kyo','きゅ'=>'kyu','りゃ'=>'lya','りぇ'=>'lye','りぃ'=>'lyi','りょ'=>'lyo', + 'りゅ'=>'lyu','みゃ'=>'mya','みぇ'=>'mye','みぃ'=>'myi','みょ'=>'myo','みゅ'=>'myu', + 'ん'=>'n','にゃ'=>'nya','にぇ'=>'nye','にぃ'=>'nyi','にょ'=>'nyo','にゅ'=>'nyu', + 'ぴゃ'=>'pya','ぴぇ'=>'pye','ぴぃ'=>'pyi','ぴょ'=>'pyo','ぴゅ'=>'pyu','りゃ'=>'rya', + 'りぇ'=>'rye','りぃ'=>'ryi','りょ'=>'ryo','りゅ'=>'ryu','しゃ'=>'sha','しぇ'=>'she', + 'し'=>'shi','しょ'=>'sho','しゅ'=>'shu','すぁ'=>'swa','すぇ'=>'swe','すぃ'=>'swi', + 'すぉ'=>'swo','すぅ'=>'swu','しゃ'=>'sya','しぇ'=>'sye','しぃ'=>'syi','しょ'=>'syo', + 'しゅ'=>'syu','てゃ'=>'tha','てぇ'=>'the','てぃ'=>'thi','てょ'=>'tho','てゅ'=>'thu', + 'つゃ'=>'tsa','つぇ'=>'tse','つぃ'=>'tsi','つょ'=>'tso','つ'=>'tsu','とぁ'=>'twa', + 'とぇ'=>'twe','とぃ'=>'twi','とぉ'=>'two','とぅ'=>'twu','ちゃ'=>'tya','ちぇ'=>'tye', + 'ちぃ'=>'tyi','ちょ'=>'tyo','ちゅ'=>'tyu','ヴゃ'=>'vya','ヴぇ'=>'vye','ヴぃ'=>'vyi', + 'ヴょ'=>'vyo','ヴゅ'=>'vyu','うぁ'=>'wha','うぇ'=>'whe','うぃ'=>'whi','うぉ'=>'who', + 'うぅ'=>'whu','ゑ'=>'wye','ゐ'=>'wyi','じゃ'=>'zha','じぇ'=>'zhe','じぃ'=>'zhi', + 'じょ'=>'zho','じゅ'=>'zhu','じゃ'=>'zya','じぇ'=>'zye','じぃ'=>'zyi','じょ'=>'zyo', + 'じゅ'=>'zyu', + // Japanese katakana + 'ア'=>'a','エ'=>'e','イ'=>'i','オ'=>'o','ウ'=>'u','バ'=>'ba','ベ'=>'be','ビ'=>'bi', + 'ボ'=>'bo','ブ'=>'bu','シ'=>'ci','ダ'=>'da','デ'=>'de','ヂ'=>'di','ド'=>'do', + 'ヅ'=>'du','ファ'=>'fa','フェ'=>'fe','フィ'=>'fi','フォ'=>'fo','フ'=>'fu','ガ'=>'ga', + 'ゲ'=>'ge','ギ'=>'gi','ゴ'=>'go','グ'=>'gu','ハ'=>'ha','ヘ'=>'he','ヒ'=>'hi','ホ'=>'ho', + 'フ'=>'hu','ジャ'=>'ja','ジェ'=>'je','ジ'=>'ji','ジョ'=>'jo','ジュ'=>'ju','カ'=>'ka', + 'ケ'=>'ke','キ'=>'ki','コ'=>'ko','ク'=>'ku','ラ'=>'la','レ'=>'le','リ'=>'li','ロ'=>'lo', + 'ル'=>'lu','マ'=>'ma','メ'=>'me','ミ'=>'mi','モ'=>'mo','ム'=>'mu','ナ'=>'na','ネ'=>'ne', + 'ニ'=>'ni','ノ'=>'no','ヌ'=>'nu','パ'=>'pa','ペ'=>'pe','ピ'=>'pi','ポ'=>'po','プ'=>'pu', + 'ラ'=>'ra','レ'=>'re','リ'=>'ri','ロ'=>'ro','ル'=>'ru','サ'=>'sa','セ'=>'se','シ'=>'si', + 'ソ'=>'so','ス'=>'su','タ'=>'ta','テ'=>'te','チ'=>'ti','ト'=>'to','ツ'=>'tu','ヴァ'=>'va', + 'ヴェ'=>'ve','ヴィ'=>'vi','ヴォ'=>'vo','ヴ'=>'vu','ワ'=>'wa','ウェ'=>'we','ウィ'=>'wi', + 'ヲ'=>'wo','ヤ'=>'ya','イェ'=>'ye','イ'=>'yi','ヨ'=>'yo','ユ'=>'yu','ザ'=>'za','ゼ'=>'ze', + 'ジ'=>'zi','ゾ'=>'zo','ズ'=>'zu','ビャ'=>'bya','ビェ'=>'bye','ビィ'=>'byi','ビョ'=>'byo', + 'ビュ'=>'byu','チャ'=>'cha','チェ'=>'che','チ'=>'chi','チョ'=>'cho','チュ'=>'chu', + 'チャ'=>'cya','チェ'=>'cye','チィ'=>'cyi','チョ'=>'cyo','チュ'=>'cyu','デャ'=>'dha', + 'デェ'=>'dhe','ディ'=>'dhi','デョ'=>'dho','デュ'=>'dhu','ドァ'=>'dwa','ドェ'=>'dwe', + 'ドィ'=>'dwi','ドォ'=>'dwo','ドゥ'=>'dwu','ヂャ'=>'dya','ヂェ'=>'dye','ヂィ'=>'dyi', + 'ヂョ'=>'dyo','ヂュ'=>'dyu','ヂ'=>'dzi','ファ'=>'fwa','フェ'=>'fwe','フィ'=>'fwi', + 'フォ'=>'fwo','フゥ'=>'fwu','フャ'=>'fya','フェ'=>'fye','フィ'=>'fyi','フョ'=>'fyo', + 'フュ'=>'fyu','ギャ'=>'gya','ギェ'=>'gye','ギィ'=>'gyi','ギョ'=>'gyo','ギュ'=>'gyu', + 'ヒャ'=>'hya','ヒェ'=>'hye','ヒィ'=>'hyi','ヒョ'=>'hyo','ヒュ'=>'hyu','ジャ'=>'jya', + 'ジェ'=>'jye','ジィ'=>'jyi','ジョ'=>'jyo','ジュ'=>'jyu','キャ'=>'kya','キェ'=>'kye', + 'キィ'=>'kyi','キョ'=>'kyo','キュ'=>'kyu','リャ'=>'lya','リェ'=>'lye','リィ'=>'lyi', + 'リョ'=>'lyo','リュ'=>'lyu','ミャ'=>'mya','ミェ'=>'mye','ミィ'=>'myi','ミョ'=>'myo', + 'ミュ'=>'myu','ン'=>'n','ニャ'=>'nya','ニェ'=>'nye','ニィ'=>'nyi','ニョ'=>'nyo', + 'ニュ'=>'nyu','ピャ'=>'pya','ピェ'=>'pye','ピィ'=>'pyi','ピョ'=>'pyo','ピュ'=>'pyu', + 'リャ'=>'rya','リェ'=>'rye','リィ'=>'ryi','リョ'=>'ryo','リュ'=>'ryu','シャ'=>'sha', + 'シェ'=>'she','シ'=>'shi','ショ'=>'sho','シュ'=>'shu','スァ'=>'swa','スェ'=>'swe', + 'スィ'=>'swi','スォ'=>'swo','スゥ'=>'swu','シャ'=>'sya','シェ'=>'sye','シィ'=>'syi', + 'ショ'=>'syo','シュ'=>'syu','テャ'=>'tha','テェ'=>'the','ティ'=>'thi','テョ'=>'tho', + 'テュ'=>'thu','ツャ'=>'tsa','ツェ'=>'tse','ツィ'=>'tsi','ツョ'=>'tso','ツ'=>'tsu', + 'トァ'=>'twa','トェ'=>'twe','トィ'=>'twi','トォ'=>'two','トゥ'=>'twu','チャ'=>'tya', + 'チェ'=>'tye','チィ'=>'tyi','チョ'=>'tyo','チュ'=>'tyu','ヴャ'=>'vya','ヴェ'=>'vye', + 'ヴィ'=>'vyi','ヴョ'=>'vyo','ヴュ'=>'vyu','ウァ'=>'wha','ウェ'=>'whe','ウィ'=>'whi', + 'ウォ'=>'who','ウゥ'=>'whu','ヱ'=>'wye','ヰ'=>'wyi','ジャ'=>'zha','ジェ'=>'zhe', + 'ジィ'=>'zhi','ジョ'=>'zho','ジュ'=>'zhu','ジャ'=>'zya','ジェ'=>'zye','ジィ'=>'zyi', + 'ジョ'=>'zyo','ジュ'=>'zyu', + + // "Greeklish" + 'Γ'=>'G','Δ'=>'E','Θ'=>'Th','Λ'=>'L','Ξ'=>'X','Π'=>'P','Σ'=>'S','Φ'=>'F','Ψ'=>'Ps', + 'γ'=>'g','δ'=>'e','θ'=>'th','λ'=>'l','ξ'=>'x','π'=>'p','σ'=>'s','φ'=>'f','ψ'=>'ps', + + // Thai + 'ก'=>'k','ข'=>'kh','ฃ'=>'kh','ค'=>'kh','ฅ'=>'kh','ฆ'=>'kh','ง'=>'ng','จ'=>'ch', + 'ฉ'=>'ch','ช'=>'ch','ซ'=>'s','ฌ'=>'ch','ญ'=>'y','ฎ'=>'d','ฏ'=>'t','ฐ'=>'th', + 'ฑ'=>'d','ฒ'=>'th','ณ'=>'n','ด'=>'d','ต'=>'t','ถ'=>'th','ท'=>'th','ธ'=>'th', + 'น'=>'n','บ'=>'b','ป'=>'p','ผ'=>'ph','ฝ'=>'f','พ'=>'ph','ฟ'=>'f','ภ'=>'ph', + 'ม'=>'m','ย'=>'y','ร'=>'r','ฤ'=>'rue','ฤๅ'=>'rue','ล'=>'l','ฦ'=>'lue', + 'ฦๅ'=>'lue','ว'=>'w','ศ'=>'s','ษ'=>'s','ส'=>'s','ห'=>'h','ฬ'=>'l','ฮ'=>'h', + 'ะ'=>'a','–ั'=>'a','รร'=>'a','า'=>'a','รร'=>'an','ำ'=>'am','–ิ'=>'i','–ี'=>'i', + '–ึ'=>'ue','–ื'=>'ue','–ุ'=>'u','–ู'=>'u','เะ'=>'e','เ–็'=>'e','เ'=>'e','แะ'=>'ae', + 'แ'=>'ae','โะ'=>'o','โ'=>'o','เาะ'=>'o','อ'=>'o','เอะ'=>'oe','เ–ิ'=>'oe', + 'เอ'=>'oe','เ–ียะ'=>'ia','เ–ีย'=>'ia','เ–ือะ'=>'uea','เ–ือ'=>'uea','–ัวะ'=>'ua', + '–ัว'=>'ua','ว'=>'ua','ใ'=>'ai','ไ'=>'ai','–ัย'=>'ai','ไย'=>'ai','าย'=>'ai', + 'เา'=>'ao','าว'=>'ao','–ุย'=>'ui','โย'=>'oi','อย'=>'oi','เย'=>'oei','เ–ือย'=>'ueai', + 'วย'=>'uai','–ิว'=>'io','เ–็ว'=>'eo','เว'=>'eo','แ–็ว'=>'aeo','แว'=>'aeo', + 'เ–ียว'=>'iao', + + // Korean + 'ㄱ'=>'k','ㅋ'=>'kh','ㄲ'=>'kk','ㄷ'=>'t','ㅌ'=>'th','ㄸ'=>'tt','ㅂ'=>'p', + 'ㅍ'=>'ph','ㅃ'=>'pp','ㅈ'=>'c','ㅊ'=>'ch','ㅉ'=>'cc','ㅅ'=>'s','ㅆ'=>'ss', + 'ㅎ'=>'h','ㅇ'=>'ng','ㄴ'=>'n','ㄹ'=>'l','ㅁ'=>'m', 'ㅏ'=>'a','ㅓ'=>'e','ㅗ'=>'o', + 'ㅜ'=>'wu','ㅡ'=>'u','ㅣ'=>'i','ㅐ'=>'ay','ㅔ'=>'ey','ㅚ'=>'oy','ㅘ'=>'wa','ㅝ'=>'we', + 'ㅟ'=>'wi','ㅙ'=>'way','ㅞ'=>'wey','ㅢ'=>'uy','ㅑ'=>'ya','ㅕ'=>'ye','ㅛ'=>'oy', + 'ㅠ'=>'yu','ㅒ'=>'yay','ㅖ'=>'yey', +); + +//Setup VIM: ex: et ts=2 enc=utf-8 : + diff --git a/plugins/dokuwiki/lib/exe/fetch.php b/plugins/dokuwiki/lib/exe/fetch.php new file mode 100644 index 0000000..59e59ca --- /dev/null +++ b/plugins/dokuwiki/lib/exe/fetch.php @@ -0,0 +1,433 @@ + + */ + +# security hotfix +die(); + + if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); + define('DOKU_DISABLE_GZIP_OUTPUT', 1); + require_once(DOKU_INC.'inc/init.php'); + require_once(DOKU_INC.'inc/common.php'); + require_once(DOKU_INC.'inc/pageutils.php'); + require_once(DOKU_INC.'inc/confutils.php'); + //close sesseion + session_write_close(); + if(!defined('CHUNK_SIZE')) define('CHUNK_SIZE',16*1024); + + $mimetypes = getMimeTypes(); + + //get input + $MEDIA = stripctl(getID('media',false)); // no cleaning except control chars - maybe external + $CACHE = calc_cache($_REQUEST['cache']); + $WIDTH = (int) $_REQUEST['w']; + $HEIGHT = (int) $_REQUEST['h']; + list($EXT,$MIME) = mimetype($MEDIA); + if($EXT === false){ + $EXT = 'unknown'; + $MIME = 'application/octet-stream'; + } + + //media to local file + if(preg_match('#^(https?)://#i',$MEDIA)){ + //handle external images + if(strncmp($MIME,'image/',6) == 0) $FILE = get_from_URL($MEDIA,$EXT,$CACHE); + if(!$FILE){ + //download failed - redirect to original URL + header('Location: '.$MEDIA); + exit; + } + }else{ + $MEDIA = cleanID($MEDIA); + if(empty($MEDIA)){ + header("HTTP/1.0 400 Bad Request"); + print 'Bad request'; + exit; + } + + $FILE = mediaFN($MEDIA); + } + + //check file existance + if(!@file_exists($FILE)){ + header("HTTP/1.0 404 Not Found"); + //FIXME add some default broken image + print 'Not Found'; + exit; + } + + //handle image resizing + if((substr($MIME,0,5) == 'image') && $WIDTH){ + $FILE = get_resized($FILE,$EXT,$WIDTH,$HEIGHT); + } + + // finally send the file to the client + sendFile($FILE,$MIME,$CACHE); + +/* ------------------------------------------------------------------------ */ + +/** + * Set headers and send the file to the client + * + * @author Andreas Gohr + * @author Ben Coburn + */ +function sendFile($file,$mime,$cache){ + global $conf; + $fmtime = filemtime($file); + // send headers + header("Content-Type: $mime"); + // smart http caching headers + if ($cache==-1) { + // cache + // cachetime or one hour + header('Expires: '.gmdate("D, d M Y H:i:s", time()+max($conf['cachetime'], 3600)).' GMT'); + header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.max($conf['cachetime'], 3600)); + header('Pragma: public'); + } else if ($cache>0) { + // recache + // remaining cachetime + 10 seconds so the newly recached media is used + header('Expires: '.gmdate("D, d M Y H:i:s", $fmtime+$conf['cachetime']+10).' GMT'); + header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.max($fmtime-time()+$conf['cachetime']+10, 0)); + header('Pragma: public'); + } else if ($cache==0) { + // nocache + header('Cache-Control: must-revalidate, no-transform, post-check=0, pre-check=0'); + header('Pragma: public'); + } + header('Accept-Ranges: bytes'); + //send important headers first, script stops here if '304 Not Modified' response + http_conditionalRequest($fmtime); + list($start,$len) = http_rangeRequest(filesize($file)); + + //application mime type is downloadable + if(substr($mime,0,11) == 'application'){ + header('Content-Disposition: attachment; filename="'.basename($file).'";'); + } + + // send file contents + $fp = @fopen($file,"rb"); + if($fp){ + fseek($fp,$start); //seek to start of range + + $chunk = ($len > CHUNK_SIZE) ? CHUNK_SIZE : $len; + while (!feof($fp) && $chunk > 0) { + @set_time_limit(); // large files can take a lot of time + print fread($fp, $chunk); + flush(); + $len -= $chunk; + $chunk = ($len > CHUNK_SIZE) ? CHUNK_SIZE : $len; + } + fclose($fp); + }else{ + header("HTTP/1.0 500 Internal Server Error"); + print "Could not read $file - bad permissions?"; + } +} + +/** + * Checks and sets headers to handle range requets + * + * @author Andreas Gohr + * @returns array The start byte and the amount of bytes to send + */ +function http_rangeRequest($size){ + if(!isset($_SERVER['HTTP_RANGE'])){ + // no range requested - send the whole file + header("Content-Length: $size"); + return array(0,$size); + } + + $t = explode('=', $_SERVER['HTTP_RANGE']); + if (!$t[0]=='bytes') { + // we only understand byte ranges - send the whole file + header("Content-Length: $size"); + return array(0,$size); + } + + $r = explode('-', $t[1]); + $start = (int)$r[0]; + $end = (int)$r[1]; + if (!$end) $end = $size - 1; + if ($start > $end || $start > $size || $end > $size){ + header('HTTP/1.1 416 Requested Range Not Satisfiable'); + print 'Bad Range Request!'; + exit; + } + + $tot = $end - $start + 1; + header('HTTP/1.1 206 Partial Content'); + header("Content-Range: bytes {$start}-{$end}/{$size}"); + header("Content-Length: $tot"); + + return array($start,$tot); +} + +/** + * Resizes the given image to the given size + * + * @author Andreas Gohr + */ +function get_resized($file, $ext, $w, $h=0){ + global $conf; + + $info = getimagesize($file); + if(!$h) $h = round(($w * $info[1]) / $info[0]); + + // we wont scale up to infinity + if($w > 2000 || $h > 2000) return $file; + + //cache + $local = getCacheName($file,'.media.'.$w.'x'.$h.'.'.$ext); + $mtime = @filemtime($local); // 0 if not exists + + if( $mtime > filemtime($file) || + resize_imageIM($ext,$file,$info[0],$info[1],$local,$w,$h) || + resize_imageGD($ext,$file,$info[0],$info[1],$local,$w,$h) ){ + return $local; + } + //still here? resizing failed + return $file; +} + +/** + * Returns the wanted cachetime in seconds + * + * Resolves named constants + * + * @author Andreas Gohr + */ +function calc_cache($cache){ + global $conf; + + if(strtolower($cache) == 'nocache') return 0; //never cache + if(strtolower($cache) == 'recache') return $conf['cachetime']; //use standard cache + return -1; //cache endless +} + +/** + * Download a remote file and return local filename + * + * returns false if download fails. Uses cached file if available and + * wanted + * + * @author Andreas Gohr + * @author Pavel Vitis + */ +function get_from_URL($url,$ext,$cache){ + global $conf; + + // if no cache or fetchsize just redirect + if ($cache==0) return false; + if (!$conf['fetchsize']) return false; + + $local = getCacheName(strtolower($url),".media.$ext"); + $mtime = @filemtime($local); // 0 if not exists + + //decide if download needed: + if( ($mtime == 0) || // cache does not exist + ($cache != -1 && $mtime < time()-$cache) // 'recache' and cache has expired + ){ + if(image_download($url,$local)){ + return $local; + }else{ + return false; + } + } + + //if cache exists use it else + if($mtime) return $local; + + //else return false + return false; +} + +/** + * Download image files + * + * @author Andreas Gohr + */ +function image_download($url,$file){ + global $conf; + $http = new DokuHTTPClient(); + $http->max_bodysize = $conf['fetchsize']; + $http->timeout = 25; //max. 25 sec + $http->header_regexp = '!\r\nContent-Type: image/(jpe?g|gif|png)!i'; + + $data = $http->get($url); + if(!$data) return false; + + $fileexists = @file_exists($file); + $fp = @fopen($file,"w"); + if(!$fp) return false; + fwrite($fp,$data); + fclose($fp); + if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']); + + // check if it is really an image + $info = @getimagesize($file); + if(!$info){ + @unlink($file); + return false; + } + + return true; +} + +/** + * resize images using external ImageMagick convert program + * + * @author Pavel Vitis + * @author Andreas Gohr + */ +function resize_imageIM($ext,$from,$from_w,$from_h,$to,$to_w,$to_h){ + global $conf; + + // check if convert is configured + if(!$conf['im_convert']) return false; + + // prepare command + $cmd = $conf['im_convert']; + $cmd .= ' -resize '.$to_w.'x'.$to_h.'!'; + if ($ext == 'jpg' || $ext == 'jpeg') { + $cmd .= ' -quality '.$conf['jpg_quality']; + } + $cmd .= " $from $to"; + + @exec($cmd,$out,$retval); + if ($retval == 0) return true; + return false; +} + +/** + * resize images using PHP's libGD support + * + * @author Andreas Gohr + */ +function resize_imageGD($ext,$from,$from_w,$from_h,$to,$to_w,$to_h){ + global $conf; + + if($conf['gdlib'] < 1) return false; //no GDlib available or wanted + + // check available memory + if(!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))){ + return false; + } + + // create an image of the given filetype + if ($ext == 'jpg' || $ext == 'jpeg'){ + if(!function_exists("imagecreatefromjpeg")) return false; + $image = @imagecreatefromjpeg($from); + }elseif($ext == 'png') { + if(!function_exists("imagecreatefrompng")) return false; + $image = @imagecreatefrompng($from); + + }elseif($ext == 'gif') { + if(!function_exists("imagecreatefromgif")) return false; + $image = @imagecreatefromgif($from); + } + if(!$image) return false; + + if(($conf['gdlib']>1) && function_exists("imagecreatetruecolor")){ + $newimg = @imagecreatetruecolor ($to_w, $to_h); + } + if(!$newimg) $newimg = @imagecreate($to_w, $to_h); + if(!$newimg){ + imagedestroy($image); + return false; + } + + //keep png alpha channel if possible + if($ext == 'png' && $conf['gdlib']>1 && function_exists('imagesavealpha')){ + imagealphablending($newimg, false); + imagesavealpha($newimg,true); + } + + //try resampling first + if(function_exists("imagecopyresampled")){ + if(!@imagecopyresampled($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h)) { + imagecopyresized($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h); + } + }else{ + imagecopyresized($newimg, $image, 0, 0, 0, 0, $to_w, $to_h, $from_w, $from_h); + } + + $okay = false; + if ($ext == 'jpg' || $ext == 'jpeg'){ + if(!function_exists('imagejpeg')){ + $okay = false; + }else{ + $okay = imagejpeg($newimg, $to, $conf['jpg_quality']); + } + }elseif($ext == 'png') { + if(!function_exists('imagepng')){ + $okay = false; + }else{ + $okay = imagepng($newimg, $to); + } + }elseif($ext == 'gif') { + if(!function_exists('imagegif')){ + $okay = false; + }else{ + $okay = imagegif($newimg, $to); + } + } + + // destroy GD image ressources + if($image) imagedestroy($image); + if($newimg) imagedestroy($newimg); + + return $okay; +} + +/** + * Checks if the given amount of memory is available + * + * If the memory_get_usage() function is not available the + * function just assumes $used bytes of already allocated memory + * + * @param int $mem Size of memory you want to allocate in bytes + * @param int $used already allocated memory (see above) + * @author Filip Oscadal + * @author Andreas Gohr + */ +function is_mem_available($mem,$bytes=1048576){ + $limit = trim(ini_get('memory_limit')); + if(empty($limit)) return true; // no limit set! + + // parse limit to bytes + $unit = strtolower(substr($limit,-1)); + switch($unit){ + case 'g': + $limit = substr($limit,0,-1); + $limit *= 1024*1024*1024; + break; + case 'm': + $limit = substr($limit,0,-1); + $limit *= 1024*1024; + break; + case 'k': + $limit = substr($limit,0,-1); + $limit *= 1024; + break; + } + + // get used memory if possible + if(function_exists('memory_get_usage')){ + $used = memory_get_usage(); + } + + + if($used+$mem > $limit){ + return false; + } + + return true; +} + +//Setup VIM: ex: et ts=2 enc=utf-8 : +?> diff --git a/plugins/dokuwiki/lib/images/fileicons/bz2.png b/plugins/dokuwiki/lib/images/fileicons/bz2.png new file mode 100644 index 0000000..d48cae0 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/bz2.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/conf.png b/plugins/dokuwiki/lib/images/fileicons/conf.png new file mode 100644 index 0000000..ddffe6f Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/conf.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/deb.png b/plugins/dokuwiki/lib/images/fileicons/deb.png new file mode 100644 index 0000000..9229d87 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/deb.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/doc.png b/plugins/dokuwiki/lib/images/fileicons/doc.png new file mode 100644 index 0000000..932567f Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/doc.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/file.gif b/plugins/dokuwiki/lib/images/fileicons/file.gif new file mode 100644 index 0000000..815ccb1 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/file.gif differ diff --git a/plugins/dokuwiki/lib/images/fileicons/file.png b/plugins/dokuwiki/lib/images/fileicons/file.png new file mode 100644 index 0000000..817014f Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/file.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/gif.png b/plugins/dokuwiki/lib/images/fileicons/gif.png new file mode 100644 index 0000000..b4c07a9 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/gif.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/gz.png b/plugins/dokuwiki/lib/images/fileicons/gz.png new file mode 100644 index 0000000..2426bd1 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/gz.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/htm.png b/plugins/dokuwiki/lib/images/fileicons/htm.png new file mode 100644 index 0000000..1a68121 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/htm.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/html.png b/plugins/dokuwiki/lib/images/fileicons/html.png new file mode 100644 index 0000000..672cbce Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/html.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/index.php b/plugins/dokuwiki/lib/images/fileicons/index.php new file mode 100644 index 0000000..805b36d --- /dev/null +++ b/plugins/dokuwiki/lib/images/fileicons/index.php @@ -0,0 +1,49 @@ + + + filetype icons + + + + + + +
    + '; +} +?> +
    + +
    + '; +} +?> +
    + + + diff --git a/plugins/dokuwiki/lib/images/fileicons/jpeg.png b/plugins/dokuwiki/lib/images/fileicons/jpeg.png new file mode 100644 index 0000000..aa4cc23 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/jpeg.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/jpg.png b/plugins/dokuwiki/lib/images/fileicons/jpg.png new file mode 100644 index 0000000..1fb6cc1 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/jpg.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/odc.png b/plugins/dokuwiki/lib/images/fileicons/odc.png new file mode 100644 index 0000000..47f65c8 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/odc.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/odf.png b/plugins/dokuwiki/lib/images/fileicons/odf.png new file mode 100644 index 0000000..a2fbc51 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/odf.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/odg.png b/plugins/dokuwiki/lib/images/fileicons/odg.png new file mode 100644 index 0000000..434f182 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/odg.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/odi.png b/plugins/dokuwiki/lib/images/fileicons/odi.png new file mode 100644 index 0000000..74f6303 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/odi.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/odp.png b/plugins/dokuwiki/lib/images/fileicons/odp.png new file mode 100644 index 0000000..a5c77f8 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/odp.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/ods.png b/plugins/dokuwiki/lib/images/fileicons/ods.png new file mode 100644 index 0000000..2ab1273 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/ods.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/odt.png b/plugins/dokuwiki/lib/images/fileicons/odt.png new file mode 100644 index 0000000..b0c21fc Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/odt.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/pdf.png b/plugins/dokuwiki/lib/images/fileicons/pdf.png new file mode 100644 index 0000000..638066d Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/pdf.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/png.png b/plugins/dokuwiki/lib/images/fileicons/png.png new file mode 100644 index 0000000..f0b5b00 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/png.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/ppt.png b/plugins/dokuwiki/lib/images/fileicons/ppt.png new file mode 100644 index 0000000..adaefc6 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/ppt.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/ps.png b/plugins/dokuwiki/lib/images/fileicons/ps.png new file mode 100644 index 0000000..c51c763 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/ps.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/rpm.png b/plugins/dokuwiki/lib/images/fileicons/rpm.png new file mode 100644 index 0000000..22212ea Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/rpm.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/rtf.png b/plugins/dokuwiki/lib/images/fileicons/rtf.png new file mode 100644 index 0000000..d8bada5 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/rtf.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/swf.png b/plugins/dokuwiki/lib/images/fileicons/swf.png new file mode 100644 index 0000000..0729ed0 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/swf.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/sxc.png b/plugins/dokuwiki/lib/images/fileicons/sxc.png new file mode 100644 index 0000000..419c183 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/sxc.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/sxd.png b/plugins/dokuwiki/lib/images/fileicons/sxd.png new file mode 100644 index 0000000..5801bb2 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/sxd.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/sxi.png b/plugins/dokuwiki/lib/images/fileicons/sxi.png new file mode 100644 index 0000000..2a94290 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/sxi.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/sxw.png b/plugins/dokuwiki/lib/images/fileicons/sxw.png new file mode 100644 index 0000000..6da97be Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/sxw.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/tar.png b/plugins/dokuwiki/lib/images/fileicons/tar.png new file mode 100644 index 0000000..5a2f717 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/tar.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/tgz.png b/plugins/dokuwiki/lib/images/fileicons/tgz.png new file mode 100644 index 0000000..141acf5 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/tgz.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/txt.png b/plugins/dokuwiki/lib/images/fileicons/txt.png new file mode 100644 index 0000000..da20009 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/txt.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/xls.png b/plugins/dokuwiki/lib/images/fileicons/xls.png new file mode 100644 index 0000000..e8cd58d Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/xls.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/xml.png b/plugins/dokuwiki/lib/images/fileicons/xml.png new file mode 100644 index 0000000..eb46323 Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/xml.png differ diff --git a/plugins/dokuwiki/lib/images/fileicons/zip.png b/plugins/dokuwiki/lib/images/fileicons/zip.png new file mode 100644 index 0000000..999ffbe Binary files /dev/null and b/plugins/dokuwiki/lib/images/fileicons/zip.png differ diff --git a/plugins/dokuwiki/lib/images/interwiki/amazon.de.gif b/plugins/dokuwiki/lib/images/interwiki/amazon.de.gif new file mode 100644 index 0000000..f52c1c5 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/amazon.de.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/amazon.gif b/plugins/dokuwiki/lib/images/interwiki/amazon.gif new file mode 100644 index 0000000..f52c1c5 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/amazon.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/amazon.uk.gif b/plugins/dokuwiki/lib/images/interwiki/amazon.uk.gif new file mode 100644 index 0000000..f52c1c5 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/amazon.uk.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/bug.gif b/plugins/dokuwiki/lib/images/interwiki/bug.gif new file mode 100644 index 0000000..3432b8d Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/bug.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/coral.gif b/plugins/dokuwiki/lib/images/interwiki/coral.gif new file mode 100644 index 0000000..0f9f675 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/coral.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/doku.gif b/plugins/dokuwiki/lib/images/interwiki/doku.gif new file mode 100644 index 0000000..7dc4248 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/doku.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/google.gif b/plugins/dokuwiki/lib/images/interwiki/google.gif new file mode 100644 index 0000000..fb39f61 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/google.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/meatball.gif b/plugins/dokuwiki/lib/images/interwiki/meatball.gif new file mode 100644 index 0000000..7ac5454 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/meatball.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/phpfn.gif b/plugins/dokuwiki/lib/images/interwiki/phpfn.gif new file mode 100644 index 0000000..638d4c4 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/phpfn.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/sb.gif b/plugins/dokuwiki/lib/images/interwiki/sb.gif new file mode 100644 index 0000000..e272a29 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/sb.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/wiki.gif b/plugins/dokuwiki/lib/images/interwiki/wiki.gif new file mode 100644 index 0000000..e8dc5d2 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/wiki.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/wp.gif b/plugins/dokuwiki/lib/images/interwiki/wp.gif new file mode 100644 index 0000000..ca853b8 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/wp.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/wpde.gif b/plugins/dokuwiki/lib/images/interwiki/wpde.gif new file mode 100644 index 0000000..ca853b8 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/wpde.gif differ diff --git a/plugins/dokuwiki/lib/images/interwiki/wpmeta.gif b/plugins/dokuwiki/lib/images/interwiki/wpmeta.gif new file mode 100644 index 0000000..ca853b8 Binary files /dev/null and b/plugins/dokuwiki/lib/images/interwiki/wpmeta.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/delete.gif b/plugins/dokuwiki/lib/images/smileys/delete.gif new file mode 100644 index 0000000..d668348 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/delete.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/fixme.gif b/plugins/dokuwiki/lib/images/smileys/fixme.gif new file mode 100644 index 0000000..b66ea99 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/fixme.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_arrow.gif b/plugins/dokuwiki/lib/images/smileys/icon_arrow.gif new file mode 100644 index 0000000..2880055 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_arrow.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_biggrin.gif b/plugins/dokuwiki/lib/images/smileys/icon_biggrin.gif new file mode 100644 index 0000000..d352772 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_biggrin.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_confused.gif b/plugins/dokuwiki/lib/images/smileys/icon_confused.gif new file mode 100644 index 0000000..0c49e06 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_confused.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_cool.gif b/plugins/dokuwiki/lib/images/smileys/icon_cool.gif new file mode 100644 index 0000000..cead030 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_cool.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_cry.gif b/plugins/dokuwiki/lib/images/smileys/icon_cry.gif new file mode 100644 index 0000000..7d54b1f Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_cry.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_doubt.gif b/plugins/dokuwiki/lib/images/smileys/icon_doubt.gif new file mode 100644 index 0000000..fd7903b Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_doubt.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_doubt2.gif b/plugins/dokuwiki/lib/images/smileys/icon_doubt2.gif new file mode 100644 index 0000000..eb4b70b Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_doubt2.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_eek.gif b/plugins/dokuwiki/lib/images/smileys/icon_eek.gif new file mode 100644 index 0000000..5d39781 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_eek.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_evil.gif b/plugins/dokuwiki/lib/images/smileys/icon_evil.gif new file mode 100644 index 0000000..ab1aa8e Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_evil.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_exclaim.gif b/plugins/dokuwiki/lib/images/smileys/icon_exclaim.gif new file mode 100644 index 0000000..6e50e2e Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_exclaim.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_frown.gif b/plugins/dokuwiki/lib/images/smileys/icon_frown.gif new file mode 100644 index 0000000..d2ac78c Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_frown.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_fun.gif b/plugins/dokuwiki/lib/images/smileys/icon_fun.gif new file mode 100644 index 0000000..a8bb8a3 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_fun.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_idea.gif b/plugins/dokuwiki/lib/images/smileys/icon_idea.gif new file mode 100644 index 0000000..a40ae0d Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_idea.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_kaddi.gif b/plugins/dokuwiki/lib/images/smileys/icon_kaddi.gif new file mode 100644 index 0000000..1410f7f Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_kaddi.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_lol.gif b/plugins/dokuwiki/lib/images/smileys/icon_lol.gif new file mode 100644 index 0000000..374ba15 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_lol.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_mrgreen.gif b/plugins/dokuwiki/lib/images/smileys/icon_mrgreen.gif new file mode 100644 index 0000000..b54cd0f Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_mrgreen.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_neutral.gif b/plugins/dokuwiki/lib/images/smileys/icon_neutral.gif new file mode 100644 index 0000000..4f31156 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_neutral.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_question.gif b/plugins/dokuwiki/lib/images/smileys/icon_question.gif new file mode 100644 index 0000000..9d07226 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_question.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_razz.gif b/plugins/dokuwiki/lib/images/smileys/icon_razz.gif new file mode 100644 index 0000000..29da2a2 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_razz.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_redface.gif b/plugins/dokuwiki/lib/images/smileys/icon_redface.gif new file mode 100644 index 0000000..ad76283 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_redface.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_rolleyes.gif b/plugins/dokuwiki/lib/images/smileys/icon_rolleyes.gif new file mode 100644 index 0000000..d7f5f2f Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_rolleyes.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_sad.gif b/plugins/dokuwiki/lib/images/smileys/icon_sad.gif new file mode 100644 index 0000000..d2ac78c Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_sad.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_silenced.gif b/plugins/dokuwiki/lib/images/smileys/icon_silenced.gif new file mode 100644 index 0000000..448399b Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_silenced.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_smile.gif b/plugins/dokuwiki/lib/images/smileys/icon_smile.gif new file mode 100644 index 0000000..7b1f6d3 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_smile.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_smile2.gif b/plugins/dokuwiki/lib/images/smileys/icon_smile2.gif new file mode 100644 index 0000000..769639d Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_smile2.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_surprised.gif b/plugins/dokuwiki/lib/images/smileys/icon_surprised.gif new file mode 100644 index 0000000..cb21424 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_surprised.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_twisted.gif b/plugins/dokuwiki/lib/images/smileys/icon_twisted.gif new file mode 100644 index 0000000..502fe24 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_twisted.gif differ diff --git a/plugins/dokuwiki/lib/images/smileys/icon_wink.gif b/plugins/dokuwiki/lib/images/smileys/icon_wink.gif new file mode 100644 index 0000000..d148288 Binary files /dev/null and b/plugins/dokuwiki/lib/images/smileys/icon_wink.gif differ diff --git a/plugins/dokuwiki/lib/plugins/changelinks/syntax.php b/plugins/dokuwiki/lib/plugins/changelinks/syntax.php new file mode 100644 index 0000000..263e066 --- /dev/null +++ b/plugins/dokuwiki/lib/plugins/changelinks/syntax.php @@ -0,0 +1,157 @@ + 'Florian Schmitz', + 'email' => 'floele@gmail.com', + 'date' => '2005-12-18', + 'name' => 'Change-Interwikilinks Plugin', + 'desc' => 'Changes the functionality of interwikilinks', + 'url' => 'http://flyspray.org/', + ); + } + + /** + * What kind of syntax are we? + */ + function getType(){ + return 'substition'; + } + + /** + * Where to sort in? + */ + function getSort(){ + return 299; + } + + /** + * Connect pattern to lexer + */ + + function connectTo($mode) { + // Word boundaries? + $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'plugin_changelinks'); + } + + /** + * Handle the match + */ + function handle($match, $state, $pos, &$handler){ + // Strip the opening and closing markup + $link = preg_replace(array('/^\[\[/','/\]\]$/u'),'',$match); + + // Split title from URL + $link = preg_split('/\|/u',$link,2); + if ( !isset($link[1]) ) { + $link[1] = NULL; + } else if ( preg_match('/^\{\{[^\}]+\}\}$/',$link[1]) ) { + // If the title is an image, convert it to an array containing the image details + $link[1] = Doku_Handler_Parse_Media($link[1]); + } + $link[0] = trim($link[0]); + + //decide which kind of link it is + + if ( preg_match('/^[a-zA-Z]+>{1}.*$/u',$link[0]) ) { + // Interwiki + $interwiki = preg_split('/>/u',$link[0]); + $handler->_addCall( + 'interwikilink', + array($link[0],$link[1],strtolower($interwiki[0]),$interwiki[1]), + $pos + ); + } elseif ( preg_match('/^\\\\\\\\[\w.:?\-;,]+?\\\\/u',$link[0]) ) { + // Windows Share + $handler->_addCall( + 'windowssharelink', + array($link[0],$link[1]), + $pos + ); + } elseif ( preg_match('#^([a-z0-9\-\.+]+?)://#i',$link[0]) ) { + // external link (accepts all protocols) + $handler->_addCall( + 'externallink', + array($link[0],$link[1]), + $pos + ); + } elseif ( preg_match('#([a-z0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i',$link[0]) ) { + // E-Mail + $handler->_addCall( + 'emaillink', + array($link[0],$link[1]), + $pos + ); + } elseif ( preg_match('!^#.+!',$link[0]) ){ + // local link + $handler->_addCall( + 'locallink', + array(substr($link[0],1),$link[1]), + $pos + ); + } else { + return array($link[0],$link[1]); + } + } + + /** + * Create output + */ + function render($mode, &$renderer, $data) { + if($mode == 'xhtml') { + global $conf; + $id = $data[0]; + $name = $data[1]; + + //prepare for formating + $link['target'] = $conf['target']['wiki']; + $link['style'] = ''; + $link['pre'] = ''; + $link['suf'] = ''; + $link['more'] = ''; + $link['class'] = 'internallink'; + $link['url'] = DOKU_INTERNAL_LINK . $id; + + if(is_array($name)){ + $link['name'] = (isset($name['title'])) ? hsc($name['title']) : hsc($id); + $link['title'] = $id; + } else{ + $link['name'] = ($name) ? hsc($name) : hsc($id); + $link['title'] = ($name) ? $name : $id; + } + + //add search string + if($search){ + ($conf['userewrite']) ? $link['url'].='?s=' : $link['url'].='&s='; + $link['url'] .= urlencode($search); + } + + //output formatted + $renderer->doc .= $renderer->_formatLink($link); + } + return true; + } + +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : +?> diff --git a/plugins/dokuwiki/lib/plugins/fslink/syntax.php b/plugins/dokuwiki/lib/plugins/fslink/syntax.php new file mode 100644 index 0000000..57c91c3 --- /dev/null +++ b/plugins/dokuwiki/lib/plugins/fslink/syntax.php @@ -0,0 +1,81 @@ + 'Florian Schmitz', + 'email' => 'floele@gmail.com', + 'date' => '2005-12-17', + 'name' => 'FS-link Plugin', + 'desc' => 'Enables Flyspray\'s bug links', + 'url' => 'http://flyspray.org/', + ); + } + + /** + * What kind of syntax are we? + */ + function getType(){ + return 'substition'; + } + + /** + * Where to sort in? + */ + function getSort(){ + return 301; + } + + /** + * Connect pattern to lexer + */ + + function connectTo($mode) { + // Word boundaries? + $this->Lexer->addSpecialPattern('FS#\d+',$mode,'plugin_fslink'); + $this->Lexer->addSpecialPattern('bug \d+',$mode,'plugin_fslink'); + } + + /** + * Handle the match + */ + function handle($match, $state, $pos, &$handler){ + return array($match, $state); + } + + /** + * Create output + */ + function render($mode, &$renderer, $data) { + if($mode == 'xhtml'){ + $fsid = explode('#', $data[0]); + if(count($fsid) < 2) { + $fsid = explode(' ', $data[0]); + } + $renderer->doc .= tpl_tasklink($fsid[1], $data[0]); + } + return true; + } + +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : +?> \ No newline at end of file diff --git a/plugins/dokuwiki/lib/plugins/newline/syntax.php b/plugins/dokuwiki/lib/plugins/newline/syntax.php new file mode 100644 index 0000000..6a5eed8 --- /dev/null +++ b/plugins/dokuwiki/lib/plugins/newline/syntax.php @@ -0,0 +1,77 @@ +s + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Florian Schmitz floele at gmail dot com + */ + +if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); +if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); +require_once(DOKU_PLUGIN.'syntax.php'); + +/** + * All DokuWiki plugins to extend the parser/rendering mechanism + * need to inherit from this class + */ +class syntax_plugin_newline extends DokuWiki_Syntax_Plugin { + + /** + * return some info + */ + function getInfo(){ + return array( + 'author' => 'Florian Schmitz', + 'email' => 'floele@gmail.com', + 'date' => '2005-12-17', + 'name' => '
    Plugin', + 'desc' => 'Enables simple newlines', + 'url' => 'http://flyspray.org/', + ); + } + + /** + * What kind of syntax are we? + */ + function getType(){ + return 'substition'; + } + + /** + * Where to sort in? + */ + function getSort(){ + return 201; + } + + /** + * Connect pattern to lexer + */ + + function connectTo($mode) { + // Word boundaries? + $this->Lexer->addSpecialPattern("(?doc .= '
    '; + return true; + } + return false; + } + +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : +?> \ No newline at end of file diff --git a/plugins/dokuwiki/lib/plugins/syntax.php b/plugins/dokuwiki/lib/plugins/syntax.php new file mode 100644 index 0000000..ccf6577 --- /dev/null +++ b/plugins/dokuwiki/lib/plugins/syntax.php @@ -0,0 +1,270 @@ + + */ +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); +require_once(DOKU_INC.'inc/parser/parser.php'); + +/** + * All DokuWiki plugins to extend the parser/rendering mechanism + * need to inherit from this class + */ +class DokuWiki_Syntax_Plugin extends Doku_Parser_Mode { + + var $allowedModesSetup = false; + var $localised = false; // set to true by setupLocale() after loading language dependent strings + var $lang = array(); // array to hold language dependent strings, best accessed via ->getLang() + var $configloaded = false; // set to true by loadConfig() after loading plugin configuration variables + var $conf = array(); // array to hold plugin settings, best accessed via ->getConf() + + /** + * General Info + * + * Needs to return a associative array with the following values: + * + * author - Author of the plugin + * email - Email address to contact the author + * date - Last modified date of the plugin in YYYY-MM-DD format + * name - Name of the plugin + * desc - Short description of the plugin (Text only) + * url - Website with more information on the plugin (eg. syntax description) + */ + function getInfo(){ + trigger_error('getType() not implemented in '.get_class($this), E_USER_WARNING); + } + + /** + * Syntax Type + * + * Needs to return one of the mode types defined in $PARSER_MODES in parser.php + */ + function getType(){ + trigger_error('getType() not implemented in '.get_class($this), E_USER_WARNING); + } + + /** + * Allowed Mode Types + * + * Defines the mode types for other dokuwiki markup that maybe nested within the + * plugin's own markup. Needs to return an array of one or more of the mode types + * defined in $PARSER_MODES in parser.php + */ + function getAllowedTypes() { + return array(); + } + + /** + * Paragraph Type + * + * Defines how this syntax is handled regarding paragraphs. This is important + * for correct XHTML nesting. Should return one of the following: + * + * 'normal' - The plugin can be used inside paragraphs + * 'block' - Open paragraphs need to be closed before plugin output + * 'stack' - Special case. Plugin wraps other paragraphs. + * + * @see Doku_Handler_Block + */ + function getPType(){ + return 'normal'; + } + + /** + * Handler to prepare matched data for the rendering process + * + * This function can only pass data to render() via its return value - render() + * may be not be run during the object's current life. + * + * Usually you should only need the $match param. + * + * @param $match string The text matched by the patterns + * @param $state int The lexer state for the match + * @param $pos int The character position of the matched text + * @param $handler ref Reference to the Doku_Handler object + * @return array Return an array with all data you want to use in render + */ + function handle($match, $state, $pos, &$handler){ + trigger_error('handle() not implemented in '.get_class($this), E_USER_WARNING); + } + + /** + * Handles the actual output creation. + * + * The function must not assume any other of the classes methods have been run + * during the object's current life. The only reliable data it receives are its + * parameters. + * + * The function should always check for the given output format and return false + * when a format isn't supported. + * + * $renderer contains a reference to the renderer object which is + * currently handling the rendering. You need to use it for writing + * the output. How this is done depends on the renderer used (specified + * by $format + * + * The contents of the $data array depends on what the handler() function above + * created + * + * @param $format string output format to being Rendered + * @param $renderer ref reference to the current renderer object + * @param $data array data created by handler() + * @return boolean rendered correctly? + */ + function render($format, &$renderer, $data) { + trigger_error('render() not implemented in '.get_class($this), E_USER_WARNING); + + } + + /** + * There should be no need to override these functions + */ + function accepts($mode) { + + if (!$this->allowedModesSetup) { + global $PARSER_MODES; + + $allowedModeTypes = $this->getAllowedTypes(); + foreach($allowedModeTypes as $mt) { + $this->allowedModes = array_merge($this->allowedModes, $PARSER_MODES[$mt]); + } + + $idx = array_search(substr(get_class($this), 7), $this->allowedModes); + if ($idx !== false) { + unset($this->allowedModes[$idx]); + } + $this->allowedModesSetup = true; + } + + return parent::accepts($mode); + } + + // plugin introspection methods + // extract from class name, format = _plugin_[_] + function getPluginType() { list($t) = explode('_', get_class($this), 2); return $t; } + function getPluginName() { list($t, $p, $n) = explode('_', get_class($this), 4); return $n; } + function getPluginComponent() { list($t, $p, $n, $c) = explode('_', get_class($this), 4); return (isset($c)?$c:''); } + + // localisation methods + /** + * getLang($id) + * + * use this function to access plugin language strings + * to try to minimise unnecessary loading of the strings when the plugin doesn't require them + * e.g. when info plugin is querying plugins for information about themselves. + * + * @param $id id of the string to be retrieved + * @return string string in appropriate language or english if not available + */ + function getLang($id) { + if (!$this->localised) $this->setupLocale(); + + return (isset($this->lang[$id]) ? $this->lang[$id] : ''); + } + + /** + * locale_xhtml($id) + * + * retrieve a language dependent wiki page and pass to xhtml renderer for display + * plugin equivalent of p_locale_xhtml() + * + * @param $id id of language dependent wiki page + * @return string parsed contents of the wiki page in xhtml format + */ + function locale_xhtml($id) { + return p_cached_output($this->localFN($id)); + } + + /** + * localFN($id) + * prepends appropriate path for a language dependent filename + * plugin equivalent of localFN() + */ + function localFN($id) { + global $conf; + $plugin = $this->getPluginName(); + $file = DOKU_PLUGIN.$plugin.'/lang/'.$conf['lang'].'/'.$id.'.txt'; + if(!@file_exists($file)){ + //fall back to english + $file = DOKU_PLUGIN.$plugin.'/lang/en/'.$id.'.txt'; + } + return $file; + } + + /** + * setupLocale() + * reads all the plugins language dependent strings into $this->lang + * this function is automatically called by getLang() + */ + function setupLocale() { + if ($this->localised) return; + + global $conf; // definitely don't invoke "global $lang" + $path = DOKU_PLUGIN.$this->getPluginName().'/lang/'; + + // don't include once, in case several plugin components require the same language file + @include($path.'en/lang.php'); + if ($conf['lang'] != 'en') @include($path.$conf['lang'].'/lang.php'); + + $this->lang = $lang; + $this->localised = true; + } + + // configuration methods + /** + * getConf($setting) + * + * use this function to access plugin configuration variables + */ + function getConf($setting){ + + if (!$this->configloaded){ $this->loadConfig(); } + + return $this->conf[$setting]; + } + + /** + * loadConfig() + * merges the plugin's default settings with any local settings + * this function is automatically called through getConf() + */ + function loadConfig(){ + global $conf; + + $defaults = $this->readDefaultSettings(); + $plugin = $this->getPluginName(); + + foreach ($defaults as $key => $value) { + if (isset($conf['plugin'][$plugin][$key])) continue; + $conf['plugin'][$plugin][$key] = $value; + } + + $this->configloaded = true; + $this->conf =& $conf['plugin'][$plugin]; + } + + /** + * read the plugin's default configuration settings from conf/default.php + * this function is automatically called through getConf() + * + * @return array setting => value + */ + function readDefaultSettings() { + + $path = DOKU_PLUGIN.$this->getPluginName().'/conf/'; + $conf = array(); + + if (@file_exists($path.'default.php')) { + include($path.'default.php'); + } + + return $conf; + } + +} +//Setup VIM: ex: et ts=4 enc=utf-8 : -- cgit v1.2.3-54-g00ecf