PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/MoodleWebRole/mod/wiki/ewiki/ewiki.php

#
PHP | 3600 lines | 2564 code | 527 blank | 509 comment | 523 complexity | 7e73657bc78899b591b8c21bed14a3cf MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, LGPL-2.0, GPL-2.0
  1. <?php
  2. @define("EWIKI_VERSION", "R1.01d");
  3. /*
  4. ErfurtWiki - an embedable, fast and user-friendly wiki engine
  5. ---------
  6. This is Public Domain (no license, no warranty); but feel free
  7. to redistribute it under GPL or anything else you like.
  8. http://erfurtwiki.sourceforge.net/
  9. Mario Salzer <mario*erphesfurt·de> and many others(tm)
  10. Use it from inside yoursite.php like that:
  11. <html><body>...
  12. <?php
  13. include("ewiki.php");
  14. echo ewiki_page();
  15. ?>
  16. */
  17. #-- you could also establish a mysql connection in here, of course:
  18. // mysql_connect(":/var/run/mysqld/mysqld.sock", "user", "pw")
  19. // and mysql_query("USE mydatabase");
  20. #-------------------------------------------------------- config ---
  21. #-- I'm sorry for that, but all the @ annoy me
  22. error_reporting(0x0000377 & error_reporting());
  23. # error_reporting(E_ALL^E_NOTICE);
  24. #-- the position of your ewiki-wrapper script
  25. define("EWIKI_SCRIPT", "?id="); # relative/absolute to docroot
  26. # define("EWIKI_SCRIPT_URL", "http://...?id="); # absolute URL
  27. #-- change to your needs (site lang)
  28. define("EWIKI_NAME", "ErfurtWiki");
  29. define("EWIKI_PAGE_INDEX", "ErfurtWiki");
  30. define("EWIKI_PAGE_NEWEST", "NewestPages");
  31. define("EWIKI_PAGE_SEARCH", "SearchPages");
  32. define("EWIKI_PAGE_HITS", "MostVisitedPages");
  33. define("EWIKI_PAGE_VERSIONS", "MostOftenChangedPages");
  34. define("EWIKI_PAGE_UPDATES", "UpdatedPages");
  35. #-- default settings are good settings - most often ;)
  36. #- look & feel
  37. define("EWIKI_PRINT_TITLE", 1); # <h2>WikiPageName</h2> on top
  38. define("EWIKI_SPLIT_TITLE", 0); # <h2>Wiki Page Name</h2>
  39. define("EWIKI_CONTROL_LINE", 1); # EditThisPage-link at bottom
  40. define("EWIKI_LIST_LIMIT", 20); # listing limit
  41. #- behaviour
  42. define("EWIKI_AUTO_EDIT", 1); # edit box for non-existent pages
  43. define("EWIKI_EDIT_REDIRECT", 1); # redirect after edit save
  44. define("EWIKI_DEFAULT_ACTION", "view"); # (keep!)
  45. define("EWIKI_CASE_INSENSITIVE", 1); # wikilink case sensitivity
  46. define("EWIKI_HIT_COUNTING", 1);
  47. define("UNIX_MILLENNIUM", 1000000000);
  48. #- rendering
  49. define("EWIKI_ALLOW_HTML", 0); # often a very bad idea
  50. define("EWIKI_HTML_CHARS", 1); # allows for &#200;
  51. define("EWIKI_ESCAPE_AT", 1); # "@" -> "&#x40;"
  52. #- http/urls
  53. define("EWIKI_HTTP_HEADERS", 1); # most often a good thing
  54. define("EWIKI_NO_CACHE", 1); # browser+proxy shall not cache
  55. define("EWIKI_URLENCODE", 1); # disable when _USE_PATH_INFO
  56. define("EWIKI_URLDECODE", 1);
  57. define("EWIKI_USE_PATH_INFO", 1 &&!strstr($_SERVER["SERVER_SOFTWARE"],"Apache"));
  58. define("EWIKI_USE_ACTION_PARAM", 1);
  59. define("EWIKI_ACTION_SEP_CHAR", "/");
  60. define("EWIKI_UP_PAGENUM", "n"); # _UP_ means "url parameter"
  61. define("EWIKI_UP_PAGEEND", "e");
  62. define("EWIKI_UP_BINARY", "binary");
  63. define("EWIKI_UP_UPLOAD", "upload");
  64. #- other stuff
  65. define("EWIKI_DEFAULT_LANG", "en");
  66. define("EWIKI_CHARSET", "UTF-8");
  67. #- user permissions
  68. define("EWIKI_PROTECTED_MODE", 0); # disable funcs + require auth
  69. define("EWIKI_PROTECTED_MODE_HIDING", 0); # hides disallowed actions
  70. define("EWIKI_AUTH_DEFAULT_RING", 3); # 0=root 1=priv 2=user 3=view
  71. define("EWIKI_AUTO_LOGIN", 1); # [auth_query] on startup
  72. #-- allowed WikiPageNameCharacters
  73. #### BEGIN MOODLE CHANGES - to remove auto-camelcase linking.
  74. global $moodle_disable_camel_case;
  75. if ($moodle_disable_camel_case) {
  76. define("EWIKI_CHARS_L", "");
  77. define("EWIKI_CHARS_U", "");
  78. }
  79. else {
  80. #### END MOODLE CHANGES
  81. define("EWIKI_CHARS_L", "a-z_µ¤$\337-\377");
  82. define("EWIKI_CHARS_U", "A-Z0-9\300-\336");
  83. #### BEGIN MOODLE CHANGES
  84. }
  85. #### END MOODLE CHANGES
  86. define("EWIKI_CHARS", EWIKI_CHARS_L.EWIKI_CHARS_U);
  87. #-- database
  88. define("EWIKI_DB_TABLE_NAME", "ewiki"); # MySQL / ADOdb
  89. define("EWIKI_DBFILES_DIRECTORY", "/tmp"); # see "db_flat_files.php"
  90. define("EWIKI_DBA", "/tmp/ewiki.dba"); # see "db_dba.php"
  91. define("EWIKI_DBQUERY_BUFFER", 512*1024); # 512K
  92. define("EWIKI_INIT_PAGES", "./init-pages"); # for initialization
  93. define("EWIKI_DB_F_TEXT", 1<<0);
  94. define("EWIKI_DB_F_BINARY", 1<<1);
  95. define("EWIKI_DB_F_DISABLED", 1<<2);
  96. define("EWIKI_DB_F_HTML", 1<<3);
  97. define("EWIKI_DB_F_READONLY", 1<<4);
  98. define("EWIKI_DB_F_WRITEABLE", 1<<5);
  99. define("EWIKI_DB_F_APPENDONLY", 1<<6); #nyi
  100. define("EWIKI_DB_F_SYSTEM", 1<<7);
  101. define("EWIKI_DB_F_PART", 1<<8);
  102. define("EWIKI_DB_F_TYPE", EWIKI_DB_F_TEXT | EWIKI_DB_F_BINARY | EWIKI_DB_F_DISABLED | EWIKI_DB_F_SYSTEM | EWIKI_DB_F_PART);
  103. define("EWIKI_DB_F_ACCESS", EWIKI_DB_F_READONLY | EWIKI_DB_F_WRITEABLE | EWIKI_DB_F_APPENDONLY);
  104. define("EWIKI_DB_F_COPYMASK", EWIKI_DB_F_TYPE | EWIKI_DB_F_ACCESS);
  105. define("EWIKI_DBFILES_NLR", '\\n');
  106. define("EWIKI_DBFILES_ENCODE", 0 || (DIRECTORY_SEPARATOR != "/"));
  107. define("EWIKI_DBFILES_GZLEVEL", "2");
  108. #-- internal
  109. define("EWIKI_ADDPARAMDELIM", (strstr(EWIKI_SCRIPT,"?") ? "&" : "?"));
  110. #-- binary content (images)
  111. define("EWIKI_SCRIPT_BINARY", /*"/binary.php?binary="*/ ltrim(strtok(" ".EWIKI_SCRIPT,"?"))."?".EWIKI_UP_BINARY."=" );
  112. define("EWIKI_CACHE_IMAGES", 1 &&!headers_sent());
  113. define("EWIKI_IMAGE_MAXSIZE", 64 *1024);
  114. define("EWIKI_IMAGE_MAXWIDTH", 3072);
  115. define("EWIKI_IMAGE_MAXHEIGHT", 2048);
  116. define("EWIKI_IMAGE_MAXALLOC", 1<<19);
  117. define("EWIKI_IMAGE_RESIZE", 1);
  118. define("EWIKI_IMAGE_ACCEPT", "image/jpeg,image/png,image/gif,application/x-shockwave-flash");
  119. define("EWIKI_IDF_INTERNAL", "internal://");
  120. define("EWIKI_ACCEPT_BINARY", 0); # for arbitrary binary data files
  121. #-- misc
  122. define("EWIKI_TMP", $_SERVER["TEMP"] ? $_SERVER["TEMP"] : "/tmp");
  123. define("EWIKI_LOGLEVEL", -1); # 0=error 1=warn 2=info 3=debug
  124. define("EWIKI_LOGFILE", "/tmp/ewiki.log");
  125. #-- plugins (tasks mapped to function names)
  126. $ewiki_plugins["database"][] = "ewiki_database_mysql";
  127. $ewiki_plugins["edit_preview"][] = "ewiki_page_edit_preview";
  128. $ewiki_plugins["render"][] = "ewiki_format";
  129. $ewiki_plugins["init"][-5] = "ewiki_localization";
  130. $ewiki_plugins["init"][-1] = "ewiki_binary";
  131. $ewiki_plugins["handler"][-105] = "ewiki_eventually_initialize";
  132. $ewiki_plugins["handler"][] = "ewiki_intermap_walking";
  133. $ewiki_plugins["view_append"][-1] = "ewiki_control_links";
  134. $ewiki_plugins["view_final"][-1] = "ewiki_add_title";
  135. $ewiki_plugins["page_final"][] = "ewiki_http_headers";
  136. $ewiki_plugins["page_final"][99115115] = "ewiki_page_css_container";
  137. $ewiki_plugins["edit_form_final"][] = "ewiki_page_edit_form_final_imgupload";
  138. $ewiki_plugins["format_block"]["pre"][] = "ewiki_format_pre";
  139. $ewiki_plugins["format_block"]["code"][] = "ewiki_format_pre";
  140. $ewiki_plugins["format_block"]["htm"][] = "ewiki_format_html";
  141. $ewiki_plugins["format_block"]["html"][] = "ewiki_format_html";
  142. $ewiki_plugins["format_block"]["comment"][] = "ewiki_format_comment";
  143. #-- internal pages
  144. $ewiki_plugins["page"][EWIKI_PAGE_NEWEST] = "ewiki_page_newest";
  145. $ewiki_plugins["page"][EWIKI_PAGE_SEARCH] = "ewiki_page_search";
  146. if (EWIKI_HIT_COUNTING) $ewiki_plugins["page"][EWIKI_PAGE_HITS] = "ewiki_page_hits";
  147. $ewiki_plugins["page"][EWIKI_PAGE_VERSIONS] = "ewiki_page_versions";
  148. $ewiki_plugins["page"][EWIKI_PAGE_UPDATES] = "ewiki_page_updates";
  149. #-- page actions
  150. $ewiki_plugins["action"]["edit"] = "ewiki_page_edit";
  151. $ewiki_plugins["action_always"]["links"] = "ewiki_page_links";
  152. $ewiki_plugins["action"]["info"] = "ewiki_page_info";
  153. $ewiki_plugins["action"]["view"] = "ewiki_page_view";
  154. #-- helper vars ---------------------------------------------------
  155. $ewiki_config["idf"]["url"] = array("http://", "mailto:", "internal://", "ftp://", "https://", "irc://", "telnet://", "news://", "chrome://", "file://", "gopher://", "httpz://");
  156. $ewiki_config["idf"]["img"] = array(".jpeg", ".png", ".jpg", ".gif", ".j2k");
  157. $ewiki_config["idf"]["obj"] = array(".swf", ".svg");
  158. #-- entitle actions
  159. $ewiki_config["action_links"]["view"] = @array_merge(array(
  160. "edit" => "EDITTHISPAGE", # ewiki_t() is called on these
  161. "links" => "BACKLINKS",
  162. "info" => "PAGEHISTORY",
  163. "like" => "LIKEPAGES",
  164. ), @$ewiki_config["action_links"]["view"]
  165. );
  166. $ewiki_config["action_links"]["info"] = @array_merge(array(
  167. "view" => "browse",
  168. "edit" => "fetchback",
  169. ), @$ewiki_config["action_links"]["info"]
  170. );
  171. #-- variable configuration settings (go into '$ewiki_config')
  172. $ewiki_config_DEFAULTSTMP = array(
  173. "edit_thank_you" => 1,
  174. "edit_box_size" => "70x15",
  175. "print_title" => EWIKI_PRINT_TITLE,
  176. "split_title" => EWIKI_SPLIT_TITLE,
  177. "control_line" => EWIKI_CONTROL_LINE,
  178. "list_limit" => EWIKI_LIST_LIMIT,
  179. "script" => EWIKI_SCRIPT,
  180. "script_url" => (defined("EWIKI_SCRIPT_URL")?EWIKI_SCRIPT_URL:NULL),
  181. "script_binary" => EWIKI_SCRIPT_BINARY,
  182. #-- heart of the wiki -- don't try to read this! ;)
  183. "wiki_pre_scan_regex" => '/
  184. (?<![~!])
  185. ((?:(?:\w+:)*['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2,}[\w\d]*)
  186. |\^([-'.EWIKI_CHARS_L.EWIKI_CHARS_U.']{3,})
  187. |\[ (?:"[^\]\"]+" | \s+ | [^:\]#]+\|)* ([^\|\"\[\]\#]+) (?:\s+ | "[^\]\"]+")* [\]\#]
  188. |(\w{3,9}:\/\/[^?#\s\[\]\'\"\)\,<]+) /x',
  189. "wiki_link_regex" => "\007 [!~]?(
  190. \#?\[[^<>\[\]\n]+\] |
  191. \^[-".EWIKI_CHARS_U.EWIKI_CHARS_L."]{3,} |
  192. \b([\w]{3,}:)*([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}\#?[\w\d]* |
  193. ([a-z]{2,9}://|mailto:)[^\s\[\]\'\"\)\,<]+ |
  194. \w[-_.+\w]+@(\w[-_\w]+[.])+\w{2,} ) \007x",
  195. #-- rendering ruleset
  196. "wm_indent" => '',
  197. "wm_table_defaults" => 'cellpadding="2" border="1" cellspacing="0"',
  198. "wm_whole_line" => array(),
  199. "htmlentities" => array(
  200. "&" => "&amp;",
  201. ">" => "&gt;",
  202. "<" => "&lt;",
  203. ),
  204. "wm_source" => array(
  205. "%%%" => "<br />",
  206. "\t" => " ",
  207. "\n;:" => "\n ", # workaround, replaces the old ;:
  208. ),
  209. "wm_list" => array(
  210. "-" => array('ul type="square"', "", "li"),
  211. "*" => array('ul type="circle"', "", "li"),
  212. "#" => array("ol", "", "li"),
  213. ":" => array("dl", "dt", "dd"),
  214. #<out># ";" => array("dl", "dt", "dd"),
  215. ),
  216. "wm_style" => array(
  217. "'''''" => array("<b><i>", "</i></b>"),
  218. "'''" => array("<b>", "</b>"),
  219. "___" => array("<i><b>", "</b></i>"),
  220. "''" => array("<em>", "</em>"),
  221. "__" => array("<strong>", "</strong>"),
  222. "^^" => array("<sup>", "</sup>"),
  223. "==" => array("<tt>", "</tt>"),
  224. #<off># "***" => array("<b><i>", "</i></b>"),
  225. #<off># "###" => array("<big><b>", "</b></big>"),
  226. "**" => array("<b>", "</b>"),
  227. "##" => array("<big>", "</big>"),
  228. "µµ" => array("<small>", "</small>"),
  229. ),
  230. "wm_start_end" => array(
  231. ),
  232. #-- rendering plugins
  233. "format_block" => array(
  234. "html" => array("&lt;html&gt;", "&lt;/html&gt;", "html", 0x0000),
  235. "htm" => array("&lt;htm&gt;", "&lt;/htm&gt;", "html", 0x0003),
  236. "code" => array("&lt;code&gt;", "&lt;/code&gt;", false, 0x0000),
  237. "pre" => array("&lt;pre&gt;", "&lt;/pre&gt;", false, 0x003F),
  238. "comment" => array("\n&lt;!--", "--&gt;", false, 0x0030),
  239. # "verbatim" => array("&lt;verbatim&gt;", "&lt;/verbatim&gt;", false, 0x0000),
  240. ),
  241. "format_params" => array(
  242. "scan_links" => 1,
  243. "html" => EWIKI_ALLOW_HTML,
  244. "mpi" => 1,
  245. ),
  246. );
  247. foreach ($ewiki_config_DEFAULTSTMP as $set => $val) {
  248. if (!isset($ewiki_config[$set])) {
  249. $ewiki_config[$set] = $val;
  250. }
  251. elseif (is_array($val)) foreach ($val as $vali=>$valv) {
  252. if (is_int($vali)) {
  253. $ewiki_config[$set][] = $valv;
  254. }
  255. elseif (!isset($ewiki_config[$set][$vali])) {
  256. $ewiki_config[$set][$vali] = $valv;
  257. }
  258. }
  259. }
  260. $ewiki_config_DEFAULTSTMP = $valv = $vali = $val = NULL;
  261. #-- init stuff, autostarted parts
  262. ksort($ewiki_plugins["init"]);
  263. if ($pf_a = $ewiki_plugins["init"]) foreach ($pf_a as $pf) {
  264. // Binary Handling starts here
  265. #### MOODLE CHANGE TO BE COMPATIBLE WITH PHP 4.1
  266. #if(headers_sent($file,$line)) {
  267. # error("Headers already sent: $file:$line");
  268. if(headers_sent()) {
  269. error("Headers already sent.");
  270. }
  271. $pf($GLOBALS);
  272. }
  273. unset($ewiki_plugins["init"]);
  274. #-- text (never remove the "C" or "en" sections!)
  275. #
  276. $ewiki_t["C"] = @array_merge(@$ewiki_t["C"], array(
  277. "DATE" => "%a, %d %b %G %T %Z",
  278. "EDIT_TEXTAREA_RESIZE_JS" => '<a href="javascript:ewiki_enlarge()" style="text-decoration:none">+</a><script type="text/javascript"><!--'."\n".'function ewiki_enlarge() {var ta=document.getElementById("ewiki_content");ta.style.width=((ta.cols*=1.1)*10).toString()+"px";ta.style.height=((ta.rows*=1.1)*30).toString()+"px";}'."\n".'//--></script>',
  279. ));
  280. #
  281. $ewiki_t["en"] = @array_merge(@$ewiki_t["en"], array(
  282. "EDITTHISPAGE" => "EditThisPage",
  283. "APPENDTOPAGE" => "Add to",
  284. "BACKLINKS" => "BackLinks",
  285. "PAGESLINKINGTO" => "Pages linking to \$title",
  286. "PAGEHISTORY" => "PageInfo",
  287. "INFOABOUTPAGE" => "Information about page",
  288. "LIKEPAGES" => "Pages like this",
  289. "NEWESTPAGES" => "Newest Pages",
  290. "LASTCHANGED" => "last changed on %c",
  291. "DOESNOTEXIST" => "This page does not yet exist, please click on EditThisPage if you'd like to create it.",
  292. "DISABLEDPAGE" => "This page is currently not available.",
  293. "ERRVERSIONSAVE" => "Sorry, while you edited this page someone else
  294. did already save a changed version. Please go back to the
  295. previous screen and copy your changes to your computers
  296. clipboard to insert it again after you reload the edit
  297. screen.",
  298. "ERRORSAVING" => "An error occoured while saving your changes. Please try again.",
  299. "THANKSFORCONTRIBUTION" => "Thank you for your contribution!",
  300. "CANNOTCHANGEPAGE" => "This page cannot be changed.",
  301. "OLDVERCOMEBACK" => "Make this old version come back to replace the current one",
  302. "PREVIEW" => "Preview",
  303. "SAVE" => "Save",
  304. "CANCEL_EDIT" => "CancelEditing",
  305. "UPLOAD_PICTURE_BUTTON" => "upload picture &gt;&gt;&gt;",
  306. "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GoodStyle\">GoodStyle</a> is to
  307. write what comes to your mind. Don't care about how it
  308. looks too much now. You can add <a href=\"".EWIKI_SCRIPT."WikiMarkup\">WikiMarkup</a>
  309. also later if you think it is necessary.<br />",
  310. "EDIT_FORM_2" => "<br />Please do not write things, which may make other
  311. people angry. And please keep in mind that you are not all that
  312. anonymous in the internet (find out more about your computers
  313. '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' at Google).",
  314. "BIN_IMGTOOLARGE" => "Image file is too large!",
  315. "BIN_NOIMG" => "This is no image file (inacceptable file format)!",
  316. "FORBIDDEN" => "You are not authorized to access this page.",
  317. ));
  318. #
  319. $ewiki_t["es"] = @array_merge(@$ewiki_t["es"], array(
  320. "EDITTHISPAGE" => "EditarEstaPágina",
  321. "BACKLINKS" => "EnlacesInversos",
  322. "PAGESLINKINGTO" => "Páginas enlazando \$title",
  323. "PAGEHISTORY" => "InfoPágina",
  324. "INFOABOUTPAGE" => "Información sobre la página",
  325. "LIKEPAGES" => "Páginas como esta",
  326. "NEWESTPAGES" => "Páginas más nuevas",
  327. "LASTCHANGED" => "última modificación %d/%m/%Y a las %H:%M",
  328. "DOESNOTEXIST" => "Esta página aún no existe, por favor eliga EditarEstaPágina si desea crearla.",
  329. "DISABLEDPAGE" => "Esta página no está disponible en este momento.",
  330. "ERRVERSIONSAVE" => "Disculpe, mientras editaba esta página alguién más
  331. salvó una versión modificada. Por favor regrese a
  332. a la pantalla anterior y copie sus cambios a su computador
  333. para insertalos nuevamente después de que cargue
  334. la pantalla de edición.",
  335. "ERRORSAVING" => "Ocurrió un error mientras se salvavan sus cambios. Por favor intente de nuevo.",
  336. "THANKSFORCONTRIBUTION" => "Gracias por su contribución!",
  337. "CANNOTCHANGEPAGE" => "Esta página no puede ser modificada.",
  338. "OLDVERCOMEBACK" => "Hacer que esta versión antigua regrese a remplazar la actual",
  339. "PREVIEW" => "Previsualizar",
  340. "SAVE" => "Salvar",
  341. "CANCEL_EDIT" => "CancelarEdición",
  342. "UPLOAD_PICTURE_BUTTON" => "subir gráfica &gt;&gt;&gt;",
  343. "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."BuenEstilo\">BuenEstilo</a> es
  344. escribir lo que viene a su mente. No se preocupe mucho
  345. por la apariencia. También puede agregar <a href=\"".EWIKI_SCRIPT."ReglasDeMarcadoWiki\">ReglasDeMarcadoWiki</a>
  346. más adelante si piensa que es necesario.<br />",
  347. "EDIT_FORM_2" => "<br />Por favor no escriba cosas, que puedan
  348. enfadar a otras personas. Y por favor tenga en mente que
  349. usted no es del todo anónimo en Internet
  350. (encuentre más sobre
  351. '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' de su computador con Google).",
  352. "BIN_IMGTOOLARGE" => "¡La gráfica es demasiado grande!",
  353. "BIN_NOIMG" => "¡No es un archivo con una gráfica (formato de archivo inaceptable)!",
  354. "FORBIDDEN" => "No está autorizado para acceder a esta página.",
  355. ));
  356. #
  357. $ewiki_t["de"] = @array_merge(@$ewiki_t["de"], array(
  358. "EDITTHISPAGE" => "DieseSeiteÄndern",
  359. "APPENDTOPAGE" => "Ergänze",
  360. "BACKLINKS" => "ZurückLinks",
  361. "PAGESLINKINGTO" => "Verweise zur Seite \$title",
  362. "PAGEHISTORY" => "SeitenInfo",
  363. "INFOABOUTPAGE" => "Informationen über Seite",
  364. "LIKEPAGES" => "Ähnliche Seiten",
  365. "NEWESTPAGES" => "Neueste Seiten",
  366. "LASTCHANGED" => "zuletzt geändert am %d.%m.%Y um %H:%M",
  367. "DISABLEDPAGE" => "Diese Seite kann momentan nicht angezeigt werden.",
  368. "ERRVERSIONSAVE" => "Entschuldige, aber während Du an der Seite
  369. gearbeitet hast, hat bereits jemand anders eine geänderte
  370. Fassung gespeichert. Damit nichts verloren geht, browse bitte
  371. zurück und speichere Deine Änderungen in der Zwischenablage
  372. (Bearbeiten->Kopieren) um sie dann wieder an der richtigen
  373. Stelle einzufügen, nachdem du die EditBoxSeite nocheinmal
  374. geladen hast.<br />
  375. Vielen Dank für Deine Mühe.",
  376. "ERRORSAVING" => "Beim Abspeichern ist ein Fehler aufgetreten. Bitte versuche es erneut.",
  377. "THANKSFORCONTRIBUTION" => "Vielen Dank für Deinen Beitrag!",
  378. "CANNOTCHANGEPAGE" => "Diese Seite kann nicht geändert werden.",
  379. "OLDVERCOMEBACK" => "Diese alte Version der Seite wieder zur Aktuellen machen",
  380. "PREVIEW" => "Vorschau",
  381. "SAVE" => "Speichern",
  382. "CANCEL_EDIT" => "ÄnderungenVerwerfen",
  383. "UPLOAD_PICTURE_BUTTON" => "Bild hochladen &gt;&gt;&gt;",
  384. "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GuterStil\">GuterStil</a> ist es,
  385. ganz einfach das zu schreiben, was einem gerade in den
  386. Sinn kommt. Du solltest dich jetzt noch nicht so sehr
  387. darum kümmern, wie die Seite aussieht. Du kannst später
  388. immernoch zurückkommen und den Text mit <a href=\"".EWIKI_SCRIPT."FormatierungsRegeln\">WikiTextFormatierungsRegeln</a>
  389. aufputschen.<br />",
  390. "EDIT_FORM_2" => "<br />Bitte schreib keine Dinge, die andere Leute
  391. verärgern könnten. Und bedenke auch, daß es schnell auf
  392. dich zurückfallen kann wenn du verschiedene andere Dinge sagst (mehr Informationen zur
  393. '<a href=\"http://google.de/search?q=computer+IP+adresse\">IP Adresse</a>'
  394. deines Computers findest du bei Google).",
  395. ));
  396. #-- InterWiki:Links
  397. $ewiki_config["interwiki"] = @array_merge(
  398. @$ewiki_config["interwiki"],
  399. array(
  400. "javascript" => "", # this actually protects from javascript: links
  401. "url" => "",
  402. # "self" => "this",
  403. "this" => EWIKI_SCRIPT, # better was absolute _URL to ewiki wrapper
  404. "jump" => ""
  405. ));
  406. // BEGIN MOODLE CHANGES - disable interwiki liks by default
  407. // can be enabled with $CFG->wiki_allow_interwiki = true . MDL-19460
  408. global $CFG;
  409. if (!empty($CFG->wiki_allow_interwiki)) {
  410. $ewiki_config["interwiki"] = @array_merge(
  411. $ewiki_config["interwiki"],
  412. array (
  413. "ErfurtWiki" => "http://erfurtwiki.sourceforge.net/?id=",
  414. "InterWiki" => "InterWikiSearch",
  415. "InterWikiSearch" => "http://sunir.org/apps/meta.pl?",
  416. "Wiki" => "WardsWiki",
  417. "WardsWiki" => "http://www.c2.com/cgi/wiki?",
  418. "WikiFind" => "http://c2.com/cgi/wiki?FindPage&amp;value=",
  419. "WikiPedia" => "http://www.wikipedia.com/wiki.cgi?",
  420. "MeatBall" => "MeatballWiki",
  421. "MeatballWiki" => "http://www.usemod.com/cgi-bin/mb.pl?",
  422. "UseMod" => "http://www.usemod.com/cgi-bin/wiki.pl?",
  423. "PhpWiki" => "http://phpwiki.sourceforge.net/phpwiki/index.php3?",
  424. "LinuxWiki" => "http://linuxwiki.de/",
  425. "OpenWiki" => "http://openwiki.com/?",
  426. "Tavi" => "http://andstuff.org/tavi/",
  427. "TWiki" => "http://twiki.sourceforge.net/cgi-bin/view/",
  428. "MoinMoin" => "http://www.purl.net/wiki/moin/",
  429. "Google" => "http://google.com/search?q=",
  430. "ISBN" => "http://www.amazon.com/exec/obidos/ISBN=",
  431. "icq" => "http://www.icq.com/"
  432. ));
  433. }
  434. // END MOODLE CHANGES
  435. #-------------------------------------------------------------------- main ---
  436. /* this is the main function, which you should preferrably call to
  437. integrate the ewiki into your web site; it chains to most other
  438. parts and plugins (including the edit box);
  439. if you do not supply the requested pages "$id" we will fetch it
  440. from the pre-defined possible URL parameters.
  441. */
  442. function ewiki_page($id=false) {
  443. global $ewiki_links, $ewiki_plugins, $ewiki_ring, $ewiki_t, $ewiki_errmsg;
  444. #-- output var
  445. $o = "";
  446. #-- selected page
  447. if (!isset($_REQUEST)) {
  448. $_REQUEST = @array_merge($_GET, $_POST);
  449. }
  450. if (!strlen($id)) {
  451. $id = ewiki_id();
  452. }
  453. $id = format_string($id,true);
  454. #-- page action
  455. $action = EWIKI_DEFAULT_ACTION;
  456. if ($delim = strpos($id, EWIKI_ACTION_SEP_CHAR)) {
  457. $action = substr($id, 0, $delim);
  458. $id = substr($id, $delim + 1);
  459. }
  460. elseif (EWIKI_USE_ACTION_PARAM && isset($_REQUEST["action"])) {
  461. $action = $_REQUEST["action"];
  462. }
  463. $GLOBALS["ewiki_id"] = $id;
  464. $GLOBALS["ewiki_title"] = ewiki_split_title($id);
  465. $GLOBALS["ewiki_action"] = $action;
  466. #-- fetch from db
  467. $dquery = array(
  468. "id" => $id
  469. );
  470. if (!isset($_REQUEST["content"]) && ($dquery["version"] = @$_REQUEST["version"])) {
  471. $dquery["forced_version"] = $dquery["version"];
  472. }
  473. $data = @array_merge($dquery, ewiki_database("GET", $dquery));
  474. #-- stop here if page is not marked as _TEXT,
  475. # perform authentication then, and let only administrators proceed
  476. if (!empty($data["flags"]) && (($data["flags"] & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT)) {
  477. if (($data["flags"] & EWIKI_DB_F_BINARY) && ($pf = $ewiki_plugins["handler_binary"][0])) {
  478. return($pf($id, $data, $action)); //_BINARY entries handled separately
  479. }
  480. elseif (!EWIKI_PROTECTED_MODE || !ewiki_auth($id, $data, $action, 0, 1) && ($ewiki_ring!=0)) {
  481. return(ewiki_t("DISABLEDPAGE"));
  482. }
  483. }
  484. #-- pre-check if actions exist
  485. $pf_page = ewiki_array($ewiki_plugins["page"], $id);
  486. #-- edit <form> for non-existent pages
  487. if (($action==EWIKI_DEFAULT_ACTION) && empty($data["content"]) && empty($pf_page)) {
  488. if (EWIKI_AUTO_EDIT) {
  489. $action = "edit";
  490. }
  491. else {
  492. $data["content"] = ewiki_t("DOESNOTEXIST");
  493. }
  494. }
  495. #-- more initialization
  496. if ($pf_a = @$ewiki_plugins["page_init"]) {
  497. ksort($pf_a);
  498. foreach ($pf_a as $pf) {
  499. $o .= $pf($id, $data, $action);
  500. }
  501. unset($ewiki_plugins["page_init"]);
  502. }
  503. $pf_page = ewiki_array($ewiki_plugins["page"], $id);
  504. #-- require auth
  505. if (EWIKI_PROTECTED_MODE) {
  506. if (!ewiki_auth($id, $data, $action, $ring=false, $force=EWIKI_AUTO_LOGIN)) {
  507. return($o.=$ewiki_errmsg);
  508. }
  509. }
  510. #-- handlers
  511. $handler_o = "";
  512. if ($pf_a = @$ewiki_plugins["handler"]) {
  513. ksort($pf_a);
  514. foreach ($pf_a as $pf) {
  515. if ($handler_o = $pf($id, $data, $action)) { break; }
  516. } }
  517. #-- finished by handler
  518. if ($handler_o) {
  519. $o .= $handler_o;
  520. }
  521. #-- actions that also work for static and internal pages
  522. elseif (($pf = @$ewiki_plugins["action_always"][$action]) && function_exists($pf)) {
  523. $o .= $pf($id, $data, $action);
  524. }
  525. #-- internal pages
  526. elseif ($pf_page && function_exists($pf_page)) {
  527. $o .= $pf_page($id, $data, $action);
  528. }
  529. #-- page actions
  530. else {
  531. $pf = @$ewiki_plugins["action"][$action];
  532. #-- fallback to "view" action
  533. if (empty($pf) || !function_exists($pf)) {
  534. $pf = "ewiki_page_view";
  535. $action = "view"; // we could also allow different (this is a
  536. // catch-all) view variants, but this would lead to some problems
  537. }
  538. $o .= $pf($id, $data, $action);
  539. }
  540. #-- error instead of page?
  541. if (empty($o) && $ewiki_errmsg) {
  542. $o = $ewiki_errmsg;
  543. }
  544. #-- html post processing
  545. if ($pf_a = $ewiki_plugins["page_final"]) {
  546. ksort($pf_a);
  547. foreach ($pf_a as $pf) {
  548. if ($action == 'edit' and $pf == 'ewiki_html_tag_balancer') {
  549. continue; // balancer breaks htmlarea buttons
  550. }
  551. $pf($o, $id, $data, $action);
  552. }
  553. }
  554. (EWIKI_ESCAPE_AT) && ($o = str_replace("@", "&#x40;", $o));
  555. return($o);
  556. }
  557. #-- HTTP meta headers
  558. function ewiki_http_headers(&$o, $id, &$data, $action) {
  559. global $ewiki_t;
  560. if (EWIKI_HTTP_HEADERS && !headers_sent()) {
  561. if (!empty($data)) {
  562. if ($uu = @$data["id"]) @header('Content-Disposition: inline; filename="' . urlencode($uu) . '.html"');
  563. if ($uu = @$data["version"]) @header('Content-Version: ' . $uu);
  564. if ($uu = @$data["lastmodified"]) @header('Last-Modified: ' . gmstrftime($ewiki_t["C"]["DATE"], $uu));
  565. }
  566. if (EWIKI_NO_CACHE) {
  567. header('Expires: ' . gmstrftime($ewiki_t["C"]["DATE"], UNIX_MILLENNIUM));
  568. header('Pragma: no-cache');
  569. header('Cache-Control: no-cache, private, must-revalidate');
  570. # change to "C-C: cache, must-revalidate" ??
  571. # private only for authenticated users / _PROT_MODE
  572. }
  573. #-- ETag
  574. if ($data["version"] && ($etag=ewiki_etag($data)) || ($etag=md5($o))) {
  575. $weak = "W/" . urlencode($id) . "." . $data["version"];
  576. header("ETag: \"$etag\""); ###, \"$weak\"");
  577. }
  578. }
  579. }
  580. function ewiki_etag(&$data) {
  581. return( urlencode($data["id"]) . ":" . dechex($data["version"]) . ":ewiki:" .
  582. dechex(crc32($data["content"]) & 0x7FFFBFFF) );
  583. }
  584. #-- encloses whole page output with a descriptive <div>
  585. function ewiki_page_css_container(&$o, &$id, &$data, &$action) {
  586. $o = "<div class=\"wiki $action "
  587. . strtr($id, ' ./ --_!"§$%&()=?²³{[]}`+#*;:,<>| @µöäüÖÄÜߤ^°«»\'\\',
  588. '- -----------------------------------------------')
  589. . "\">\n"
  590. . $o . "\n</div>\n";
  591. }
  592. function ewiki_split_title ($id='', $split=EWIKI_SPLIT_TITLE, $entities=1) {
  593. strlen($id) or ($id = $GLOBALS["ewiki_id"]);
  594. if ($split) {
  595. $id = preg_replace("/([".EWIKI_CHARS_L."])([".EWIKI_CHARS_U."]+)/", "$1 $2", $id);
  596. }
  597. return($entities ? s($id) : $id);
  598. }
  599. function ewiki_add_title(&$html, $id, &$data, $action, $go_action="links") {
  600. $html = ewiki_make_title($id, '', 1, $action, $go_action) . $html;
  601. }
  602. function ewiki_make_title($id='', $title='', $class=3, $action="view", $go_action="links", $may_split=1) {
  603. global $ewiki_config, $ewiki_plugins, $ewiki_title, $ewiki_id;
  604. #-- advanced handler
  605. if ($pf = @$ewiki_plugins["make_title"][0]) {
  606. return($pf($title, $class, $action, $go_action, $may_split));
  607. }
  608. #-- disabled
  609. elseif (!$ewiki_config["print_title"]) {
  610. return("");
  611. }
  612. #-- get id
  613. if (empty($id)) {
  614. $id = $ewiki_id;
  615. }
  616. #-- get title
  617. if (!strlen($title)) {
  618. $title = $ewiki_title; // already in &html; format
  619. }
  620. elseif ($ewiki_config["split_title"] && $may_split) {
  621. $title = ewiki_split_title($title, $ewiki_config["split_title"], 0&($title!=$ewiki_title));
  622. }
  623. else {
  624. $title = s($title);
  625. }
  626. #-- title mangling
  627. if ($pf_a = @$ewiki_plugins["title_transform"]) {
  628. foreach ($pf_a as $pf) { $pf($id, $title, $go_action); }
  629. }
  630. #-- clickable link or simple headline
  631. if ($class <= $ewiki_config["print_title"]) {
  632. if ($uu = @$ewiki_config["link_title_action"][$action]) {
  633. $go_action = $uu;
  634. }
  635. if ($uu = @$ewiki_config["link_title_url"]) {
  636. $href = $uu;
  637. unset($ewiki_config["link_title_url"]);
  638. }
  639. else {
  640. $href = ewiki_script($go_action, $id);
  641. }
  642. $o = '<a href="' . $href . '">' . ($title) . '</a>';
  643. }
  644. else {
  645. $o = $title;
  646. }
  647. return('<h2 class="page title">' . $o . '</h2>'."\n");
  648. }
  649. function ewiki_page_view($id, &$data, $action, $all=1) {
  650. global $ewiki_plugins, $ewiki_config;
  651. $o = "";
  652. #-- render requested wiki page <-- goal !!!
  653. $render_args = array(
  654. "scan_links" => 1,
  655. "html" => (EWIKI_ALLOW_HTML||(@$data["flags"]&EWIKI_DB_F_HTML)),
  656. );
  657. $o .= $ewiki_plugins["render"][0] ($data["content"], $render_args);
  658. if (!$all) {
  659. return($o);
  660. }
  661. #### MOODLE CHANGE
  662. /// Add Moodle filters to text porion of wiki.
  663. global $moodle_format; // from wiki/view.php
  664. $o = format_text($o, $moodle_format);
  665. $o.= "<br /><br />";
  666. #-- control line + other per-page info stuff
  667. if ($pf_a = $ewiki_plugins["view_append"]) {
  668. ksort($pf_a);
  669. foreach ($pf_a as $n => $pf) { $o .= $pf($id, $data, $action); }
  670. }
  671. if ($pf_a = $ewiki_plugins["view_final"]) {
  672. ksort($pf_a);
  673. foreach ($pf_a as $n => $pf) { $pf($o, $id, $data, $action); }
  674. }
  675. if (!empty($_REQUEST["thankyou"]) && $ewiki_config["edit_thank_you"]) {
  676. $o = ewiki_t("THANKSFORCONTRIBUTION") . $o;
  677. }
  678. if (EWIKI_HIT_COUNTING) {
  679. ewiki_database("HIT", $data);
  680. }
  681. return($o);
  682. }
  683. #-------------------------------------------------------------------- util ---
  684. /* retrieves "$id/$action" string from URL / QueryString / PathInfo,
  685. change this in conjunction with ewiki_script() to customize your URLs
  686. further whenever desired
  687. */
  688. function ewiki_id() {
  689. ($id = @$_REQUEST["id"]) or
  690. ($id = @$_REQUEST["name"]) or
  691. ($id = @$_REQUEST["page"]) or
  692. ($id = @$_REQUEST["file"]) or
  693. (EWIKI_USE_PATH_INFO) and ($id = ltrim(@$_SERVER["PATH_INFO"], "/")) or
  694. (!isset($_REQUEST["id"])) and ($id = trim(strtok($_SERVER["QUERY_STRING"], "&")));
  695. if (!strlen($id) || ($id=="id=")) {
  696. $id = EWIKI_PAGE_INDEX;
  697. }
  698. (EWIKI_URLDECODE) && ($id = urldecode($id));
  699. return($id);
  700. }
  701. /* replaces EWIKI_SCRIPT, works more sophisticated, and
  702. bypasses various design flaws
  703. - if only the first parameter is used (old style), it can contain
  704. a complete "action/WikiPage" - but this is ambigutious
  705. - else $asid is the action, and $id contains the WikiPageName
  706. - $ewiki_config["script"] will now be used in favour of the constant
  707. - needs more work on _BINARY, should be a separate function
  708. */
  709. ## MOODLE-CHANGE: $asid="", Knows the devil why....
  710. function ewiki_script($asid="", $id=false, $params="", $bin=0, $html=1, $script=NULL) {
  711. global $ewiki_config, $ewiki_plugins;
  712. #-- get base script url from config vars
  713. if (empty($script)) {
  714. $script = &$ewiki_config[!$bin?"script":"script_binary"];
  715. }
  716. #-- separate $action and $id for old style requests
  717. if ($id === false) {
  718. if (strpos($asid, EWIKI_ACTION_SEP_CHAR) !== false) {
  719. $asid = strtok($asid, EWIKI_ACTION_SEP_CHAR);
  720. $id = strtok("\000");
  721. }
  722. else {
  723. $id = $asid;
  724. $asid = "";
  725. }
  726. }
  727. #-- prepare params
  728. if (is_array($params)) {
  729. $uu = $params;
  730. $params = "";
  731. if ($uu) foreach ($uu as $k=>$v) {
  732. $params .= (strlen($params)?"&":"") . rawurlencode($k) . "=" . rawurlencode($v);
  733. }
  734. }
  735. #-- action= parameter
  736. if (EWIKI_USE_ACTION_PARAM >= 2) {
  737. $params = "action=$asid" . (strlen($params)?"&":"") . $params;
  738. $asid = "";
  739. }
  740. #-- workaround slashes in $id
  741. if (empty($asid) && (strpos($id, EWIKI_ACTION_SEP_CHAR) !== false) && !$bin) {
  742. $asid = "view";
  743. }
  744. /*paranoia*/ $asid = trim($asid, EWIKI_ACTION_SEP_CHAR);
  745. #-- make url
  746. if (EWIKI_URLENCODE) {
  747. $id = urlencode($id);
  748. $asid = urlencode($asid);
  749. }
  750. else {
  751. # only urlencode &, %, ? for example
  752. }
  753. $url = $script;
  754. if ($asid) {
  755. $id = $asid . EWIKI_ACTION_SEP_CHAR . $id; #= "action/PageName"
  756. }
  757. if (strpos($url, "%s") !== false) {
  758. $url = str_replace("%s", $id, $url);
  759. }
  760. else {
  761. $url .= $id;
  762. }
  763. #-- add url params
  764. if (strlen($params)) {
  765. $url .= (strpos($url,"?")!==false ? "&":"?") . $params;
  766. }
  767. #-- fin
  768. if ($html) {
  769. //Don't replace & if it's part of encoded character (bug 2209)
  770. $url = preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/","&amp;", $url);
  771. } else {
  772. //This is going to be used in some header or meta redirect, so It cannot use &amp; (bug 2620)
  773. $url = preg_replace('/&amp;/', '&', $url);
  774. }
  775. return($url);
  776. }
  777. /* this ewiki_script() wrapper is used to generate URLs to binary
  778. content in the ewiki database
  779. */
  780. function ewiki_script_binary($asid, $id=false, $params=array(), $upload=0) {
  781. $upload |= is_string($params) && strlen($params) || count($params);
  782. #-- generate URL directly to the plainly saved data file,
  783. # see also plugins/binary_store
  784. if (defined("EWIKI_DB_STORE_URL") && !$upload) {
  785. $url = EWIKI_DB_STORE_URL . rawurlencode($id);
  786. }
  787. #-- else get standard URL (thru ewiki.php) from ewiki_script()
  788. else {
  789. $url = ewiki_script($asid, $id, $params, "_BINARY=1");
  790. }
  791. return($url);
  792. }
  793. /* this function returns the absolute ewiki_script url, if EWIKI_SCRIPT_URL
  794. is set, else it guesses the value
  795. */
  796. function ewiki_script_url() {
  797. global $ewiki_action, $ewiki_id, $ewiki_config;
  798. $scr_template = $ewiki_config["script"];
  799. $scr_current = ewiki_script($ewiki_action, $ewiki_id);
  800. $req_uri = $_SERVER["REQUEST_URI"];
  801. if ($url = $ewiki_config["script_url"]) {
  802. return($url);
  803. }
  804. elseif (strpos($req_uri, $scr_current) !== false) {
  805. $url = str_replace($req_uri, $scr_current, $scr_template);
  806. }
  807. elseif (strpos($req_uri, "?") && (strpos($scr_template, "?") !== false)) {
  808. $url = substr($req_uri, 0, strpos($req_uri, "?"))
  809. . substr($scr_template, strpos($scr_template, "?"));
  810. }
  811. elseif (strpos($req_uri, $sn = $_SERVER["SCRIPT_NAME"])) {
  812. $url = $sn . "?id=";
  813. }
  814. else {
  815. return(NULL); #-- could not guess it
  816. }
  817. #$url = "http://" . $_SERVER["SERVER_NAME"] . $url;
  818. return($url);
  819. }
  820. #------------------------------------------------------------ page plugins ---
  821. function ewiki_page_links($id, &$data, $action) {
  822. $o = ewiki_make_title($id, ewiki_t("PAGESLINKINGTO", array("title"=>$id)), 1, $action, "", "_MAY_SPLIT=1");
  823. if ($pages = ewiki_get_backlinks($id)) {
  824. $o .= ewiki_list_pages($pages);
  825. } else {
  826. $o .= ewiki_t("This page isn't linked from anywhere else.");
  827. }
  828. return($o);
  829. }
  830. function ewiki_get_backlinks($id) {
  831. $result = ewiki_database("SEARCH", array("refs" => $id));
  832. $pages = array();
  833. while ($row = $result->get(0, 0x0020)) {
  834. if ( strpos($row["refs"], "\n$id\n") !== false) {
  835. $pages[] = $row["id"];
  836. }
  837. }
  838. return($pages);
  839. }
  840. function ewiki_get_links($id) {
  841. if ($data = ewiki_database("GET", array("id"=>$id))) {
  842. $refs = explode("\n", trim($data["refs"]));
  843. $r = array();
  844. foreach (ewiki_database("FIND", $refs) as $id=>$exists) {
  845. if ($exists) {
  846. $r[] = $id;
  847. }
  848. }
  849. return($r);
  850. }
  851. }
  852. function ewiki_list_pages($pages=array(), $limit=EWIKI_LIST_LIMIT,
  853. $value_as_title=0, $pf_list=false)
  854. {
  855. global $ewiki_plugins;
  856. $o = "";
  857. $is_num = !empty($pages[0]);
  858. $lines = array();
  859. $n = 0;
  860. foreach ($pages as $id=>$add_text) {
  861. $title = $id;
  862. $params = "";
  863. if (is_array($add_text)) {
  864. list($id, $params, $title, $add_text) = $add_text;
  865. }
  866. elseif ($is_num) {
  867. $id = $title = $add_text;
  868. $add_text = "";
  869. }
  870. elseif ($value_as_title) {
  871. $title = $add_text;
  872. $add_text = "";
  873. }
  874. $lines[] = '<a href="' . ewiki_script("", $id, $params) . '">' . s($title) . '</a> ' . $add_text;
  875. if (($limit > 0) && ($n++ >= $limit)) {
  876. break;
  877. }
  878. }
  879. if ($pf_a = @$ewiki_plugins["list_transform"])
  880. foreach ($pf_a as $pf_transform) {
  881. $pf_transform($lines);
  882. }
  883. if (($pf_list) || ($pf_list = @$ewiki_plugins["list_pages"][0])) {
  884. $o = $pf_list($lines);
  885. }
  886. elseif($lines) {
  887. $o = "&middot; " . implode("<br />\n&middot; ", $lines) . "<br />\n";
  888. }
  889. return($o);
  890. }
  891. function ewiki_page_ordered_list($orderby="created", $asc=0, $print, $title) {
  892. $o = ewiki_make_title("", $title, 2, ".list", "links", 0);
  893. $sorted = array();
  894. $result = ewiki_database("GETALL", array($orderby));
  895. while ($row = $result->get()) {
  896. $row = ewiki_database("GET", array(
  897. "id" => $row["id"],
  898. ($asc >= 0 ? "version" : "uu") => 1 // version 1 is most accurate for {hits}
  899. ));
  900. #-- text page?
  901. if (EWIKI_DB_F_TEXT == ($row["flags"] & EWIKI_DB_F_TYPE)) {
  902. #-- viewing allowed?
  903. if (!EWIKI_PROTECTED_MODE || !EWIKI_PROTECTED_MODE_HIDING || ewiki_auth($row["id"], $row, "view")) {
  904. $sorted[$row["id"]] = $row[$orderby];
  905. }
  906. }
  907. }
  908. if ($asc != 0) { arsort($sorted); }
  909. else { asort($sorted); }
  910. foreach ($sorted as $name => $value) {
  911. if (empty($value)) { $value = "0"; }
  912. ##### BEGIN MOODLE ADDITION #####
  913. #$sorted[$name] = strftime(str_replace('%n', $value, $print), $value);
  914. if($print=="LASTCHANGED") {
  915. $value=strftime("%c",$value);
  916. }
  917. $sorted[$name] = get_string(strtolower($print),"wiki",$value);
  918. ##### BEGIN MOODLE ADDITION #####
  919. }
  920. $o .= ewiki_list_pages($sorted);
  921. return($o);
  922. }
  923. function ewiki_page_newest($id=0, $data=0) {
  924. return( ewiki_page_ordered_list("created", 1, "LASTCHANGED", ewiki_t(EWIKI_PAGE_NEWEST)) );
  925. }
  926. function ewiki_page_updates($id=0, $data=0) {
  927. return( ewiki_page_ordered_list("lastmodified", -1, "LASTCHANGED", ewiki_t(EWIKI_PAGE_UPDATES)) );
  928. }
  929. function ewiki_page_hits($id=0, $data=0) {
  930. ##### BEGIN MOODLE ADDITION #####
  931. return( ewiki_page_ordered_list("hits", 1, "hits", ewiki_t(EWIKI_PAGE_HITS)) );
  932. }
  933. function ewiki_page_versions($id=0, $data=0) {
  934. return( ewiki_page_ordered_list("version", -1, "changes", ewiki_t(EWIKI_PAGE_VERSIONS)) );
  935. ##### END MOODLE ADDITION #####
  936. }
  937. function ewiki_page_search($id, &$data, $action) {
  938. global $CFG;
  939. $o = ewiki_make_title($id, $id, 2, $action);
  940. if (! ($q = @$_REQUEST["q"])) {
  941. $o .= '<form action="' . ewiki_script("", $id) . '" method="post">';
  942. $o .= '<fieldset class="invisiblefieldset">';
  943. $o .= '<input name="q" size="30" /><br /><br />';
  944. $o .= '<input type="submit" value="'.$id.'" />';
  945. $o .= '</fieldset>';
  946. $o .= '</form>';
  947. }
  948. else {
  949. $found = array();
  950. if ($CFG->unicodedb) {
  951. $q = preg_replace('/\s*[\W]+\s*/u', ' ', $q);
  952. } else {
  953. $q = preg_replace('/\s*[^\w]+\s*/', ' ', $q);
  954. }
  955. foreach (explode(" ", $q) as $search) {
  956. if (empty($search)) { continue; }
  957. $result = ewiki_database("SEARCH", array("content" => $search));
  958. while ($row = $result->get()) {
  959. #-- show this entry in page listings?
  960. if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $row, "view")) {
  961. continue;
  962. }
  963. $found[] = $row["id"];
  964. }
  965. }
  966. $o .= ewiki_list_pages($found);
  967. }
  968. return($o);
  969. }
  970. function ewiki_page_info($id, &$data, $action) {
  971. global $ewiki_plugins, $ewiki_config, $ewiki_links;
  972. global $CFG, $course; // MOODLE HACK
  973. $o = ewiki_make_title($id, ewiki_t("INFOABOUTPAGE")." '{$id}'", 2, $action,"", "_MAY_SPLIT=1");
  974. $flagnames = array(
  975. "TEXT", "BIN", "DISABLED", "HTML", "READONLY", "WRITEABLE",
  976. "APPENDONLY", "SYSTEM",
  977. );
  978. $show = array(
  979. "version", "author", "userid", "created",
  980. "lastmodified", "refs",
  981. "flags", "meta", "content"
  982. );
  983. #-- versions to show
  984. $v_start = $data["version"];
  985. if ( ($uu=@$_REQUEST[EWIKI_UP_PAGENUM]) && ($uu<=$v_start) ) {
  986. $v_start = $uu;
  987. }
  988. $v_end = $v_start - $ewiki_config["list_limit"] + 1;
  989. if ( ($uu=@$_REQUEST[EWIKI_UP_PAGEEND]) && ($uu<=$v_start) ) {
  990. $v_end = $uu;
  991. }
  992. $v_end = max($v_end, 1);
  993. #-- go
  994. # the very ($first) entry is rendered more verbosely than the others
  995. for ($v=$v_start,$first=1; ($v>=$v_end); $v--,$first=0) {
  996. $current = ewiki_database("GET", array("id"=>$id, "version"=>$v));
  997. if (!strlen(trim($current["id"])) || !$current["version"] || !strlen(trim($current["content"]))) {
  998. continue;
  999. }
  1000. $o .= '<table class="version-info" cellpadding="2" cellspacing="1">' . "\n";
  1001. #-- additional info-actions
  1002. $commands = '';
  1003. foreach ($ewiki_config["action_links"]["info"] as $thisaction=>$title)
  1004. if (@$ewiki_plugins["action"][$thisaction] || @$ewiki_plugins["action_always"][$thisaction]) {
  1005. ##### BEGIN MOODLE ADDITION #####
  1006. if ($commands) {
  1007. $commands .= '&nbsp;&nbsp;';
  1008. }
  1009. $commands .= '<a href="' .
  1010. ewiki_script($thisaction, $id, array("version"=>$current["version"])) .
  1011. '">' . get_string($title,"wiki") . '</a>';
  1012. ##### END MOODLE ADDITION #####
  1013. }
  1014. #-- print page database entry
  1015. foreach($show as $i) {
  1016. $value = @$current[$i];
  1017. #-- show database {fields} differently
  1018. if ($i == "meta") {
  1019. continue; // MOODLE DOESN'T USE IT
  1020. $str = "";
  1021. if ($first && $value) { foreach ($value as $n=>$d) {
  1022. $str .= s("$n: $d") . "<br />\n";
  1023. } }
  1024. $value = $str;
  1025. }
  1026. elseif ($value >= UNIX_MILLENNIUM) { #-- {lastmodified}, {created}
  1027. #### BEGIN MOODLE CHANGE
  1028. $value=userdate($value);
  1029. #$value = strftime("%c", $value);
  1030. #### END MOODLE CHANGE
  1031. }
  1032. elseif ($i == "content") {
  1033. continue; // MOODLE DOESN'T CARE
  1034. $value = strlen(trim($value)) . " bytes";
  1035. $i = "content size";
  1036. }
  1037. elseif ($first && ($i == "refs") && !(EWIKI_PROTECTED_MODE && (EWIKI_PROTECTED_MODE_HIDING>=2))) {
  1038. $a = explode("\n", trim($value));
  1039. $ewiki_links = ewiki_database("FIND", $a);
  1040. ewiki_merge_links($ewiki_links);
  1041. foreach ($a as $n=>$link) {
  1042. $a[$n] = ewiki_link_regex_callback(array("$link"), "force_noimg");
  1043. }
  1044. $value = trim(implode(", ", $a));
  1045. if (!$value) {
  1046. continue;
  1047. }
  1048. }
  1049. elseif (strpos($value, "\n") !== false) { #-- also for {refs}
  1050. $value = str_replace("\n", ", ", trim($value));
  1051. if (!$value) {
  1052. continue;
  1053. }
  1054. }
  1055. elseif ($i == "version") {
  1056. $value = '<a href="' .
  1057. ewiki_script("", $id, array("version"=>$value)) . '">' .
  1058. $value . '</a> '."($commands)";
  1059. }
  1060. elseif ($i == "flags") {
  1061. continue; // MOODLE DOESN'T USE IT
  1062. $fstr = "";
  1063. for ($n = 0; $n < 32; $n++) {
  1064. if ($value & (1 << $n)) {
  1065. if (! ($s=$flagnames[$n])) { $s = "UU$n"; }
  1066. $fstr .= $s . " ";
  1067. }
  1068. }
  1069. $value = $fstr;
  1070. }
  1071. elseif ($i == "author") {
  1072. continue;
  1073. $ewiki_links=1;
  1074. $value = preg_replace_callback("/((\w+:)?([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}[\w\d]*)/", "ewiki_link_regex_callback", $value);
  1075. }
  1076. elseif ($i == "userid") {
  1077. $i = 'author';
  1078. if ($user = get_record('user', 'id', (int)$value)) {
  1079. if (!isset($course->id)) {
  1080. $course->id = 1;
  1081. }
  1082. $picture = print_user_picture($user->id, $course->id, $user->picture, false, true, true);
  1083. $value = $picture." <a href=\"$CFG->wwwroot/user/view.php?id=$user->id&amp;course=$course->id\">".fullname($user)."</a>";
  1084. } else {
  1085. continue;
  1086. //$value = @$current['author'];
  1087. }
  1088. }
  1089. ##### BEGIN MOODLE ADDITION #####
  1090. $o .= '<tr class="page-'.$i.'"><td style="vertical-align:top;text-align:right;white-space: nowrap;"><b>' .ewiki_t($i). ':</b></td>' .
  1091. '<td>' . $value . "</td></tr>\n";
  1092. ##### END MOODLE ADDITION #####
  1093. }
  1094. $o .= "</table><br /><br />\n";
  1095. }
  1096. #-- page result split
  1097. if ($v >= 1) {
  1098. $o .= "<br />\n".get_string('showversions','wiki').' '.ewiki_chunked_page($action, $id, -1, $v, 1, 0, 0) . "\n <br />";
  1099. }
  1100. return($o);
  1101. }
  1102. function ewiki_chunked_page($action, $id, $dir=-1, $start=10, $end=1, $limit=0, $overlap=0.25, $collapse_last=0.67) {
  1103. global $ewiki_config;
  1104. if (empty($limit)) {
  1105. $limit = $ewiki_config["list_limit"];
  1106. }
  1107. if ($overlap < 1) {
  1108. $overlap = (int) ($limit * $overlap);
  1109. }
  1110. $p = "";
  1111. $n = $start;
  1112. while ($n) {
  1113. $n -= $dir * $overlap;
  1114. $e = $n + $dir * ($limit + $overlap) + 1;
  1115. if ($dir<0) {
  1116. $e = max(1, $e);
  1117. if ($e <= $collapse_last * $limit) {
  1118. $e = 1;
  1119. }
  1120. }
  1121. else {
  1122. $e = min($end, $e);
  1123. if ($e >= $collapse_last * $limit) {
  1124. $e = $end;
  1125. }
  1126. }
  1127. $o .= ($o?" &middot; ":"")
  1128. . '<a href="'.ewiki_script($action, $id, array(EWIKI_UP_PAGENUM=>$n, EWIKI_UP_PAGEEND=>$e))
  1129. . '">'. "$n-$e" . '</a>';
  1130. if (($n=$e-1) < $end) {
  1131. $n = false;
  1132. }
  1133. }
  1134. return('<span class="chunked-result">'. $o .'</span>');
  1135. }
  1136. function ewiki_page_edit($id, $data, $action) {
  1137. global $ewiki_links, $ewiki_author, $ewiki_plugins, $ewiki_ring, $ewiki_errmsg;
  1138. $hidden_postdata = array();
  1139. #-- previous version come back
  1140. if (@$data["forced_version"]) {
  1141. $current = ewiki_database("GET", array("id"=>$id));
  1142. $data["version"] = $current["version"];
  1143. unset($current);
  1144. unset($_REQUEST["content"]);
  1145. unset($_REQUEST["version"]);
  1146. }
  1147. #-- edit hacks
  1148. if ($pf_a = @$ewiki_plugins["edit_hook"]) foreach ($pf_a as $pf) {
  1149. if ($output = $pf($id, $data, $hidden_postdata)) {
  1150. return($output);
  1151. }
  1152. }
  1153. #-- permission checks
  1154. if (isset($ewiki_ring)) {
  1155. $ring = $ewiki_ring;
  1156. } else {
  1157. $ring = 3;
  1158. }
  1159. $flags = @$data["flags"];
  1160. if (!($flags & EWIKI_DB_F_WRITEABLE)) {
  1161. #-- perform auth
  1162. $edit_ring = (EWIKI_PROTECTED_MODE>=2) ? (2) : (NULL);
  1163. if (EWIKI_PROTECTED_MODE && !ewiki_auth($id, $data, $action, $edit_ring, "FORCE")) {
  1164. return($ewiki_errmsg);
  1165. }
  1166. #-- flag checking
  1167. if (($flags & EWIKI_DB_F_READONLY) and ($ring >= 2)) {
  1168. return(ewiki_t("CANNOTCHANGEPAGE"));
  1169. }
  1170. if (($flags) and (($flags & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT) and ($ring >= 1)) {
  1171. return(ewiki_t("CANNOTCHANGEPAGE"));
  1172. }
  1173. }
  1174. #-- "Edit Me"
  1175. $o = ewiki_make_title($id, ewiki_t("EDITTHISPAGE").(" '{$id}'"), 2, $action, "", "_MAY_SPLIT=1");
  1176. #-- preview
  1177. if (isset($_REQUEST["preview"])) {
  1178. $o .= $ewiki_plugins["edit_preview"][0]($data);
  1179. }
  1180. #-- save
  1181. if (isset($_REQUEST["save"])) {
  1182. #-- normalize to UNIX newlines
  1183. $_REQUEST["content"] = str_replace("\015\012", "\012", $_REQUEST["content"]);
  1184. $_REQUEST["content"] = str_replace("\015", "\012", $_REQUEST["content"]);
  1185. #-- check for concurrent version saving
  1186. $error = 0;
  1187. if ((@$data["version"] >= 1) && ($data["version"] != @$_REQUEST["version"]) || (@$_REQUEST["version"] < 1)) {
  1188. $pf = $ewiki_plugins["edit_patch"][0];
  1189. if (!$pf || !$pf($id, $data)) {
  1190. $error = 1;
  1191. $o .= ewiki_t("ERRVERSIONSAVE") . "<br /><br />";
  1192. }
  1193. }
  1194. if (!$error) {
  1195. #-- new pages` flags
  1196. if (! ($set_flags = @$data["flags"] & EWIKI_DB_F_COPYMASK)) {
  1197. $set_flags = 1;
  1198. }
  1199. if (EWIKI_ALLOW_HTML) {
  1200. $set_flags |= EWIKI_DB_F_HTML;
  1201. }
  1202. #-- mk db entry
  1203. $save = array(
  1204. "id" => $id,
  1205. "version" => @$data["version"] + 1,
  1206. "flags" => $set_flags,
  1207. "content" => $_REQUEST["content"],
  1208. "created" => ($uu=@$data["created"]) ? $uu : time(),
  1209. "meta" => ($uu=@$data["meta"]) ? $uu : "",
  1210. "hits" => ($uu=@$data["hits"]) ? $uu : "0",
  1211. );
  1212. ewiki_data_update($save);
  1213. #-- edit storage hooks
  1214. if ($pf_a = @$ewiki_plugins["edit_save"]) {
  1215. foreach ($pf_a as $pf) {
  1216. $pf($save, $data);
  1217. }
  1218. }
  1219. #-- save
  1220. if (!$save || !ewiki_database("WRITE", $save)) {
  1221. $o .= $ewiki_errmsg ? $ewiki_errmsg : ewiki_t("ERRORSAVING");
  1222. }
  1223. else {
  1224. #-- prevent double saving, when ewiki_page() is re-called
  1225. $_REQUEST = $_GET = $_POST = array();
  1226. $o = ewiki_t("THANKSFORCONTRIBUTION") . "<br /><br />";
  1227. $o .= ewiki_page($id);
  1228. if (EWIKI_EDIT_REDIRECT) {
  1229. $url = ewiki_script("", $id, "thankyou=1", 0, 0, EWIKI_HTTP_HEADERS?ewiki_script_url():0);
  1230. if (EWIKI_HTTP_HEADERS && !headers_sent()) {
  1231. header("Status: 303 Redirect for GET");
  1232. header("Location: $url");
  1233. #header("URI: $url");
  1234. #header("Refresh: 0; URL=$url");
  1235. }
  1236. else {
  1237. $o .= '<meta http-equiv="Refresh" content="0; URL='.s($url).'">';
  1238. }
  1239. }
  1240. }
  1241. }
  1242. //@REWORK
  1243. // header("Reload-Location: " . ewiki_script("", $id, "", 0, 0, ewiki_script_url()) );
  1244. }
  1245. else {
  1246. #-- Edit <form>
  1247. $o .= ewiki_page_edit_form($id, $data, $hidden_postdata);
  1248. #-- additional forms
  1249. if ($pf_a = $ewiki_plugins["edit_form_final"]) foreach ($pf_a as $pf) {
  1250. $pf($o, $id, $data, $action);
  1251. }
  1252. }
  1253. return($o);
  1254. }
  1255. function ewiki_data_update(&$data, $author="") {
  1256. global $USER, $ewiki_links;
  1257. #-- add backlinks entry
  1258. ewiki_scan_wikiwords($data["content"], $ewiki_links, "_STRIP_EMAIL=1");
  1259. $data["refs"] = "\n\n".implode("\n", array_keys($ewiki_links))."\n\n";
  1260. $data["lastmodified"] = time();
  1261. $data["author"] = ewiki_author($author);
  1262. if (isset($USER->id)) {
  1263. $data["userid"] = $USER->id;
  1264. }
  1265. }
  1266. #-- edit <textarea>
  1267. function ewiki_page_edit_form(&$id, &$data, &$hidden_postdata) {
  1268. global $ewiki_plugins, $ewiki_config, $moodle_format;
  1269. $o='';
  1270. #-- previously edited, or db fetched content
  1271. if (@$_REQUEST["content"] || @$_REQUEST["version"]) {
  1272. $data = array(
  1273. "version" => &$_REQUEST["version"],
  1274. "content" => &$_REQUEST["content"]
  1275. );
  1276. }
  1277. else {
  1278. if (empty($data["version"])) {
  1279. $data["version"] = 1;
  1280. }
  1281. @$data["content"] .= "";
  1282. }
  1283. #-- normalize to DOS newlines
  1284. $data["content"] = str_replace("\015\012", "\012", $data["content"]);
  1285. $data["content"] = str_replace("\015", "\012", $data["content"]);
  1286. $data["content"] = str_replace("\012", "\015\012", $data["content"]);
  1287. $hidden_postdata["version"] = &$data["version"];
  1288. #-- edit textarea/form
  1289. // deleted name="ewiki", can not find the reference, and it's breaking xhtml
  1290. $o .= ewiki_t("EDIT_FORM_1")
  1291. . '<form method="post" enctype="multipart/form-data" action="'
  1292. . ewiki_script("edit", $id) . '" '
  1293. . ' accept-charset="'.EWIKI_CHARSET.'">' . "\n";
  1294. $o .= '<div>';
  1295. #-- additional POST vars
  1296. foreach ($hidden_postdata as $name => $value) {
  1297. $o .= '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
  1298. }
  1299. ($cols = strtok($ewiki_config["edit_box_size"], "x*/,;:")) && ($rows = strtok("x, ")) || ($cols=70) && ($rows=15);
  1300. global $ewiki_use_editor, $ewiki_editor_content;
  1301. $ewiki_editor_content=1;
  1302. if($ewiki_use_editor) {
  1303. ob_start();
  1304. $usehtmleditor = can_use_html_editor();
  1305. echo '<table><tr><td>';
  1306. if ($usehtmleditor) { //clean and convert before editing
  1307. $options = new object();
  1308. $options->smiley = false;
  1309. $options->filter = false;
  1310. $oldtext = format_text(ewiki_format($data["content"]), $moodle_format, $options);
  1311. } else {
  1312. $oldtext = ewiki_format($data["content"]);
  1313. }
  1314. print_textarea($usehtmleditor, $rows, $cols, 680, 400, "content", $oldtext);
  1315. echo '</td></tr></table>';
  1316. if ($usehtmleditor) {
  1317. use_html_editor("content");
  1318. }
  1319. $o .= ob_get_contents();
  1320. ob_end_clean();
  1321. } else {
  1322. ##### END MOODLE ADDITION #####
  1323. $o .= '<textarea wrap="soft" id="ewiki_content" name="content" rows="'.$rows.'" cols="'.$cols.'">'
  1324. . s($data["content"]) . "</textarea>"
  1325. . $GLOBALS["ewiki_t"]["C"]["EDIT_TEXTAREA_RESIZE_JS"];
  1326. ##### BEGIN MOODLE ADDITION #####
  1327. }
  1328. ##### END MOODLE ADDITION #####
  1329. #-- more <input> elements before the submit button
  1330. if ($pf_a = $ewiki_plugins["edit_form_insert"]) foreach ($pf_a as $pf) {
  1331. $o .= $pf($id, $data, $action);
  1332. }
  1333. ##### BEGIN MOODLE ADDITION (Cancel Editing into Button) #####
  1334. $o .= "\n<br />\n"
  1335. . '<input type="submit" name="save" value="'. ewiki_t("SAVE") . '" />'."\n"
  1336. . '<input type="submit" name="preview" value="'. ewiki_t("PREVIEW") . '" />' . "\n"
  1337. . '<input type="submit" name="canceledit" value="'. ewiki_t("CANCEL_EDIT") . '" />' . "\n";
  1338. # . ' &nbsp; <a href="'. ewiki_script("", $id) . '">' . ewiki_t("CANCEL_EDIT") . '</a>';
  1339. ##### END MOODLE ADDITION #####
  1340. #-- additional form elements
  1341. if ($pf_a = $ewiki_plugins["edit_form_append"]) foreach ($pf_a as $pf) {
  1342. $o .= $pf($id, $data, $action);
  1343. }
  1344. $o .= "\n</div></form>\n";
  1345. // . ewiki_t("EDIT_FORM_2"); // MOODLE DELETION
  1346. return('<div class="edit-box">'. $o .'</div>');
  1347. }
  1348. #-- pic upload form
  1349. function ewiki_page_edit_form_final_imgupload(&$o, &$id, &$data, &$action) {
  1350. if (EWIKI_SCRIPT_BINARY && EWIKI_UP_UPLOAD && EWIKI_IMAGE_MAXSIZE) {
  1351. $o .= "\n<br />\n". '<div class="image-upload">'
  1352. . '<form action='
  1353. . '"'. ewiki_script_binary("", EWIKI_IDF_INTERNAL, "", "_UPLOAD=1") .'"'
  1354. . ' method="post" enctype="multipart/form-data" target="_upload">'
  1355. . '<fieldset class="invisiblefieldset">'
  1356. . '<input type="hidden" name="MAX_FILE_SIZE" value="'.EWIKI_IMAGE_MAXSIZE.'" />'
  1357. . '<input type="file" name="'.EWIKI_UP_UPLOAD.'"'
  1358. . (defined("EWIKI_IMAGE_ACCEPT") ? ' accept="'.EWIKI_IMAGE_ACCEPT.'" />' : " />")
  1359. . '<input type="hidden" name="'.EWIKI_UP_BINARY.'" value="'.EWIKI_IDF_INTERNAL.'" />'
  1360. . '&nbsp;&nbsp;&nbsp;'
  1361. . '<input type="submit" value="'.ewiki_t("UPLOAD_PICTURE_BUTTON").'" />'
  1362. . '</fieldset></form></div>'. "\n";
  1363. }
  1364. }
  1365. function ewiki_page_edit_preview(&$data) {
  1366. #### BEGIN MOODLE CHANGES
  1367. global $moodle_format;
  1368. $preview_text=$GLOBALS["ewiki_plugins"]["render"][0]($_REQUEST["content"], 1, EWIKI_ALLOW_HTML || (@$data["flags"]&EWIKI_DB_F_HTML));
  1369. return( '<div class="preview">'
  1370. . "<hr noshade>"
  1371. . "<div class='mdl-right'>" . ewiki_t("PREVIEW") . "</div><hr noshade><br />\n"
  1372. . format_text($preview_text, $moodle_format)
  1373. . "<br /><br /><hr noshade><br />"
  1374. . "</div>"
  1375. );
  1376. #### END MOODLE CHANGES
  1377. }
  1378. function ewiki_control_links($id, &$data, $action) {
  1379. global $ewiki_plugins, $ewiki_ring, $ewiki_config;
  1380. $action_links = & $ewiki_config["action_links"][$action];
  1381. #-- disabled
  1382. if (!$ewiki_config["control_line"]) {
  1383. return("");
  1384. }
  1385. $o = "\n"
  1386. . '<div class="mdl-right action-links control-links">'
  1387. . "\n<br />\n"
  1388. . "<hr noshade>" . "\n";
  1389. if (@$data["forced_version"]) {
  1390. $o .= '<form action="' . ewiki_script("edit", $id) . '" method="post">' .
  1391. '<fieldset class="invisiblefieldset">'.
  1392. '<input type="hidden" name="edit" value="old" />' .
  1393. '<input type="hidden" name="version" value="'.$data["forced_version"].'" />' .
  1394. '<input type="submit" value="' . ewiki_t("OLDVERCOMEBACK") . '" /></form> ';
  1395. }
  1396. else {
  1397. foreach ($action_links as $action => $title)
  1398. if (!empty($ewiki_plugins["action"][$action]) || !empty($ewiki_plugins["action_always"][$action]) || strpos($action, ":/"))
  1399. {
  1400. if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($id, $data, $action)) { continue; }
  1401. $o .= '<a href="'
  1402. . (strpos($action, ":/") ? $action : ewiki_script($action, $id))
  1403. . '">' . ewiki_t($title) . '</a> &middot; ';
  1404. }
  1405. }
  1406. if ($data["lastmodified"] >= UNIX_MILLENNIUM) {
  1407. $o .= '<small>' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . '</small>';
  1408. }
  1409. $o .= "</div>\n";
  1410. return($o);
  1411. }
  1412. # ============================================================= rendering ===
  1413. ######## ### ### ######### ### ### ### #######
  1414. ######## #### ### ######### ### #### ### #######
  1415. ### ##### ### ### ##### ### ###
  1416. ###### ######### ### #### ### ######### ######
  1417. ###### ######### ### #### ### ######### ######
  1418. ### ### ##### ### ### ### ### ##### ###
  1419. ######## ### #### ######### ### ### #### #######
  1420. ######## ### ### ######### ### ### ### #######
  1421. /*
  1422. The _format() function transforms $wiki_source pages into <html> strings,
  1423. also calls various markup and helper plugins during the transformation
  1424. process. The $params array can activate various features and extensions.
  1425. only accepts UNIX newlines!
  1426. */
  1427. function ewiki_format (
  1428. $wiki_source,
  1429. $params = array()
  1430. )
  1431. {
  1432. global $ewiki_links, $ewiki_plugins, $ewiki_config;
  1433. #-- state vars
  1434. $params = @array_merge($ewiki_config["format_params"], $params);
  1435. $s = array(
  1436. "in" => 0, # current input $iii[] block array index
  1437. "para" => "",
  1438. "line" => "",
  1439. "post" => "", # string to append after current line/paragraph
  1440. "line_i" => 0,
  1441. "lines" => array(),
  1442. "list" => "", # lists
  1443. "tbl" => 0, # open table?
  1444. "indent" => 0, # indentation
  1445. "close" => array(),
  1446. );
  1447. #-- aliases
  1448. $in = &$s["in"];
  1449. $line = &$s["line"];
  1450. $lines = &$s["lines"];
  1451. $para = &$s["para"];
  1452. $post = &$s["post"];
  1453. $list = &$s["list"];
  1454. #-- input and output arrays
  1455. if ($wiki_source[0] == "<") { # also prepend an empty line
  1456. $wiki_source = "\n" . $wiki_source; # for faster strpos() searchs
  1457. }
  1458. $iii = array(
  1459. 0 => array(
  1460. 0 => $wiki_source."\n", # body + empty line
  1461. 1 => 0x0FFF, # flags (0x1=WikiMarkup, 0x2=WikiLinks, 0x100=BlockPlugins)
  1462. 2 => "core", # block plugin name
  1463. )
  1464. );
  1465. $ooo = array(
  1466. );
  1467. unset($wiki_source);
  1468. #-- plugins
  1469. $pf_tbl = @$ewiki_plugins["format_table"][0];
  1470. $pf_line = @$ewiki_plugins["format_line"];
  1471. #-- wikimarkup (wm)
  1472. $htmlentities = $ewiki_config["htmlentities"];
  1473. $wm_indent = &$ewiki_config["wm_indent"];
  1474. $wm_table_defaults = &$ewiki_config["wm_table_defaults"];
  1475. $wm_source = &$ewiki_config["wm_source"];
  1476. $wm_list = &$ewiki_config["wm_list"];
  1477. $wm_list_chars = implode("", array_keys($wm_list));
  1478. $wm_style = &$ewiki_config["wm_style"];
  1479. $wm_start_end = &$ewiki_config["wm_start_end"];
  1480. #-- eleminate html
  1481. $iii[0][0] = strtr($iii[0][0], $htmlentities);
  1482. unset($htmlentities["&"]);
  1483. #-- pre-processing plugins (working on wiki source)
  1484. if ($pf_source = $ewiki_plugins["format_source"]) {
  1485. foreach ($pf_source as $pf) $pf($iii[0][0]);
  1486. }
  1487. #-- simple markup
  1488. $iii[0][0] = strtr($iii[0][0], $wm_source);
  1489. #-- separate input into blocks ------------------------------------------
  1490. foreach ($ewiki_config["format_block"] as $btype => $binfo) {
  1491. #-- disabled block plugin?
  1492. if ($binfo[2] && !$params[$binfo[2]]) {
  1493. continue;
  1494. }
  1495. #-- traverse $iii[]
  1496. $in = -1;
  1497. while ((++$in) < count($iii)) {
  1498. #-- search fragment delimeters
  1499. if ($iii[$in][1] & 0x0100)
  1500. while (
  1501. ($c = & $iii[$in][0]) &&
  1502. (($l = strpos($c, $binfo[0])) !== false) &&
  1503. ($r = strpos($c, $binfo[1], $l)) )
  1504. {
  1505. $l_len = strlen($binfo[0]);
  1506. $r_len = strlen($binfo[1]);
  1507. $repl = array();
  1508. // pre-text
  1509. if (($l > 0) && trim($text = substr($c, 0, $l))) {
  1510. $repl[] = array($text, 0xFFFF, "core");
  1511. }
  1512. // the extracted part
  1513. if (trim($text = substr($c, $l+$l_len, $r-$l-$r_len))) {
  1514. $repl[] = array($text, $binfo[3], "$btype");
  1515. }
  1516. // rest
  1517. if (($r+$r_len < strlen($c)) && trim($text = substr($c, $r+$r_len))) {
  1518. $repl[] = array($text, 0xFFFF, "core");
  1519. }
  1520. array_splice($iii, $in, 1, $repl);
  1521. $in += 1;
  1522. }
  1523. }
  1524. }
  1525. #-- run format_block plugins
  1526. $in = -1;
  1527. while ((++$in) < count($iii)) {
  1528. if (($btype = $iii[$in][2]) && ($pf_a = $ewiki_plugins["format_block"][$btype])) {
  1529. $c = &$iii[$in][0];
  1530. foreach ($pf_a as $pf) {
  1531. # current buffer $c and pointer $in into $iii[] and state $s
  1532. $pf($c, $in, $iii, $s, $btype);
  1533. }
  1534. }
  1535. }
  1536. #-- wiki markup ------------------------------------------------------
  1537. $para = "";
  1538. $in = -1;
  1539. while ((++$in) < count($iii)) {
  1540. #-- wikimarkup
  1541. if ($iii[$in][1] & 0x0001) {
  1542. #-- input $lines buffer, and output buffer $ooo array
  1543. $lines = explode("\n", $iii[$in][0]);
  1544. $ooo[$in] = array(
  1545. 0 => "",
  1546. 1 => $iii[$in][1]
  1547. );
  1548. $out = &$ooo[$in][0];
  1549. $s["block"] = ($iii[$in][2] != "core"); # disables indentation & paragraphs
  1550. #-- walk through wiki source lines
  1551. $line_max = count($lines);
  1552. foreach ($lines as $s["line_i"]=>$line) {
  1553. //echo "<pre>line={$s[line_i]}:".htmlspecialchars($line).":".htmlspecialchars($line[0])."</pre>";
  1554. #-- empty lines separate paragraphs
  1555. if (!strlen($line)) {
  1556. ewiki_format_close_para($ooo, $s);
  1557. ewiki_format_close_tags($ooo, $s);
  1558. if (!$s["block"]) {
  1559. $out .= "\n";
  1560. }
  1561. }
  1562. #-- horiz bar
  1563. if (!strncmp($line, "----", 4)) {
  1564. $out .= "<hr noshade>\n";
  1565. continue;
  1566. }
  1567. #-- html comment
  1568. #if (!strncmp($line, "&lt;!--", 7)) {
  1569. # $out .= "<!-- " . htmlentities(str_replace("--", "__", substr($line, 7))) . " -->\n";
  1570. # continue;
  1571. #}
  1572. ($c0 = $line[0])
  1573. or ($c0 = "\000");
  1574. #-- tables
  1575. ### MOODLE CHANGE: TRIM
  1576. if (($c0 == "|") && ($line[strlen(trim($line))-1] == "|")) {
  1577. if (!$s["tbl"]) {
  1578. ewiki_format_close_para($ooo, $s);
  1579. ewiki_format_close_tags($ooo, $s);
  1580. $s["list"] = "";
  1581. }
  1582. $line = substr($line, 1, -1);
  1583. if ($pf_tbl) {
  1584. $pf_tbl($line, $ooo, $s);
  1585. }
  1586. else {
  1587. if (!$s["tbl"]) {
  1588. $out .= "<table " . $wm_table_defaults . ">\n";
  1589. $s["close"][] = "\n</table>";
  1590. }
  1591. $line = "<tr>\n<td>" . str_replace("|", "</td>\n<td>", $line) . "</td>\n</tr>";
  1592. }
  1593. $s["tbl"] = 1;
  1594. $para = false;
  1595. }
  1596. elseif ($s["tbl"]) {
  1597. $s["tbl"] = 0;
  1598. }
  1599. #-- headlines
  1600. if (($c0 == "!") && ($excl = strspn($line, "!"))) {
  1601. if ($excl > 3) {
  1602. $excl = 3;
  1603. }
  1604. $line = substr($line, $excl);
  1605. $excl = 5 - $excl;
  1606. $line = "<h$excl>" . $line . "</h$excl>";
  1607. if ($para) {
  1608. ewiki_format_close_para($ooo, $s);
  1609. }
  1610. ewiki_format_close_tags($ooo, $s);
  1611. $para = false;
  1612. }
  1613. #-- whole-line markup
  1614. # ???
  1615. #-- indentation (space/tab markup)
  1616. $n_indent = 0;
  1617. if (!$list && (!$s["block"]) && ($n_indent = strspn($line, " "))) {
  1618. $n_indent = (int) ($n_indent / 2.65);
  1619. while ($n_indent > $s["indent"]) {
  1620. $out .= $wm_indent;
  1621. $s["indent"]++;
  1622. }
  1623. }
  1624. while ($n_indent < $s["indent"]) {
  1625. $out .= "";
  1626. $s["indent"]--;
  1627. }
  1628. #-- text style triggers
  1629. foreach ($wm_style as $find=>$replace) {
  1630. $find_len = strlen($find);
  1631. $loop = 20;
  1632. while(($loop--) && (($l = strpos($line, $find)) !== false) && ($r = strpos($line, $find, $l + $find_len))) {
  1633. $line = substr($line, 0, $l) . $replace[0] .
  1634. substr($line, $l + strlen($find), $r - $l - $find_len) .
  1635. $replace[1] . substr($line, $r + $find_len);
  1636. }
  1637. }
  1638. #-- list markup
  1639. if (isset($wm_list[$c0])) {
  1640. if (!$list) {
  1641. ewiki_format_close_para($ooo, $s);
  1642. ewiki_format_close_tags($ooo, $s);
  1643. }
  1644. $new_len = strspn($line, $wm_list_chars);
  1645. $new_list = substr($line, 0, $new_len);
  1646. $old_len = strlen($list);
  1647. $lchar = $new_list[$new_len-1];
  1648. list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
  1649. #-- cut line
  1650. $line = substr($line, $new_len);
  1651. $lspace = "";
  1652. $linsert = "";
  1653. if ($ltag1) {
  1654. $linsert = "<$ltag1>" . strtok($line, $lchar) . "</$ltag1> ";
  1655. $line = strtok("\000");
  1656. }
  1657. #-- add another <li>st entry
  1658. if ($new_len == $old_len) {
  1659. $lspace = str_repeat(" ", $new_len);
  1660. $out .= "</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
  1661. }
  1662. #-- add list
  1663. elseif ($new_len > $old_len) {
  1664. while ($new_len > ($old_len=strlen($list))) {
  1665. $lchar = $new_list[$old_len];
  1666. $list .= $lchar;
  1667. list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
  1668. $lclose = strtok($lopen, " ");
  1669. $lspace = str_repeat(" ", $new_len);
  1670. $out .= "\n$lspace<$lopen>\n" . "$lspace". $linsert . "<$ltag2>";
  1671. $s["close"][] = "$lspace</$lclose>";
  1672. $s["close"][] = "$lspace</$ltag2>";
  1673. }
  1674. }
  1675. #-- close lists
  1676. else {
  1677. while ($new_len < ($old_len=strlen($list))) {
  1678. $remove = $old_len-$new_len;
  1679. ewiki_format_close_tags($ooo, $s, 2*$remove);
  1680. $list = substr($list, 0, -$remove);
  1681. }
  1682. if ($new_len) {
  1683. $lspace = str_repeat(" ", $new_len);
  1684. $out .= "$lspace</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
  1685. }
  1686. }
  1687. $list = $new_list;
  1688. $para = false;
  1689. }
  1690. elseif ($list) {
  1691. if ($c0 == " ") {
  1692. $para = false;
  1693. }
  1694. else {
  1695. ewiki_format_close_tags($ooo, $s);
  1696. $list = "";
  1697. }
  1698. }
  1699. #-- start-end markup
  1700. foreach ($wm_start_end as $d) {
  1701. $len0 = strlen($d[0]);
  1702. $loop = 20;
  1703. while(($loop--) && (($l = strpos($line, $d[0])) !== false) && ($r = strpos($line, $d[1], $l + $len0))) {
  1704. $len1 = strlen($d[1]);
  1705. $line = substr($line, 0, $l) . $d[2] .
  1706. substr($line, $l + $len0, $r - $l - $len0) .
  1707. $replace[1] . substr($line, $r + $len1);
  1708. }
  1709. }
  1710. #-- call wiki source formatting plugins that work on current line
  1711. if ($pf_line) {
  1712. foreach ($pf_line as $pf) $pf($out, $line, $post);
  1713. }
  1714. #-- add formatted line to page-output
  1715. $line .= $post;
  1716. if ($para === false) {
  1717. $out .= $line;
  1718. $para = "";
  1719. }
  1720. else {
  1721. $para .= $line . "\n";
  1722. }
  1723. }
  1724. #-- last block, or next not WikiSource?
  1725. if (!isset($iii[$in+1]) || !($iii[$in+1][1] & 0x0011)) {
  1726. ewiki_format_close_para($ooo, $s);
  1727. ewiki_format_close_tags($ooo, $s);
  1728. }
  1729. }
  1730. #-- copy as is into output buffer
  1731. else {
  1732. $ooo[$in] = $iii[$in];
  1733. }
  1734. $iii[$in] = array();
  1735. }
  1736. #-- wiki linking ------------------------------------------------------
  1737. $scan_src = "";
  1738. for ($in=0; $in<count($ooo); $in++) {
  1739. if (EWIKI_HTML_CHARS && ($ooo[$in][1] & 0x0004)) { # html character entities
  1740. $ooo[$in][0] = str_replace("&amp;#", "&#", $ooo[$in][0]);
  1741. }
  1742. if ($ooo[$in][1] & 0x0022) {
  1743. #-- join together multiple WikiSource blocks
  1744. while (isset($ooo[$in+1]) && ($ooo[$in][1] & 0x0002) && ($ooo[$in+1][1] & 0x0002)) {
  1745. $ooo[$in] = array(
  1746. 0 => $ooo[$in][0] . "\n" . $ooo[$in+1][0],
  1747. 1 => $ooo[$in][1] | $ooo[$in+1][1],
  1748. );
  1749. array_splice($ooo, $in+1, 1);
  1750. }
  1751. }
  1752. $scan_src .= $ooo[$in][0];
  1753. }
  1754. #-- pre-scan
  1755. if (1+$params["scan_links"]) {
  1756. ewiki_scan_wikiwords($scan_src, $ewiki_links);
  1757. }
  1758. if ($pf_linkprep = $ewiki_plugins["format_prepare_linking"]) {
  1759. foreach ($pf_linkprep as $pf) $pf($scan_src);
  1760. }
  1761. $scan_src = NULL;
  1762. #-- finally the link-detection-regex
  1763. for ($in=0; $in<count($ooo); $in++) {
  1764. if ($ooo[$in][1] & 0x0002) {
  1765. ##### BEGIN MOODLE ADDITION #####
  1766. # No WikiLinks in Editor
  1767. #################################
  1768. global $ewiki_use_editor, $ewiki_editor_content;
  1769. if(!($ewiki_use_editor && $ewiki_editor_content)) {
  1770. ##### END MOODLE ADDITION #####
  1771. ewiki_render_wiki_links($ooo[$in][0]);
  1772. ##### BEGIN MOODLE ADDITION #####
  1773. }
  1774. ##### END MOODLE ADDITION #####
  1775. }
  1776. }
  1777. #-- fin: combine all blocks into html string ----------------------------
  1778. $html = "";
  1779. for ($in=0; $in<count($ooo); $in++) {
  1780. $html .= $ooo[$in][0] . "\n";
  1781. $ooo[$in] = 0;
  1782. }
  1783. #-- call post processing plugins
  1784. if ($pf_final = $ewiki_plugins["format_final"]) {
  1785. foreach ($pf_final as $pf) $pf($html);
  1786. }
  1787. return($html);
  1788. }
  1789. function ewiki_format_close_para(&$ooo, &$s) {
  1790. $out = &$ooo[$s["in"]][0];
  1791. #-- output text block
  1792. if (trim($s["para"])) {
  1793. if (!$s["block"]) {
  1794. #### MOODLE CHANGES
  1795. global $ewiki_use_editor;
  1796. if(!$ewiki_use_editor) {
  1797. $s["para"] = "\n<p>\n" . ltrim($s["para"], "\n") . "</p>\n";
  1798. }
  1799. #### MOODLE CHANGES
  1800. }
  1801. #-- paragraph formation plugins
  1802. if ($pf_a = $GLOBALS["ewiki_plugins"]["format_para"]) {
  1803. foreach ($pf_a as $pf) {
  1804. $pf($s["para"], $ooo, $s);
  1805. }
  1806. }
  1807. $out .= $s["para"];
  1808. $s["para"] = "";
  1809. }
  1810. #-- indentation
  1811. while ($s["indent"]) {
  1812. $out .= "";
  1813. $s["indent"]--;
  1814. }
  1815. }
  1816. function ewiki_format_close_tags(&$ooo, &$s, $count=100) {
  1817. $out = &$ooo[$s["in"]][0];
  1818. if (!is_array($s) || !is_array($s["close"])) {
  1819. die("\$s is garbaged == $s!!");
  1820. }
  1821. while (($count--) && ($add = array_pop($s["close"]))) {
  1822. $out .= $add . "\n";
  1823. }
  1824. }
  1825. function ewiki_format_pre(&$str, &$in, &$iii, &$s, $btype) {
  1826. $str = "<pre class=\"markup $btype\">" . $str . "</pre>";
  1827. }
  1828. function ewiki_format_html(&$str, &$in, &$iii, &$s) {
  1829. $he = array_reverse($GLOBALS["ewiki_config"]["htmlentities"]);
  1830. $str = strtr($str, array_flip($he));
  1831. $str = "<span class=\"markup html\">" . $str . "\n</span>\n";
  1832. }
  1833. function ewiki_format_comment(&$str, &$in, &$iii, &$s, $btype) {
  1834. $str = "<!-- " . str_replace("--", "¯¯", $str) . " -->";
  1835. }
  1836. /* unclean pre-scanning for WikiWords in a page,
  1837. pre-query to the db */
  1838. function ewiki_scan_wikiwords(&$wiki_source, &$ewiki_links, $se=0) {
  1839. global $ewiki_config;
  1840. #-- find matches
  1841. preg_match_all($ewiki_config["wiki_pre_scan_regex"], $wiki_source, $uu);
  1842. $uu = @array_merge($uu[1], $uu[2], $uu[3], $uu[4], (array)@$uu[5]);
  1843. #-- clean up list, trim() spaces (allows more unclean regex) - page id unification
  1844. foreach ($uu as $i=>$id) {
  1845. $uu[$i] = trim($id);
  1846. }
  1847. unset($uu[""]);
  1848. $uu = array_unique($uu);
  1849. #-- query db
  1850. $ewiki_links = ewiki_database("FIND", $uu);
  1851. #-- strip email adresses
  1852. if ($se) {
  1853. foreach ($ewiki_links as $c=>$uu) {
  1854. if (strpos($c, "@") && (strpos($c, ".") || strpos($c, ":"))) {
  1855. unset($ewiki_links[$c]);
  1856. }
  1857. }
  1858. }
  1859. }
  1860. /* regex on page content,
  1861. handled by callback (see below)
  1862. */
  1863. function ewiki_render_wiki_links(&$o) {
  1864. global $ewiki_links, $ewiki_config, $ewiki_plugins;
  1865. #-- merge with dynamic pages list
  1866. ewiki_merge_links($ewiki_links);
  1867. #-- replace WikiWords
  1868. $link_regex = &$ewiki_config["wiki_link_regex"];
  1869. $o = preg_replace_callback($link_regex, "ewiki_link_regex_callback", $o);
  1870. #-- cleanup
  1871. unset($ewiki_links);
  1872. }
  1873. /*
  1874. combines with page plugin list,
  1875. and makes all case-insensitive
  1876. */
  1877. function ewiki_merge_links(&$ewiki_links) {
  1878. global $ewiki_plugins;
  1879. #### BEGIN MOODLE CHANGES
  1880. global $ewiki_link_case;
  1881. $ewiki_link_case=array();
  1882. #### END MOODLE CHANGES
  1883. if ($ewiki_links !== true) {
  1884. foreach ($ewiki_plugins["page"] as $page=>$uu) {
  1885. $ewiki_links[$page] = 1;
  1886. }
  1887. #### BEGIN MOODLE CHANGES
  1888. foreach($ewiki_links as $page => $uu) {
  1889. if($uu) {
  1890. $ewiki_link_case[strtolower($page)]=$page;
  1891. }
  1892. }
  1893. #### END MOODLE CHANGES
  1894. $ewiki_links = ewiki_array($ewiki_links);
  1895. }
  1896. }
  1897. /* link rendering (p)regex callback
  1898. (ooutch, this is a complicated one)
  1899. */
  1900. function ewiki_link_regex_callback($uu, $force_noimg=0) {
  1901. #print "<pre>"; print_r($uu); print "</pre>";
  1902. global $ewiki_links, $ewiki_plugins, $ewiki_config, $ewiki_id;
  1903. $str = trim($uu[0]);
  1904. $type = array();
  1905. $states = array();
  1906. #-- link bracket '[' escaped with '!' or '~'
  1907. if (($str[0] == "!") || ($str[0] == "~")) {
  1908. return(substr($str, 1));
  1909. }
  1910. if ($str[0] == "#") {
  1911. $states["define"] = 1;
  1912. $str = substr($str, 1);
  1913. }
  1914. if ($str[0] == "[") {
  1915. $states["brackets"] = 1;
  1916. $str = substr($str, 1, -1);
  1917. }
  1918. #-- explicit title given via [ title | WikiLink ]
  1919. $href = $title = strtok($str, "|");
  1920. if ($uu = strtok("|")) {
  1921. $href = $uu;
  1922. $states["titled"] = 1;
  1923. }
  1924. #-- title and href swapped: swap back
  1925. if (strpos("://", $title) || strpos($title, ":") && !strpos($href, ":")) {
  1926. $uu = $title; $title = $href; $href = $uu;
  1927. }
  1928. #-- new entitling scheme [ url "title" ]
  1929. if ((($l=strpos($str, '"')) < ($r=strrpos($str, '"'))) && ($l!==false) ) {
  1930. $title = substr($str, $l + 1, $r - $l - 1);
  1931. $href = substr($str, 0, $l) . substr($str, $r + 1);
  1932. $states["titled"] = 1;
  1933. }
  1934. #-- strip spaces
  1935. $spaces_l = ($href[0]==" ") ?1:0;
  1936. $spaces_r = ($href[strlen($href)-1]==" ") ?1:0;
  1937. $title = ltrim(trim($title), "^");
  1938. $href = ltrim(trim($href), "^");
  1939. #-- strip_htmlentities()
  1940. if (1&& (strpos($href, "&")!==false) && strpos($href, ";")) {
  1941. foreach (array("&lt;"=>"<", "&gt;"=>">", "&amp;"=>"&") as $f=>$t) {
  1942. $href = str_replace($f, $t, $href);
  1943. }
  1944. }
  1945. #-- anchors
  1946. $href2 = "";
  1947. if (($p = strrpos($href, "#")) && ($p) && ($href[$p-1] != "&")) {
  1948. $href2 = trim(substr($href, $p));
  1949. $href = trim(substr($href, 0, $p));
  1950. }
  1951. elseif ($p === 0) {
  1952. $states["define"] = 1;
  1953. }
  1954. if ($href == ".") {
  1955. $href = $ewiki_id;
  1956. }
  1957. #-- for case-insensitivines
  1958. $href_i = EWIKI_CASE_INSENSITIVE ? strtolower($href) : ($href);
  1959. #-- injected URLs
  1960. if (strpos($inj_url = $ewiki_links[$href_i], "://")) {
  1961. if ($href==$title) { $href = $inj_url; }
  1962. }
  1963. #-- interwiki links
  1964. if (strpos($href, ":") && ($uu = ewiki_interwiki($href, $type))) {
  1965. $href = $uu;
  1966. $str = "<a href=\"$href$href2\">$title</a>";
  1967. }
  1968. #-- action:WikiLinks
  1969. elseif ($ewiki_plugins["action"][$a=strtolower(strtok($href, ":"))]) {
  1970. $type = array($a, "action", "wikipage");
  1971. $str = '<a href="' . ewiki_script($a, strtok("\000")) . '">' . $title . '</a>';
  1972. }
  1973. #-- page anchor definitions, if ($href[0]=="#")
  1974. elseif (@$states["define"]) {
  1975. $type = array("anchor");
  1976. if ($title==$href) { $title="&nbsp;"; }
  1977. $str = '<a name="' . s(ltrim($href, "#")) . '">' . ltrim($title, "#") . '</a>';
  1978. }
  1979. #-- inner page anchor jumps
  1980. elseif (strlen($href2) && ($href==$ewiki_id) || ($href[0]=="#") && ($href2=&$href)) {
  1981. $type = array("jump");
  1982. $str = '<a href="' . s($href2) . '">' . $title . '</a>';
  1983. }
  1984. #-- ordinary internal WikiLinks
  1985. elseif (($ewiki_links === true) || @$ewiki_links[$href_i]) {
  1986. $type = array("wikipage");
  1987. #### BEGIN MOODLE CHANGES
  1988. global $ewiki_link_case;
  1989. $href_realcase=array_key_exists($href_i,$ewiki_link_case) ? $ewiki_link_case[$href_i] : $href;
  1990. $str = '<a href="' . ewiki_script("", $href_realcase) . s($href2)
  1991. . '">' . $title . '</a>';
  1992. #### END MOODLE CHANGES
  1993. }
  1994. #-- guess for mail@addresses, convert to URI if
  1995. elseif (strpos($href, "@") && !strpos($href, ":")) {
  1996. $type = array("email");
  1997. $href = "mailto:" . $href;
  1998. }
  1999. #-- not found fallback
  2000. else {
  2001. $str = "";
  2002. #-- a plugin may take care
  2003. if ($pf_a = $ewiki_plugins["link_notfound"]) {
  2004. foreach ($pf_a as $pf) {
  2005. if ($str = $pf($title, $href, $href2, $type)) {
  2006. break;
  2007. } }
  2008. }
  2009. #-- (QuestionMarkLink to edit/ action)
  2010. if (!$str) {
  2011. $type = array("notfound");
  2012. $str = '<span class="NotFound"><b>' . $title . '</b><a href="' .
  2013. ewiki_script("", $href) . '">?</a></span>';
  2014. }
  2015. }
  2016. #-- convert standard URLs
  2017. foreach ($ewiki_config["idf"]["url"] as $find)
  2018. if (strpos($href, $find)===0) {
  2019. $type[-2] = "url";
  2020. $type[-1] = strtok($find, ":");
  2021. #-- URL plugins
  2022. if ($pf_a = $ewiki_plugins["link_url"]) foreach ($pf_a as $pf) {
  2023. if ($str = $pf($href, $title)) { break 2; }
  2024. }
  2025. $meta = @$ewiki_links[$href];
  2026. #-- check for image files
  2027. $ext = substr($href, strrpos($href,"."));
  2028. $nocache = strpos($ext, "no");
  2029. $ext = strtok($ext, "?&#");
  2030. $obj = in_array($ext, $ewiki_config["idf"]["obj"]);
  2031. $img = $obj || in_array($ext, $ewiki_config["idf"]["img"]);
  2032. #-- internal:// references (binary files)
  2033. if (EWIKI_SCRIPT_BINARY && ((strpos($href, EWIKI_IDF_INTERNAL)===0) ||
  2034. EWIKI_IMAGE_MAXSIZE && EWIKI_CACHE_IMAGES && $img && !$nocache) )
  2035. {
  2036. $type = array("binary");
  2037. $href = ewiki_script_binary("", $href);
  2038. }
  2039. #-- output html reference
  2040. if (!$img || $force_noimg || !$states["brackets"] || (strpos($href, EWIKI_IDF_INTERNAL) === 0)) {
  2041. $str = '<a href="' . $href . '">' . $title . '</a>';
  2042. }
  2043. #-- img tag
  2044. else {
  2045. if (is_string($meta)) {
  2046. $meta = unserialize($meta);
  2047. }
  2048. $type = array("image");
  2049. #-- uploaded images size
  2050. $x = $meta["width"];
  2051. $y = $meta["height"];
  2052. if ($p = strpos('?', $href)) { #-- width/height given in url
  2053. parse_str(str_replace("&amp;", "&", substr($href, $p)), $meta);
  2054. ($uu = $meta["x"] . $meta["width"]) and ($x = $uu);
  2055. ($uu = $meta["y"] . $meta["height"]) and ($y = $uu);
  2056. if ($scale = $meta["r"] . $meta["scale"]) {
  2057. ($p = strpos($scale, "%")) and ($scale = strpos($scale, 0, $p) / 100);
  2058. $x *= $scale; $y *= $scale;
  2059. }
  2060. }
  2061. $align = array('', ' align="right"', ' align="left"', ' align="center"');
  2062. $align = $align[$spaces_l + 2*$spaces_r];
  2063. $str = ($obj ? '<embed width="70%"' : '<img') . ' src="' . $href . '"' .
  2064. ' alt="' . ($title) . '"' .
  2065. (@$states["titled"] ? ' title="' . ($title) . '"' : '').
  2066. ($x && $y ? " width=\"$x\" height=\"$y\"" : "") .
  2067. $align . " />" . ($obj ? "</embed>" : "");
  2068. # htmlentities($title)
  2069. }
  2070. break;
  2071. }
  2072. #-- icon/transform plugins
  2073. ksort($type);
  2074. if ($pf_a = @$ewiki_plugins["link_final"]) {
  2075. foreach ($pf_a as $pf) { $pf($str, $type, $href, $title); }
  2076. }
  2077. return($str);
  2078. }
  2079. /*
  2080. Returns URL if it encounters an InterWiki:Link or workalike.
  2081. */
  2082. function ewiki_interwiki($href, &$type) {
  2083. global $ewiki_config, $ewiki_plugins;
  2084. if (strpos($href, ":") and !strpos($href, "//")
  2085. and ($p1 = strtok($href, ":"))) {
  2086. $page = strtok("\000");
  2087. if (($p1 = ewiki_array($ewiki_config["interwiki"], $p1)) !== NULL) {
  2088. $type = array("interwiki", $uu);
  2089. while ($p1_alias = $ewiki_config["interwiki"][$p1]) {
  2090. $type[] = $p1;
  2091. $p1 = $p1_alias;
  2092. }
  2093. if (!strpos($p1, "%s")) {
  2094. $p1 .= "%s";
  2095. }
  2096. $href = str_replace("%s", $page, $p1);
  2097. return($href);
  2098. }
  2099. elseif ($pf = $ewiki_plugins["intermap"][$p1]) {
  2100. return($pf($p1, $page));
  2101. }
  2102. }
  2103. }
  2104. /*
  2105. implements FeatureWiki:InterMapWalking
  2106. */
  2107. function ewiki_intermap_walking($id, &$data, $action) {
  2108. if (empty($data["version"]) && ($href = ewiki_interwiki($id, $uu))) {
  2109. header("Location: $href");
  2110. return("<a href=\"$href\">$href</a>");
  2111. }
  2112. }
  2113. # =========================================================================
  2114. ##### ## ## ## ## ##### ## ##
  2115. ###### ## ### ## #### ###### ## ##
  2116. ## ## ## ### ## ###### ## ## ## ##
  2117. ##### ## #### ## ## ## ###### ######
  2118. ##### ## ####### ###### #### ####
  2119. ## ### ## ## #### ###### ##### ##
  2120. ## ### ## ## ### ## ## ## ### ##
  2121. ###### ## ## ### ## ## ## ## ##
  2122. ###### ## ## ## ## ## ## ## ##
  2123. /* fetch & store
  2124. */
  2125. function ewiki_binary($break=0) {
  2126. global $ewiki_plugins;
  2127. global $USER; // MOODLE
  2128. #-- reject calls
  2129. if (!strlen($id = @$_REQUEST[EWIKI_UP_BINARY]) || !EWIKI_IDF_INTERNAL) {
  2130. return(false);
  2131. }
  2132. if (headers_sent()) die("ewiki-binary configuration error");
  2133. #-- upload requests
  2134. $upload_file = @$_FILES[EWIKI_UP_UPLOAD];
  2135. $add_meta = array();
  2136. if ($orig_name = @$upload_file["name"]) {
  2137. $add_meta["Content-Location"] = urlencode($orig_name);
  2138. $add_meta["Content-Disposition"] = 'inline; filename="'.urlencode(basename("remote://$orig_name")).'"';
  2139. }
  2140. #-- what are we doing here?
  2141. if (($id == EWIKI_IDF_INTERNAL) && ($upload_file)) {
  2142. $do = "upload";
  2143. }
  2144. else {
  2145. $data = ewiki_database("GET", array("id" => $id));
  2146. $flags = @$data["flags"];
  2147. if (EWIKI_DB_F_BINARY == ($flags & EWIKI_DB_F_TYPE)) {
  2148. $do = "get";
  2149. }
  2150. elseif (empty($data["version"]) and EWIKI_CACHE_IMAGES) {
  2151. $do = "cache";
  2152. }
  2153. else {
  2154. $do = "nop";
  2155. }
  2156. }
  2157. #-- auth only happens when enforced with _PROTECTED_MODE_XXL setting
  2158. # (authentication for inline images in violation of the WWW spirit)
  2159. if ((EWIKI_PROTECTED_MODE>=5) && !ewiki_auth($id, $data, "binary-{$do}")) {
  2160. return($_REQUEST["id"]="view/BinaryPermissionError");
  2161. }
  2162. #-- upload an image
  2163. if ($do == "upload"){
  2164. $id = ewiki_binary_save_image($upload_file["tmp_name"], "", $return=0, $add_meta);
  2165. @unlink($upload_file["tmp_name"]);
  2166. ($title = trim($orig_name, "/")) && ($title = preg_replace("/[^-._\w\d]+/", "_", substr(substr($orig_name, strrpos($title, "/")), 0, 20)))
  2167. && ($title = '"'.$title.'"') || ($title="");
  2168. if ($id) {
  2169. echo<<<EOF
  2170. <html><head><title>File/Picture Upload</title><script type="text/javascript"><!--
  2171. opener.document.forms["ewiki"].elements["content"].value += "\\nUPLOADED PICTURE: [$id$title]\\n";
  2172. window.setTimeout("self.close()", 5000);
  2173. //--></script></head><body bgcolor="#440707" text="#FFFFFF">Your uploaded file was saved as<br /><big><b>
  2174. [$id]
  2175. </b></big>.<br /><br /><noscript>Please copy this &uarr; into the text input box:<br />select/mark it with your mouse, press [Ctrl]+[Insert], go back<br />to the previous screen and paste it into the textbox by pressing<br />[Shift]+[Insert] inside there.</noscript></body></html>
  2176. EOF;
  2177. }
  2178. }
  2179. #-- request for contents from the db
  2180. elseif ($do == "get") {
  2181. #### CHANGED FOR MOODLE
  2182. if (EWIKI_HIT_COUNTING) {
  2183. $tmp["id"]=$id;
  2184. ewiki_database("HIT", $tmp);
  2185. }
  2186. #### CHANGED FOR MOODLE
  2187. #-- send http_headers from meta
  2188. if (is_array($data["meta"])) {
  2189. foreach ($data["meta"] as $hdr=>$val) {
  2190. if (($hdr[0] >= "A") && ($hdr[0] <= "Z")) {
  2191. header("$hdr: $val");
  2192. }
  2193. }
  2194. }
  2195. #-- fetch from binary store
  2196. if ($pf_a = $ewiki_plugins["binary_get"]) {
  2197. #### CHANGED FOR MOODLE
  2198. foreach ($pf_a as $pf) { $pf($id, $data["meta"]); }
  2199. #### END CHANGED FOR MOODLE
  2200. }
  2201. #-- else fpassthru
  2202. echo $data["content"];
  2203. }
  2204. #-- fetch & cache requested URL,
  2205. elseif ($do == "cache") {
  2206. #-- check for standard protocol names, to prevent us from serving
  2207. # evil requests for '/etc/passwd.jpeg' or '../.htaccess.gif'
  2208. if (preg_match('@^\w?(http|ftp|https|ftps|sftp)\w?://@', $id)) {
  2209. #-- generate local copy
  2210. $filename = tempnam(EWIKI_TMP, "ewiki.local.temp.");
  2211. if (($i = fopen($id, "rb")) && ($o = fopen($filename, "wb"))) {
  2212. while (!feof($i)) {
  2213. fwrite($o, fread($i, 65536));
  2214. }
  2215. fclose($i);
  2216. fclose($o);
  2217. $add_meta = array(
  2218. "Content-Location" => urlencode($id),
  2219. "Content-Disposition" => 'inline; filename="'.urlencode(basename($id)).'"'
  2220. );
  2221. $result = ewiki_binary_save_image($filename, $id, "RETURN", $add_meta);
  2222. }
  2223. }
  2224. #-- deliver
  2225. if ($result && !$break) {
  2226. ewiki_binary($break=1);
  2227. }
  2228. #-- mark URL as unavailable
  2229. else {
  2230. $data = array(
  2231. "id" => $id,
  2232. "version" => 1,
  2233. "flags" => EWIKI_DB_F_DISABLED,
  2234. "lastmodified" => time(),
  2235. "created" => time(),
  2236. "author" => ewiki_author("ewiki_binary_cache"),
  2237. "userid" => $USER->id,
  2238. "content" => "",
  2239. "meta" => array("Status"=>"404 Absent"),
  2240. );
  2241. ewiki_database("WRITE", $data);
  2242. header("Location: $id");
  2243. ewiki_log("imgcache: did not find '$id', and marked it now in database as DISABLED", 2);
  2244. }
  2245. }
  2246. #-- "we don't sell this!"
  2247. else {
  2248. if (strpos($id, EWIKI_IDF_INTERNAL) === false) {
  2249. header("Status: 301 Located SomeWhere Else");
  2250. header("Location: $id");
  2251. }
  2252. else {
  2253. header("Status: 404 Absent");
  2254. header("X-Broken-URI: $id");
  2255. }
  2256. }
  2257. // you should not remove this one, it is really a good idea to use it!
  2258. die();
  2259. }
  2260. function ewiki_binary_save_image($filename, $id="", $return=0,
  2261. $add_meta=array(), $accept_all=EWIKI_ACCEPT_BINARY, $care_for_images=1)
  2262. {
  2263. global $ewiki_plugins;
  2264. global $USER; // MOODLE
  2265. #-- break on empty files
  2266. if (!filesize($filename)) {
  2267. return(false);
  2268. }
  2269. #-- check for image type and size
  2270. $mime_types = array(
  2271. "application/octet-stream",
  2272. "image/gif",
  2273. "image/jpeg",
  2274. "image/png",
  2275. "application/x-shockwave-flash"
  2276. );
  2277. $ext_types = array(
  2278. "bin", "gif", "jpeg", "png", "swf"
  2279. );
  2280. list($width, $height, $mime_i, $uu) = getimagesize($filename);
  2281. (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
  2282. #-- images expected
  2283. if ($care_for_images) {
  2284. #-- mime type
  2285. if (!$mime_i && !$accept_all || !filesize($filename)) {
  2286. ewiki_die(ewiki_t("BIN_NOIMG"), $return);
  2287. return;
  2288. }
  2289. #-- resize image
  2290. if (strpos($mime,"image/")!==false) {
  2291. if ($pf_a = $ewiki_plugins["image_resize"]) {
  2292. foreach ($pf_a as $pf) {
  2293. if (EWIKI_IMAGE_RESIZE && (filesize($filename) > EWIKI_IMAGE_MAXSIZE)) {
  2294. $pf($filename, $mime, $return);
  2295. clearstatcache();
  2296. }}}}
  2297. #-- reject image if too large
  2298. if (strlen($content) > EWIKI_IMAGE_MAXSIZE) {
  2299. ewiki_die(ewiki_t("BIN_IMGTOOLARGE"), $return);
  2300. return;
  2301. }
  2302. #-- again check mime type and image sizes
  2303. list($width, $height, $mime_i, $uu) = getimagesize($filename);
  2304. (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
  2305. }
  2306. ($ext = $ext_types[$mime_i]) or ($ext = $ext_types[0]);
  2307. #-- binary files
  2308. if ((!$mime_i) && ($pf = $ewiki_plugins["mime_magic"][0])) {
  2309. if ($tmp = $pf($content)) {
  2310. $mime = $tmp;
  2311. }
  2312. }
  2313. if (!strlen($mime)) {
  2314. $mime = $mime_types[0];
  2315. }
  2316. #-- store size of binary file
  2317. $add_meta["size"] = filesize($filename);
  2318. $content = "";
  2319. #-- handler for (large/) binary content?
  2320. if ($pf_a = $ewiki_plugins["binary_store"]) {
  2321. foreach ($pf_a as $pf) {
  2322. $pf($filename, $id, $add_meta, $ext);
  2323. }
  2324. }
  2325. #-- read file into memory (2MB), to store it into the database
  2326. if ($filename) {
  2327. $f = fopen($filename, "rb");
  2328. $content = fread($f, 1<<21);
  2329. fclose($f);
  2330. }
  2331. #-- generate db file name
  2332. if (empty($id)) {
  2333. $md5sum = md5($content);
  2334. $id = EWIKI_IDF_INTERNAL . $md5sum . ".$ext";
  2335. ewiki_log("generated md5sum '$md5sum' from file content");
  2336. }
  2337. #-- prepare meta data
  2338. $meta = @array_merge(array(
  2339. "class" => $mime_i ? "image" : "file",
  2340. "Content-Type" => $mime,
  2341. "Pragma" => "cache",
  2342. ), $add_meta);
  2343. if ($mime_i) {
  2344. $meta["width"] = $width;
  2345. $meta["height"] = $height;
  2346. }
  2347. #-- database entry
  2348. $data = array(
  2349. "id" => $id,
  2350. "version" => "1",
  2351. "author" => ewiki_author(),
  2352. "userid" => $USER->id,
  2353. "flags" => EWIKI_DB_F_BINARY | EWIKI_DB_F_READONLY,
  2354. "created" => time(),
  2355. "lastmodified" => time(),
  2356. "meta" => &$meta,
  2357. "content" => &$content,
  2358. );
  2359. #-- write if not exist
  2360. $exists = ewiki_database("FIND", array($id));
  2361. if (! $exists[$id] ) {
  2362. $result = ewiki_database("WRITE", $data);
  2363. ewiki_log("saving of '$id': " . ($result ? "ok" : "error"));
  2364. }
  2365. else {
  2366. ewiki_log("binary_save_image: '$id' was already in the database", 2);
  2367. }
  2368. return($id);
  2369. }
  2370. # =========================================================================
  2371. #### #### #### ######## ########
  2372. ##### ##### #### ########## ##########
  2373. ###### ###### #### #### ### #### ###
  2374. ############# #### ####
  2375. ############# #### ######## ####
  2376. #### ### #### #### ######## ####
  2377. #### # #### #### #### ####
  2378. #### #### #### ### #### #### ###
  2379. #### #### #### ######### ##########
  2380. #### #### #### ####### ########
  2381. /* yes! it is not neccessary to annoy users with country flags, if the
  2382. http already provides means to determine preferred languages!
  2383. */
  2384. function ewiki_localization() {
  2385. global $ewiki_t, $ewiki_plugins;
  2386. $deflangs = ','.@$_ENV["LANGUAGE"] . ','.@$_ENV["LANG"]
  2387. . ",".EWIKI_DEFAULT_LANG . ",en,C";
  2388. foreach (explode(",", @$_SERVER["HTTP_ACCEPT_LANGUAGE"].$deflangs) as $l) {
  2389. $l = strtok($l, ";");
  2390. $l = strtok($l, "-"); $l = strtok($l, "_"); $l = strtok($l, ".");
  2391. $l = trim($l);
  2392. $ewiki_t["languages"][] = strtolower($l);
  2393. }
  2394. }
  2395. /* poor mans gettext, $repl is an array of string replacements to get
  2396. applied to the fetched text chunk,
  2397. "$const" is either an entry from $ewiki_t[] or a larger text block
  2398. containing _{text} replacement braces of the form "_{...}"
  2399. */
  2400. function ewiki_t($const, $repl=array(), $pref_langs=array()) {
  2401. ##### BEGIN MOODLE ADDITION #####
  2402. $replacechars=array("." => "",
  2403. "," => "",
  2404. "!" => "",
  2405. ";" => "",
  2406. ":" => "",
  2407. "'" => "",
  2408. '"' => "",
  2409. "-" => "",
  2410. "_" => "",
  2411. " " => "",
  2412. "+" => "");
  2413. $translation=get_string(strtolower(strtr($const,$replacechars)),"wiki",$repl);
  2414. return $translation;
  2415. ##### END MOODLE ADDITION #####
  2416. /* global $ewiki_t;
  2417. #-- use default language wishes
  2418. if (empty($pref_langs)) {
  2419. $pref_langs = $ewiki_t["languages"];
  2420. }
  2421. #-- large text snippet replaceing
  2422. if (strpos($const, "_{") !== false) {
  2423. while ( (($l=strpos($const,"_{")) || ($l===0)) && ($r=strpos($const,"}",$l)) ) {
  2424. $const = substr($const, 0, $l)
  2425. . ewiki_t(substr($const, $l+2, $r-$l-2))
  2426. . substr($const,$r+1);
  2427. }
  2428. }
  2429. #-- just one string
  2430. else foreach ($pref_langs as $l) {
  2431. if (is_string($r = @$ewiki_t[$l][$const]) || ($r = @$ewiki_t[$l][strtoupper($const)])) {
  2432. foreach ($repl as $key=>$value) {
  2433. if ($key[0] != '$') {
  2434. $key = '$'.$key;
  2435. }
  2436. $r = str_replace($key, $value, $r);
  2437. }
  2438. return($r);
  2439. }
  2440. }
  2441. return($const);*/
  2442. }
  2443. function ewiki_log($msg, $error_type=3) {
  2444. if ((EWIKI_LOGLEVEL >= 0) && ($error_type <= EWIKI_LOGLEVEL)) {
  2445. $msg = time() . " - " .
  2446. getremoteaddr() . ":" . $_SERVER["REMOTE_PORT"] . " - " .
  2447. $_SERVER["REQUEST_METHOD"] . " " . $_SERVER["REQUEST_URI"] . " - " .
  2448. strtr($msg, "\n\r\000\377\t\f", "\r\r\r\r\t\f") . "\n";
  2449. error_log($msg, 3, EWIKI_LOGFILE);
  2450. }
  2451. }
  2452. function ewiki_die($msg, $return=0) {
  2453. ewiki_log($msg, 1);
  2454. if ($return) {
  2455. return($GLOBALS["ewiki_error"] = $msg);
  2456. }
  2457. else {
  2458. die($msg);
  2459. }
  2460. }
  2461. function ewiki_array_hash(&$a) {
  2462. return(count($a) . ":" . implode(":", array_keys(array_slice($a, 0, 3))));
  2463. }
  2464. /* provides an case-insensitive in_array replacement to search a page name
  2465. in a list of others;
  2466. the supplied $array WILL be lowercased afterwards, unless $dn was set
  2467. */
  2468. function ewiki_in_array($value, &$array, $dn=0, $ci=EWIKI_CASE_INSENSITIVE) {
  2469. static $as = array();
  2470. #-- work around pass-by-reference
  2471. if ($dn && $ci) { $dest = array(); }
  2472. else { $dest = &$array; }
  2473. #-- make everything lowercase
  2474. if ($ci) {
  2475. $value = strtolower($value);
  2476. if (empty($as[ewiki_array_hash($array)])) { // prevent working on the
  2477. foreach ($array as $i=>$v) { // same array multiple times
  2478. $dest[$i] = strtolower($v);
  2479. }
  2480. $as[ewiki_array_hash($dest)] = 1;
  2481. }
  2482. }
  2483. #-- search in values
  2484. return(in_array($value, $dest));
  2485. }
  2486. /* case-insensitively retrieves an entry from an $array,
  2487. or returns the given $array lowercased if $key was obmitted
  2488. */
  2489. function ewiki_array($array, $key=false, $am=1, $ci=EWIKI_CASE_INSENSITIVE) {
  2490. #-- make everything lowercase
  2491. if ($ci) {
  2492. $key = strtolower($key);
  2493. $r = array();
  2494. foreach ($array as $i=>$v) {
  2495. $i = strtolower($i);
  2496. if (!$am || empty($r[$i])) {
  2497. $r[$i] = $v;
  2498. }
  2499. else {
  2500. $r[$i] .= $v; //RET: doubling for images`meta won't happen
  2501. } // but should be "+" here for integers
  2502. }
  2503. $array = &$r;
  2504. }
  2505. #-- search in values
  2506. if ($key) {
  2507. return(@$array[$key]);
  2508. }
  2509. else {
  2510. return($array);
  2511. }
  2512. }
  2513. function ewiki_author($defstr="") {
  2514. $author = @$GLOBALS["ewiki_author"];
  2515. ($ip = getremoteaddr()) or ($ip = "127.0.0.0");
  2516. ($port = $_SERVER["REMOTE_PORT"]) or ($port = "null");
  2517. $hostname = $ip;
  2518. $remote = (($ip != $hostname) ? $hostname . " " : "")
  2519. . $ip . ":" . $port;
  2520. (empty($author)) && (
  2521. ($author = $defstr) ||
  2522. ($author = $_SERVER["HTTP_FROM"]) || // RFC2068 sect 14.22
  2523. ($author = $_SERVER["PHP_AUTH_USER"])
  2524. );
  2525. (empty($author))
  2526. && ($author = $remote)
  2527. || ($author = addslashes($author) . " (" . $remote . ")" );
  2528. return($author);
  2529. }
  2530. /* Returns a value of (true) if the currently logged in user (this must
  2531. be handled by one of the plugin backends) is authenticated to do the
  2532. current $action, or to view the current $id page.
  2533. - alternatively just checks current authentication $ring permission level
  2534. - errors are returned via the global $ewiki_errmsg
  2535. */
  2536. function ewiki_auth($id, &$data, $action, $ring=false, $request_auth=0) {
  2537. global $ewiki_plugins, $ewiki_ring, $ewiki_author, $ewiki_errmsg;
  2538. $ok = true;
  2539. $ewiki_errmsg="";
  2540. #echo "_a($id,dat,$action,$ring,$request_auth)<br />\n";
  2541. if (EWIKI_PROTECTED_MODE) {
  2542. #-- set required vars
  2543. if (!isset($ewiki_ring)) {
  2544. $ewiki_ring = (int)EWIKI_AUTH_DEFAULT_RING;
  2545. }
  2546. if ($ring===false) {
  2547. $ring = NULL;
  2548. }
  2549. #-- plugins to call
  2550. $pf_login = @$ewiki_plugins["auth_query"][0];
  2551. $pf_perm = $ewiki_plugins["auth_perm"][0];
  2552. #-- nobody is currently logged in, so try to fetch username,
  2553. # the login <form> is not yet enforced
  2554. if ($pf_login && empty($ewiki_auth_user)) {
  2555. $pf_login($data, 0);
  2556. }
  2557. #-- check permission for current request (page/action/ring)
  2558. if ($pf_perm) {
  2559. #-- via _auth handler
  2560. $ok = $pf_perm($id, $data, $action, $ring, $request_auth);
  2561. #-- if it failed, we really depend on the login <form>,
  2562. # and then recall the _perm plugin
  2563. if ($pf_login && (($request_auth >= 2) || !$ok && $request_auth && (empty($ewiki_auth_user) || EWIKI_AUTO_LOGIN) && empty($ewiki_errmsg))) {
  2564. //@FIXME: complicated if() - strip empty(errmsg) ??
  2565. $pf_login($data, $request_auth);
  2566. $ok = $pf_perm($id, $data, $action, $ring, $request_auth=0);
  2567. }
  2568. }
  2569. else {
  2570. $ok = !isset($ring) || isset($ring) && ($ewiki_ring <= $ring);
  2571. }
  2572. #-- return error string
  2573. if (!$ok && empty($ewiki_errmsg)) {
  2574. $ewiki_errmsg = ewiki_t("FORBIDDEN");
  2575. }
  2576. }
  2577. return($ok);
  2578. }
  2579. /*
  2580. Queries all registered ["auth_userdb"] plugins for the given
  2581. username, and compares password to against "db" value, sets
  2582. $ewiki_ring and returns(true) if valid.
  2583. */
  2584. function ewiki_auth_user($username, $password) {
  2585. global $ewiki_ring, $ewiki_errmsg, $ewiki_auth_user, $ewiki_plugins, $ewiki_author;
  2586. if (empty($username)) {
  2587. return(false);
  2588. }
  2589. if (($password[0] == "$") || (strlen($password) > 12)) {
  2590. ewiki_log("_auth_userdb: password was transmitted in encoded form, or is just too long (login attemp for user '$username')", 2);
  2591. return(false);
  2592. }
  2593. if ($pf_u = $ewiki_plugins["auth_userdb"])
  2594. foreach ($pf_u as $pf) {
  2595. if (function_exists($pf) && ($entry = $pf($username, $password))) {
  2596. #-- get and compare password
  2597. if ($entry = (array) $entry) {
  2598. $enc_pw = $entry[0];
  2599. }
  2600. $success = false
  2601. || ($enc_pw == substr($password, 0, 12))
  2602. || ($enc_pw == md5($password))
  2603. || ($enc_pw == crypt($password, substr($enc_pw, 0, 2)))
  2604. || function_exists("sha1") && ($enc_pw == sha1($password));
  2605. $success &= $enc_pw != "*";
  2606. #-- return if it matches
  2607. if ($success) {
  2608. if (isset($entry[1])) {
  2609. $ewiki_ring = (int)($entry[1]);
  2610. } else {
  2611. $ewiki_ring = 2; //(EWIKI_AUTH_DEFAULT_RING - 1);
  2612. }
  2613. if (empty($ewiki_author)) {
  2614. ($ewiki_author = $entry[2]) or
  2615. ($ewiki_author = $username);
  2616. }
  2617. return($success && ($ewiki_auth_user=$username));
  2618. }
  2619. }
  2620. }
  2621. if ($username || $password) {
  2622. ewiki_log("_auth_userdb: wrong password supplied for user '$username', not verified against any userdb", 3);
  2623. $ewiki_errmsg = "wrong username and/or password";
  2624. # ewiki_auth($uu, $uu, $uu, $uu, 2);
  2625. }
  2626. return(false);
  2627. }
  2628. /* reads all files from "./init-pages/" into the database,
  2629. when ewiki is run for the very first time and the FrontPage
  2630. does not yet exist in the database
  2631. */
  2632. function ewiki_eventually_initialize(&$id, &$data, &$action) {
  2633. global $USER;
  2634. #-- initialize database only if frontpage missing
  2635. if (($id==EWIKI_PAGE_INDEX) && ($action=="edit") && empty($data["version"])) {
  2636. ewiki_database("INIT", array());
  2637. #### BEGIN MOODLE CHANGE
  2638. $path=EWIKI_INIT_PAGES;
  2639. if (!empty($path)) {
  2640. if ($dh = @opendir($path=EWIKI_INIT_PAGES)) {
  2641. while (false !== ($filename = readdir($dh))) {
  2642. #### MOODLE CHANGE TO SOLVE BUG #3830. Original doesn't support dots in names.
  2643. //Orig->if (preg_match('/^(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+\w*)+/', $filename)) {
  2644. if ($filename == clean_filename($filename) && !is_dir($path.'/'.$filename)) {
  2645. #### END OF MOODLE CHANGE TO SOLVE BUG #3830. Original doesn't support dots in names.
  2646. $found = ewiki_database("FIND", array($filename));
  2647. if (! $found[$filename]) {
  2648. $content = implode("", file("$path/$filename"));
  2649. ewiki_scan_wikiwords($content, $ewiki_links, "_STRIP_EMAIL=1");
  2650. $refs = "\n\n" . implode("\n", array_keys($ewiki_links)) . "\n\n";
  2651. $save = array(
  2652. "id" => "$filename",
  2653. "version" => "1",
  2654. "flags" => "1",
  2655. "content" => $content,
  2656. "author" => ewiki_author("ewiki_initialize"),
  2657. "userid" => $USER->id,
  2658. "refs" => $refs,
  2659. "lastmodified" => filemtime("$path/$filename"),
  2660. "created" => filectime("$path/$filename") // (not exact)
  2661. );
  2662. ewiki_database("WRITE", $save);
  2663. }
  2664. }
  2665. }
  2666. closedir($dh);
  2667. }
  2668. else {
  2669. echo "<b>ewiki error</b>: could not read from directory ". realpath($path) ."<br />\n";
  2670. }
  2671. }
  2672. #### END MOODLE CHANGE
  2673. #-- try to view/ that newly inserted page
  2674. if ($data = ewiki_database("GET", array("id"=>$id))) {
  2675. $action = "view";
  2676. }
  2677. }
  2678. }
  2679. #---------------------------------------------------------------------------
  2680. ######## ### ######## ### ######## ### ###### ########
  2681. ######## ### ######## ### ######## ### ###### ########
  2682. ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  2683. ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  2684. ## ## ## ## ## ## ## ## ## ## ## ## ##
  2685. ## ## ## ## ## ## ## ## ## ## ## ## ##
  2686. ## ## ## ## ## ## ## ######## ## ## ###### ######
  2687. ## ## ## ## ## ## ## ######## ## ## ###### ######
  2688. ## ## ######### ## ######### ## ## ######### ## ##
  2689. ## ## ######### ## ######### ## ## ######### ## ##
  2690. ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  2691. ## ## ## ## ## ## ## ## ## ## ## ## ## ##
  2692. ######## ## ## ## ## ## ######## ## ## ###### ########
  2693. ######## ## ## ## ## ## ######## ## ## ###### ########
  2694. /* wrapper
  2695. */
  2696. function ewiki_database($action, $args, $sw1=0, $sw2=0, $pf=false) {
  2697. #-- normalize (fetch bad parameters)
  2698. if (($action=="GET") && !is_array($args) && is_string($args)) {
  2699. $args = array("id" => $args);
  2700. }
  2701. #-- treat special
  2702. switch ($action) {
  2703. case "GETALL":
  2704. $args = array_unique(@array_merge($args, array("flags", "version")));
  2705. $args = array_diff($args, array("id"));
  2706. break;
  2707. case "SEARCH":
  2708. # unset($args["version"]);
  2709. # unset($args["flags"]);
  2710. break;
  2711. default:
  2712. break;
  2713. }
  2714. #-- handle {meta} sub array as needed
  2715. if (is_array(@$args["meta"])) {
  2716. $args["meta"] = serialize($args["meta"]);
  2717. }
  2718. #-- database plugin
  2719. if (($pf) || ($pf = @$GLOBALS["ewiki_plugins"]["database"][0])) {
  2720. $r = $pf($action, $args, $sw1, $sw2);
  2721. }
  2722. else {
  2723. ewiki_log("DB layer: no backend!", 0);
  2724. $r = false;
  2725. }
  2726. #-- database layer generation 2 abstraction
  2727. if (is_array($r) && (($action=="SEARCH") || ($action=="GETALL"))) {
  2728. $z = new ewiki_dbquery_result(array_keys($args));
  2729. foreach ($r as $id=>$row) {
  2730. $z->add($row);
  2731. }
  2732. $r = $z;
  2733. }
  2734. #-- extract {meta} sub array
  2735. if (is_array($r) && !is_array(@$r["meta"]) && strlen(@$r["meta"])) {
  2736. $r["meta"] = unserialize($r["meta"]);
  2737. }
  2738. return($r);
  2739. }
  2740. /* returned for SEARCH and GETALL queries, as those operations are
  2741. otherwise too memory exhaustive
  2742. */
  2743. class ewiki_dbquery_result {
  2744. var $keys = array();
  2745. var $entries = array();
  2746. var $buffer = EWIKI_DBQUERY_BUFFER;
  2747. var $size = 0;
  2748. function ewiki_dbquery_result($keys) {
  2749. $keys = @array_merge($keys, array(-50=>"id", "version", "flags"));
  2750. $this->keys = array_unique($keys);
  2751. }
  2752. function add($row) {
  2753. if (is_array($row)) {
  2754. if ($this->buffer) {
  2755. $this->size += strlen(serialize($row));
  2756. $this->buffer = $this->size <= EWIKI_DBQUERY_BUFFER;
  2757. }
  2758. else {
  2759. $row = $row["id"];
  2760. }
  2761. }
  2762. $this->entries[] = $row;
  2763. }
  2764. function get($all=0, $flags=0x00) {
  2765. $row = array();
  2766. $prot_hide = ($flags&0x0020) && EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING;
  2767. do {
  2768. if (count($this->entries)) {
  2769. #-- fetch very first entry from $entries list
  2770. $r = array_shift($this->entries);
  2771. #-- finish if buffered entry
  2772. if (is_array($r) && !$all) {
  2773. $row = $r;
  2774. }
  2775. #-- else refetch complete entry from database
  2776. else {
  2777. if (is_array($r)) {
  2778. $r = $r["id"];
  2779. }
  2780. $r = ewiki_database("GET", array("id"=>$r));
  2781. if (!$all) {
  2782. foreach ($this->keys as $key) {
  2783. $row[$key] = $r[$key];
  2784. }
  2785. } else {
  2786. $row = $r;
  2787. }
  2788. }
  2789. unset($r);
  2790. }
  2791. else {
  2792. return(NULL); // no more entries
  2793. }
  2794. #-- expand {meta} field
  2795. if (is_array($row) && is_string(@$row["meta"])) {
  2796. $row["meta"] = unserialize($row["meta"]);
  2797. }
  2798. #-- drop unwanted results
  2799. if ($prot_hide && !ewiki_auth($row["id"], $row, $ewiki_action)) {
  2800. $row = array();
  2801. }
  2802. } while ($prot_hide && empty($row));
  2803. return($row);
  2804. }
  2805. function count() {
  2806. return(count($this->entries));
  2807. }
  2808. }
  2809. /* MySQL database backend
  2810. (default)
  2811. Note: this is of course an abuse of the relational database scheme,
  2812. but neccessary for real db independence and abstraction
  2813. */
  2814. function ewiki_database_mysql($action, &$args, $sw1, $sw2) {
  2815. #-- reconnect to the database (if multiple are used)
  2816. #<off># mysql_ping($GLOBALS["db"]);
  2817. #-- result array
  2818. $r = array();
  2819. switch($action) {
  2820. /* Returns database entry as array for the page whose name was given
  2821. with the "id" key in the $args array, usually fetches the latest
  2822. version of a page, unless a specific "version" was requested in
  2823. the $args array.
  2824. */
  2825. case "GET":
  2826. $id = "'" . mysql_escape_string($args["id"]) . "'";
  2827. ($version = 0 + @$args["version"]) and ($version = "AND (version=$version)") or ($version="");
  2828. $result = mysql_query("SELECT * FROM " . EWIKI_DB_TABLE_NAME
  2829. . " WHERE (pagename=$id) $version ORDER BY version DESC LIMIT 1"
  2830. );
  2831. if ($result && ($r = mysql_fetch_array($result, MYSQL_ASSOC))) {
  2832. $r["id"] = $r["pagename"];
  2833. unset($r["pagename"]);
  2834. }
  2835. if (strlen($r["meta"])) {
  2836. $r["meta"] = @unserialize($r["meta"]);
  2837. }
  2838. break;
  2839. /* Increases the hit counter for the page name given in $args array
  2840. with "id" index key.
  2841. */
  2842. case "HIT":
  2843. mysql_query("UPDATE " . EWIKI_DB_TABLE_NAME . " SET hits=(hits+1) WHERE pagename='" . mysql_escape_string($args["id"]) . "'");
  2844. break;
  2845. /* Stores the $data array into the database, while not overwriting
  2846. existing entries (using WRITE); returns 0 on failure and 1 if
  2847. saved correctly.
  2848. */
  2849. case "OVERWRITE": // fall-through
  2850. $COMMAND = "REPLACE";
  2851. case "WRITE":
  2852. $args["pagename"] = $args["id"];
  2853. unset($args["id"]);
  2854. if (is_array($args["meta"])) {
  2855. $args["meta"] = serialize($args["meta"]);
  2856. }
  2857. $sql1 = $sql2 = "";
  2858. foreach ($args as $index => $value) {
  2859. if (is_int($index)) {
  2860. continue;
  2861. }
  2862. $a = ($sql1 ? ', ' : '');
  2863. $sql1 .= $a . $index;
  2864. $sql2 .= $a . "'" . mysql_escape_string($value) . "'";
  2865. }
  2866. strlen(@$COMMAND) || ($COMMAND = "INSERT");
  2867. $result = mysql_query("$COMMAND INTO " . EWIKI_DB_TABLE_NAME .
  2868. " (" . $sql1 . ") VALUES (" . $sql2 . ")"
  2869. );
  2870. return($result && mysql_affected_rows() ?1:0);
  2871. break;
  2872. /* Checks for existence of the WikiPages whose names are given in
  2873. the $args array. Returns an array with the specified WikiPageNames
  2874. associated with values of "0" or "1" (stating if the page exists
  2875. in the database). For images/binary db entries returns the "meta"
  2876. field instead of an "1".
  2877. */
  2878. case "FIND":
  2879. $sql = "";
  2880. foreach (array_values($args) as $id) if (strlen($id)) {
  2881. $r[$id] = 0;
  2882. $sql .= ($sql ? " OR " : "") .
  2883. "(pagename='" . mysql_escape_string($id) . "')";
  2884. }
  2885. $result = mysql_query($sql = "SELECT pagename AS id, meta FROM " .
  2886. EWIKI_DB_TABLE_NAME . " WHERE $sql "
  2887. );
  2888. while ($result && ($row = mysql_fetch_row($result))) {
  2889. $r[$row[0]] = strpos($row[1], 's:5:"image"') ? $row[1] : 1;
  2890. }
  2891. break;
  2892. /* Returns an array of __all__ pages, where each entry is made up
  2893. of the fields from the database requested with the $args array,
  2894. e.g. array("flags","meta","lastmodified");
  2895. */
  2896. case "GETALL":
  2897. $result = mysql_query("SELECT pagename AS id, ".
  2898. implode(", ", $args) .
  2899. " FROM ". EWIKI_DB_TABLE_NAME .
  2900. " GROUP BY id, version DESC"
  2901. );
  2902. $r = new ewiki_dbquery_result($args);
  2903. $drop = "";
  2904. while ($result && ($row = mysql_fetch_array($result, MYSQL_ASSOC))) {
  2905. $i = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
  2906. if ($i != $drop) {
  2907. $drop = $i;
  2908. $r->add($row);
  2909. }
  2910. }
  2911. break;
  2912. /* Returns array of database entries (also arrays), where the one
  2913. specified column matches the specified content string, for example
  2914. $args = array("content" => "text...piece")
  2915. is not guaranteed to only search/return the latest version of a page
  2916. */
  2917. case "SEARCH":
  2918. $field = implode("", array_keys($args));
  2919. $content = strtolower(implode("", $args));
  2920. if ($field == "id") { $field = "pagename"; }
  2921. $result = mysql_query("SELECT pagename AS id, version, flags" .
  2922. (EWIKI_DBQUERY_BUFFER && ($field!="pagename") ? ", $field" : "") .
  2923. " FROM " . EWIKI_DB_TABLE_NAME .
  2924. " WHERE LOCATE('" . mysql_escape_string($content) . "', LCASE($field)) " .
  2925. " GROUP BY id, version DESC"
  2926. );
  2927. $r = new ewiki_dbquery_result(array("id","version",$field));
  2928. $drop = "";
  2929. while ($result && ($row = mysql_fetch_array($result, MYSQL_ASSOC))) {
  2930. $i = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
  2931. if ($i != $drop) {
  2932. $drop = $i;
  2933. $r->add($row);
  2934. }
  2935. }
  2936. break;
  2937. case "DELETE":
  2938. $id = mysql_escape_string($args["id"]);
  2939. $version = $args["version"];
  2940. mysql_query("DELETE FROM " . EWIKI_DB_TABLE_NAME ."
  2941. WHERE pagename='$id' AND version=$version");
  2942. break;
  2943. case "INIT":
  2944. mysql_query("CREATE TABLE " . EWIKI_DB_TABLE_NAME ."
  2945. (pagename VARCHAR(160) NOT NULL,
  2946. version INTEGER UNSIGNED NOT NULL DEFAULT 0,
  2947. flags INTEGER UNSIGNED DEFAULT 0,
  2948. content MEDIUMTEXT,
  2949. author VARCHAR(100) DEFAULT 'ewiki',
  2950. userid INTEGER UNSIGNED DEFAULT 0,
  2951. created INTEGER UNSIGNED DEFAULT ".time().",
  2952. lastmodified INTEGER UNSIGNED DEFAULT 0,
  2953. refs MEDIUMTEXT,
  2954. meta MEDIUMTEXT,
  2955. hits INTEGER UNSIGNED DEFAULT 0,
  2956. PRIMARY KEY id (pagename, version) )
  2957. ");
  2958. echo mysql_error();
  2959. break;
  2960. default:
  2961. }
  2962. return($r);
  2963. }
  2964. ?>