Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / mod / wiki / ewiki / ewiki.php
blob6b38174ae73fac537b1cb5f8e827d86301f1b5d1
1 <?php
2 @define("EWIKI_VERSION", "R1.01d");
4 /*
6 ErfurtWiki - an embedable, fast and user-friendly wiki engine
7 ---------
8 This is Public Domain (no license, no warranty); but feel free
9 to redistribute it under GPL or anything else you like.
11 http://erfurtwiki.sourceforge.net/
12 Mario Salzer <mario*erphesfurt·de> and many others(tm)
15 Use it from inside yoursite.php like that:
16 <html><body>...
17 <?php
18 include("ewiki.php");
19 echo ewiki_page();
24 #-- you could also establish a mysql connection in here, of course:
25 // mysql_connect(":/var/run/mysqld/mysqld.sock", "user", "pw")
26 // and mysql_query("USE mydatabase");
29 #-------------------------------------------------------- config ---
31 #-- I'm sorry for that, but all the @ annoy me
32 error_reporting(0x0000377 & error_reporting());
33 # error_reporting(E_ALL^E_NOTICE);
35 #-- the position of your ewiki-wrapper script
36 define("EWIKI_SCRIPT", "?id="); # relative/absolute to docroot
37 # define("EWIKI_SCRIPT_URL", "http://...?id="); # absolute URL
39 #-- change to your needs (site lang)
40 define("EWIKI_NAME", "ErfurtWiki");
41 define("EWIKI_PAGE_INDEX", "ErfurtWiki");
42 define("EWIKI_PAGE_NEWEST", "NewestPages");
43 define("EWIKI_PAGE_SEARCH", "SearchPages");
44 define("EWIKI_PAGE_HITS", "MostVisitedPages");
45 define("EWIKI_PAGE_VERSIONS", "MostOftenChangedPages");
46 define("EWIKI_PAGE_UPDATES", "UpdatedPages");
48 #-- default settings are good settings - most often ;)
49 #- look & feel
50 define("EWIKI_PRINT_TITLE", 1); # <h2>WikiPageName</h2> on top
51 define("EWIKI_SPLIT_TITLE", 0); # <h2>Wiki Page Name</h2>
52 define("EWIKI_CONTROL_LINE", 1); # EditThisPage-link at bottom
53 define("EWIKI_LIST_LIMIT", 20); # listing limit
54 #- behaviour
55 define("EWIKI_AUTO_EDIT", 1); # edit box for non-existent pages
56 define("EWIKI_EDIT_REDIRECT", 1); # redirect after edit save
57 define("EWIKI_DEFAULT_ACTION", "view"); # (keep!)
58 define("EWIKI_CASE_INSENSITIVE", 1); # wikilink case sensitivity
59 define("EWIKI_HIT_COUNTING", 1);
60 define("UNIX_MILLENNIUM", 1000000000);
61 #- rendering
62 define("EWIKI_ALLOW_HTML", 0); # often a very bad idea
63 define("EWIKI_HTML_CHARS", 1); # allows for &#200;
64 define("EWIKI_ESCAPE_AT", 1); # "@" -> "&#x40;"
65 #- http/urls
66 define("EWIKI_HTTP_HEADERS", 1); # most often a good thing
67 define("EWIKI_NO_CACHE", 1); # browser+proxy shall not cache
68 define("EWIKI_URLENCODE", 1); # disable when _USE_PATH_INFO
69 define("EWIKI_URLDECODE", 1);
70 define("EWIKI_USE_PATH_INFO", 1 &&!strstr($_SERVER["SERVER_SOFTWARE"],"Apache"));
71 define("EWIKI_USE_ACTION_PARAM", 1);
72 define("EWIKI_ACTION_SEP_CHAR", "/");
73 define("EWIKI_UP_PAGENUM", "n"); # _UP_ means "url parameter"
74 define("EWIKI_UP_PAGEEND", "e");
75 define("EWIKI_UP_BINARY", "binary");
76 define("EWIKI_UP_UPLOAD", "upload");
77 #- other stuff
78 define("EWIKI_DEFAULT_LANG", "en");
79 define("EWIKI_CHARSET", "UTF-8");
80 #- user permissions
81 define("EWIKI_PROTECTED_MODE", 0); # disable funcs + require auth
82 define("EWIKI_PROTECTED_MODE_HIDING", 0); # hides disallowed actions
83 define("EWIKI_AUTH_DEFAULT_RING", 3); # 0=root 1=priv 2=user 3=view
84 define("EWIKI_AUTO_LOGIN", 1); # [auth_query] on startup
86 #-- allowed WikiPageNameCharacters
88 #### BEGIN MOODLE CHANGES - to remove auto-camelcase linking.
89 global $moodle_disable_camel_case;
90 if ($moodle_disable_camel_case) {
91 define("EWIKI_CHARS_L", "");
92 define("EWIKI_CHARS_U", "");
94 else {
95 #### END MOODLE CHANGES
97 define("EWIKI_CHARS_L", "a-z_µ¤$\337-\377");
98 define("EWIKI_CHARS_U", "A-Z0-9\300-\336");
100 #### BEGIN MOODLE CHANGES
102 #### END MOODLE CHANGES
104 define("EWIKI_CHARS", EWIKI_CHARS_L.EWIKI_CHARS_U);
106 #-- database
107 define("EWIKI_DB_TABLE_NAME", "ewiki"); # MySQL / ADOdb
108 define("EWIKI_DBFILES_DIRECTORY", "/tmp"); # see "db_flat_files.php"
109 define("EWIKI_DBA", "/tmp/ewiki.dba"); # see "db_dba.php"
110 define("EWIKI_DBQUERY_BUFFER", 512*1024); # 512K
111 define("EWIKI_INIT_PAGES", "./init-pages"); # for initialization
113 define("EWIKI_DB_F_TEXT", 1<<0);
114 define("EWIKI_DB_F_BINARY", 1<<1);
115 define("EWIKI_DB_F_DISABLED", 1<<2);
116 define("EWIKI_DB_F_HTML", 1<<3);
117 define("EWIKI_DB_F_READONLY", 1<<4);
118 define("EWIKI_DB_F_WRITEABLE", 1<<5);
119 define("EWIKI_DB_F_APPENDONLY", 1<<6); #nyi
120 define("EWIKI_DB_F_SYSTEM", 1<<7);
121 define("EWIKI_DB_F_PART", 1<<8);
122 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);
123 define("EWIKI_DB_F_ACCESS", EWIKI_DB_F_READONLY | EWIKI_DB_F_WRITEABLE | EWIKI_DB_F_APPENDONLY);
124 define("EWIKI_DB_F_COPYMASK", EWIKI_DB_F_TYPE | EWIKI_DB_F_ACCESS);
126 define("EWIKI_DBFILES_NLR", '\\n');
127 define("EWIKI_DBFILES_ENCODE", 0 || (DIRECTORY_SEPARATOR != "/"));
128 define("EWIKI_DBFILES_GZLEVEL", "2");
130 #-- internal
131 define("EWIKI_ADDPARAMDELIM", (strstr(EWIKI_SCRIPT,"?") ? "&" : "?"));
133 #-- binary content (images)
134 define("EWIKI_SCRIPT_BINARY", /*"/binary.php?binary="*/ ltrim(strtok(" ".EWIKI_SCRIPT,"?"))."?".EWIKI_UP_BINARY."=" );
135 define("EWIKI_CACHE_IMAGES", 1 &&!headers_sent());
136 define("EWIKI_IMAGE_MAXSIZE", 64 *1024);
137 define("EWIKI_IMAGE_MAXWIDTH", 3072);
138 define("EWIKI_IMAGE_MAXHEIGHT", 2048);
139 define("EWIKI_IMAGE_MAXALLOC", 1<<19);
140 define("EWIKI_IMAGE_RESIZE", 1);
141 define("EWIKI_IMAGE_ACCEPT", "image/jpeg,image/png,image/gif,application/x-shockwave-flash");
142 define("EWIKI_IDF_INTERNAL", "internal://");
143 define("EWIKI_ACCEPT_BINARY", 0); # for arbitrary binary data files
145 #-- misc
146 define("EWIKI_TMP", $_SERVER["TEMP"] ? $_SERVER["TEMP"] : "/tmp");
147 define("EWIKI_LOGLEVEL", -1); # 0=error 1=warn 2=info 3=debug
148 define("EWIKI_LOGFILE", "/tmp/ewiki.log");
150 #-- plugins (tasks mapped to function names)
151 $ewiki_plugins["database"][] = "ewiki_database_mysql";
152 $ewiki_plugins["edit_preview"][] = "ewiki_page_edit_preview";
153 $ewiki_plugins["render"][] = "ewiki_format";
154 $ewiki_plugins["init"][-5] = "ewiki_localization";
155 $ewiki_plugins["init"][-1] = "ewiki_binary";
156 $ewiki_plugins["handler"][-105] = "ewiki_eventually_initialize";
157 $ewiki_plugins["handler"][] = "ewiki_intermap_walking";
158 $ewiki_plugins["view_append"][-1] = "ewiki_control_links";
159 $ewiki_plugins["view_final"][-1] = "ewiki_add_title";
160 $ewiki_plugins["page_final"][] = "ewiki_http_headers";
161 $ewiki_plugins["page_final"][99115115] = "ewiki_page_css_container";
162 $ewiki_plugins["edit_form_final"][] = "ewiki_page_edit_form_final_imgupload";
163 $ewiki_plugins["format_block"]["pre"][] = "ewiki_format_pre";
164 $ewiki_plugins["format_block"]["code"][] = "ewiki_format_pre";
165 $ewiki_plugins["format_block"]["htm"][] = "ewiki_format_html";
166 $ewiki_plugins["format_block"]["html"][] = "ewiki_format_html";
167 $ewiki_plugins["format_block"]["comment"][] = "ewiki_format_comment";
170 #-- internal pages
171 $ewiki_plugins["page"][EWIKI_PAGE_NEWEST] = "ewiki_page_newest";
172 $ewiki_plugins["page"][EWIKI_PAGE_SEARCH] = "ewiki_page_search";
173 if (EWIKI_HIT_COUNTING) $ewiki_plugins["page"][EWIKI_PAGE_HITS] = "ewiki_page_hits";
174 $ewiki_plugins["page"][EWIKI_PAGE_VERSIONS] = "ewiki_page_versions";
175 $ewiki_plugins["page"][EWIKI_PAGE_UPDATES] = "ewiki_page_updates";
177 #-- page actions
178 $ewiki_plugins["action"]["edit"] = "ewiki_page_edit";
179 $ewiki_plugins["action_always"]["links"] = "ewiki_page_links";
180 $ewiki_plugins["action"]["info"] = "ewiki_page_info";
181 $ewiki_plugins["action"]["view"] = "ewiki_page_view";
183 #-- helper vars ---------------------------------------------------
184 $ewiki_config["idf"]["url"] = array("http://", "mailto:", "internal://", "ftp://", "https://", "irc://", "telnet://", "news://", "chrome://", "file://", "gopher://", "httpz://");
185 $ewiki_config["idf"]["img"] = array(".jpeg", ".png", ".jpg", ".gif", ".j2k");
186 $ewiki_config["idf"]["obj"] = array(".swf", ".svg");
188 #-- entitle actions
189 $ewiki_config["action_links"]["view"] = @array_merge(array(
190 "edit" => "EDITTHISPAGE", # ewiki_t() is called on these
191 "links" => "BACKLINKS",
192 "info" => "PAGEHISTORY",
193 "like" => "LIKEPAGES",
194 ), @$ewiki_config["action_links"]["view"]
196 $ewiki_config["action_links"]["info"] = @array_merge(array(
197 "view" => "browse",
198 "edit" => "fetchback",
199 ), @$ewiki_config["action_links"]["info"]
202 #-- variable configuration settings (go into '$ewiki_config')
203 $ewiki_config_DEFAULTSTMP = array(
204 "edit_thank_you" => 1,
205 "edit_box_size" => "70x15",
206 "print_title" => EWIKI_PRINT_TITLE,
207 "split_title" => EWIKI_SPLIT_TITLE,
208 "control_line" => EWIKI_CONTROL_LINE,
209 "list_limit" => EWIKI_LIST_LIMIT,
210 "script" => EWIKI_SCRIPT,
211 "script_url" => (defined("EWIKI_SCRIPT_URL")?EWIKI_SCRIPT_URL:NULL),
212 "script_binary" => EWIKI_SCRIPT_BINARY,
213 #-- heart of the wiki -- don't try to read this! ;)
215 "wiki_pre_scan_regex" => '/
216 (?<![~!])
217 ((?:(?:\w+:)*['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2,}[\w\d]*)
218 |\^([-'.EWIKI_CHARS_L.EWIKI_CHARS_U.']{3,})
219 |\[ (?:"[^\]\"]+" | \s+ | [^:\]#]+\|)* ([^\|\"\[\]\#]+) (?:\s+ | "[^\]\"]+")* [\]\#]
220 |(\w{3,9}:\/\/[^?#\s\[\]\'\"\)\,<]+) /x',
222 "wiki_link_regex" => "\007 [!~]?(
223 \#?\[[^<>\[\]\n]+\] |
224 \^[-".EWIKI_CHARS_U.EWIKI_CHARS_L."]{3,} |
225 \b([\w]{3,}:)*([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}\#?[\w\d]* |
226 ([a-z]{2,9}://|mailto:)[^\s\[\]\'\"\)\,<]+ |
227 \w[-_.+\w]+@(\w[-_\w]+[.])+\w{2,} ) \007x",
229 #-- rendering ruleset
230 "wm_indent" => '',
231 "wm_table_defaults" => 'cellpadding="2" border="1" cellspacing="0"',
232 "wm_whole_line" => array(),
233 "htmlentities" => array(
234 "&" => "&amp;",
235 ">" => "&gt;",
236 "<" => "&lt;",
238 "wm_source" => array(
239 "%%%" => "<br />",
240 "\t" => " ",
241 "\n;:" => "\n ", # workaround, replaces the old ;:
243 "wm_list" => array(
244 "-" => array('ul type="square"', "", "li"),
245 "*" => array('ul type="circle"', "", "li"),
246 "#" => array("ol", "", "li"),
247 ":" => array("dl", "dt", "dd"),
248 #<out># ";" => array("dl", "dt", "dd"),
250 "wm_style" => array(
251 "'''''" => array("<b><i>", "</i></b>"),
252 "'''" => array("<b>", "</b>"),
253 "___" => array("<i><b>", "</b></i>"),
254 "''" => array("<em>", "</em>"),
255 "__" => array("<strong>", "</strong>"),
256 "^^" => array("<sup>", "</sup>"),
257 "==" => array("<tt>", "</tt>"),
258 #<off># "***" => array("<b><i>", "</i></b>"),
259 #<off># "###" => array("<big><b>", "</b></big>"),
260 "**" => array("<b>", "</b>"),
261 "##" => array("<big>", "</big>"),
262 "µµ" => array("<small>", "</small>"),
264 "wm_start_end" => array(
266 #-- rendering plugins
267 "format_block" => array(
268 "html" => array("&lt;html&gt;", "&lt;/html&gt;", "html", 0x0000),
269 "htm" => array("&lt;htm&gt;", "&lt;/htm&gt;", "html", 0x0003),
270 "code" => array("&lt;code&gt;", "&lt;/code&gt;", false, 0x0000),
271 "pre" => array("&lt;pre&gt;", "&lt;/pre&gt;", false, 0x003F),
272 "comment" => array("\n&lt;!--", "--&gt;", false, 0x0030),
273 # "verbatim" => array("&lt;verbatim&gt;", "&lt;/verbatim&gt;", false, 0x0000),
275 "format_params" => array(
276 "scan_links" => 1,
277 "html" => EWIKI_ALLOW_HTML,
278 "mpi" => 1,
281 foreach ($ewiki_config_DEFAULTSTMP as $set => $val) {
282 if (!isset($ewiki_config[$set])) {
283 $ewiki_config[$set] = $val;
285 elseif (is_array($val)) foreach ($val as $vali=>$valv) {
286 if (is_int($vali)) {
287 $ewiki_config[$set][] = $valv;
289 elseif (!isset($ewiki_config[$set][$vali])) {
290 $ewiki_config[$set][$vali] = $valv;
294 $ewiki_config_DEFAULTSTMP = $valv = $vali = $val = NULL;
296 #-- init stuff, autostarted parts
297 ksort($ewiki_plugins["init"]);
298 if ($pf_a = $ewiki_plugins["init"]) foreach ($pf_a as $pf) {
299 // Binary Handling starts here
300 #### MOODLE CHANGE TO BE COMPATIBLE WITH PHP 4.1
301 #if(headers_sent($file,$line)) {
302 # error("Headers already sent: $file:$line");
303 if(headers_sent()) {
304 error("Headers already sent.");
306 $pf($GLOBALS);
308 unset($ewiki_plugins["init"]);
310 #-- text (never remove the "C" or "en" sections!)
312 $ewiki_t["C"] = @array_merge(@$ewiki_t["C"], array(
313 "DATE" => "%a, %d %b %G %T %Z",
314 "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>',
317 $ewiki_t["en"] = @array_merge(@$ewiki_t["en"], array(
318 "EDITTHISPAGE" => "EditThisPage",
319 "APPENDTOPAGE" => "Add to",
320 "BACKLINKS" => "BackLinks",
321 "PAGESLINKINGTO" => "Pages linking to \$title",
322 "PAGEHISTORY" => "PageInfo",
323 "INFOABOUTPAGE" => "Information about page",
324 "LIKEPAGES" => "Pages like this",
325 "NEWESTPAGES" => "Newest Pages",
326 "LASTCHANGED" => "last changed on %c",
327 "DOESNOTEXIST" => "This page does not yet exist, please click on EditThisPage if you'd like to create it.",
328 "DISABLEDPAGE" => "This page is currently not available.",
329 "ERRVERSIONSAVE" => "Sorry, while you edited this page someone else
330 did already save a changed version. Please go back to the
331 previous screen and copy your changes to your computers
332 clipboard to insert it again after you reload the edit
333 screen.",
334 "ERRORSAVING" => "An error occoured while saving your changes. Please try again.",
335 "THANKSFORCONTRIBUTION" => "Thank you for your contribution!",
336 "CANNOTCHANGEPAGE" => "This page cannot be changed.",
337 "OLDVERCOMEBACK" => "Make this old version come back to replace the current one",
338 "PREVIEW" => "Preview",
339 "SAVE" => "Save",
340 "CANCEL_EDIT" => "CancelEditing",
341 "UPLOAD_PICTURE_BUTTON" => "upload picture &gt;&gt;&gt;",
342 "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GoodStyle\">GoodStyle</a> is to
343 write what comes to your mind. Don't care about how it
344 looks too much now. You can add <a href=\"".EWIKI_SCRIPT."WikiMarkup\">WikiMarkup</a>
345 also later if you think it is necessary.<br />",
346 "EDIT_FORM_2" => "<br />Please do not write things, which may make other
347 people angry. And please keep in mind that you are not all that
348 anonymous in the internet (find out more about your computers
349 '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' at Google).",
350 "BIN_IMGTOOLARGE" => "Image file is too large!",
351 "BIN_NOIMG" => "This is no image file (inacceptable file format)!",
352 "FORBIDDEN" => "You are not authorized to access this page.",
355 $ewiki_t["es"] = @array_merge(@$ewiki_t["es"], array(
356 "EDITTHISPAGE" => "EditarEstaPágina",
357 "BACKLINKS" => "EnlacesInversos",
358 "PAGESLINKINGTO" => "Páginas enlazando \$title",
359 "PAGEHISTORY" => "InfoPágina",
360 "INFOABOUTPAGE" => "Información sobre la página",
361 "LIKEPAGES" => "Páginas como esta",
362 "NEWESTPAGES" => "Páginas más nuevas",
363 "LASTCHANGED" => "última modificación %d/%m/%Y a las %H:%M",
364 "DOESNOTEXIST" => "Esta página aún no existe, por favor eliga EditarEstaPágina si desea crearla.",
365 "DISABLEDPAGE" => "Esta página no está disponible en este momento.",
366 "ERRVERSIONSAVE" => "Disculpe, mientras editaba esta página alguién más
367 salvó una versión modificada. Por favor regrese a
368 a la pantalla anterior y copie sus cambios a su computador
369 para insertalos nuevamente después de que cargue
370 la pantalla de edición.",
371 "ERRORSAVING" => "Ocurrió un error mientras se salvavan sus cambios. Por favor intente de nuevo.",
372 "THANKSFORCONTRIBUTION" => "Gracias por su contribución!",
373 "CANNOTCHANGEPAGE" => "Esta página no puede ser modificada.",
374 "OLDVERCOMEBACK" => "Hacer que esta versión antigua regrese a remplazar la actual",
375 "PREVIEW" => "Previsualizar",
376 "SAVE" => "Salvar",
377 "CANCEL_EDIT" => "CancelarEdición",
378 "UPLOAD_PICTURE_BUTTON" => "subir gráfica &gt;&gt;&gt;",
379 "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."BuenEstilo\">BuenEstilo</a> es
380 escribir lo que viene a su mente. No se preocupe mucho
381 por la apariencia. También puede agregar <a href=\"".EWIKI_SCRIPT."ReglasDeMarcadoWiki\">ReglasDeMarcadoWiki</a>
382 más adelante si piensa que es necesario.<br />",
383 "EDIT_FORM_2" => "<br />Por favor no escriba cosas, que puedan
384 enfadar a otras personas. Y por favor tenga en mente que
385 usted no es del todo anónimo en Internet
386 (encuentre más sobre
387 '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' de su computador con Google).",
388 "BIN_IMGTOOLARGE" => "¡La gráfica es demasiado grande!",
389 "BIN_NOIMG" => "¡No es un archivo con una gráfica (formato de archivo inaceptable)!",
390 "FORBIDDEN" => "No está autorizado para acceder a esta página.",
393 $ewiki_t["de"] = @array_merge(@$ewiki_t["de"], array(
394 "EDITTHISPAGE" => "DieseSeiteÄndern",
395 "APPENDTOPAGE" => "Ergänze",
396 "BACKLINKS" => "ZurückLinks",
397 "PAGESLINKINGTO" => "Verweise zur Seite \$title",
398 "PAGEHISTORY" => "SeitenInfo",
399 "INFOABOUTPAGE" => "Informationen über Seite",
400 "LIKEPAGES" => "Ähnliche Seiten",
401 "NEWESTPAGES" => "Neueste Seiten",
402 "LASTCHANGED" => "zuletzt geändert am %d.%m.%Y um %H:%M",
403 "DISABLEDPAGE" => "Diese Seite kann momentan nicht angezeigt werden.",
404 "ERRVERSIONSAVE" => "Entschuldige, aber während Du an der Seite
405 gearbeitet hast, hat bereits jemand anders eine geänderte
406 Fassung gespeichert. Damit nichts verloren geht, browse bitte
407 zurück und speichere Deine Änderungen in der Zwischenablage
408 (Bearbeiten->Kopieren) um sie dann wieder an der richtigen
409 Stelle einzufügen, nachdem du die EditBoxSeite nocheinmal
410 geladen hast.<br />
411 Vielen Dank für Deine Mühe.",
412 "ERRORSAVING" => "Beim Abspeichern ist ein Fehler aufgetreten. Bitte versuche es erneut.",
413 "THANKSFORCONTRIBUTION" => "Vielen Dank für Deinen Beitrag!",
414 "CANNOTCHANGEPAGE" => "Diese Seite kann nicht geändert werden.",
415 "OLDVERCOMEBACK" => "Diese alte Version der Seite wieder zur Aktuellen machen",
416 "PREVIEW" => "Vorschau",
417 "SAVE" => "Speichern",
418 "CANCEL_EDIT" => "ÄnderungenVerwerfen",
419 "UPLOAD_PICTURE_BUTTON" => "Bild hochladen &gt;&gt;&gt;",
420 "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GuterStil\">GuterStil</a> ist es,
421 ganz einfach das zu schreiben, was einem gerade in den
422 Sinn kommt. Du solltest dich jetzt noch nicht so sehr
423 darum kümmern, wie die Seite aussieht. Du kannst später
424 immernoch zurückkommen und den Text mit <a href=\"".EWIKI_SCRIPT."FormatierungsRegeln\">WikiTextFormatierungsRegeln</a>
425 aufputschen.<br />",
426 "EDIT_FORM_2" => "<br />Bitte schreib keine Dinge, die andere Leute
427 verärgern könnten. Und bedenke auch, daß es schnell auf
428 dich zurückfallen kann wenn du verschiedene andere Dinge sagst (mehr Informationen zur
429 '<a href=\"http://google.de/search?q=computer+IP+adresse\">IP Adresse</a>'
430 deines Computers findest du bei Google).",
433 #-- InterWiki:Links
434 $ewiki_config["interwiki"] = @array_merge(
435 @$ewiki_config["interwiki"],
436 array(
437 "javascript" => "", # this actually protects from javascript: links
438 "url" => "",
439 # "self" => "this",
440 "this" => EWIKI_SCRIPT, # better was absolute _URL to ewiki wrapper
441 "jump" => "",
442 "ErfurtWiki" => "http://erfurtwiki.sourceforge.net/?id=",
443 "InterWiki" => "InterWikiSearch",
444 "InterWikiSearch" => "http://sunir.org/apps/meta.pl?",
445 "Wiki" => "WardsWiki",
446 "WardsWiki" => "http://www.c2.com/cgi/wiki?",
447 "WikiFind" => "http://c2.com/cgi/wiki?FindPage&amp;value=",
448 "WikiPedia" => "http://www.wikipedia.com/wiki.cgi?",
449 "MeatBall" => "MeatballWiki",
450 "MeatballWiki" => "http://www.usemod.com/cgi-bin/mb.pl?",
451 "UseMod" => "http://www.usemod.com/cgi-bin/wiki.pl?",
452 "PhpWiki" => "http://phpwiki.sourceforge.net/phpwiki/index.php3?",
453 "LinuxWiki" => "http://linuxwiki.de/",
454 "OpenWiki" => "http://openwiki.com/?",
455 "Tavi" => "http://andstuff.org/tavi/",
456 "TWiki" => "http://twiki.sourceforge.net/cgi-bin/view/",
457 "MoinMoin" => "http://www.purl.net/wiki/moin/",
458 "Google" => "http://google.com/search?q=",
459 "ISBN" => "http://www.amazon.com/exec/obidos/ISBN=",
460 "icq" => "http://www.icq.com/",
467 #-------------------------------------------------------------------- main ---
469 /* this is the main function, which you should preferrably call to
470 integrate the ewiki into your web site; it chains to most other
471 parts and plugins (including the edit box);
472 if you do not supply the requested pages "$id" we will fetch it
473 from the pre-defined possible URL parameters.
475 function ewiki_page($id=false) {
477 global $ewiki_links, $ewiki_plugins, $ewiki_ring, $ewiki_t, $ewiki_errmsg;
478 #-- output var
479 $o = "";
481 #-- selected page
482 if (!isset($_REQUEST)) {
483 $_REQUEST = @array_merge($_GET, $_POST);
485 if (!strlen($id)) {
486 $id = ewiki_id();
488 $id = format_string($id,true);
489 #-- page action
490 $action = EWIKI_DEFAULT_ACTION;
491 if ($delim = strpos($id, EWIKI_ACTION_SEP_CHAR)) {
492 $action = substr($id, 0, $delim);
493 $id = substr($id, $delim + 1);
495 elseif (EWIKI_USE_ACTION_PARAM && isset($_REQUEST["action"])) {
496 $action = $_REQUEST["action"];
498 $GLOBALS["ewiki_id"] = $id;
499 $GLOBALS["ewiki_title"] = ewiki_split_title($id);
500 $GLOBALS["ewiki_action"] = $action;
502 #-- fetch from db
503 $dquery = array(
504 "id" => $id
506 if (!isset($_REQUEST["content"]) && ($dquery["version"] = @$_REQUEST["version"])) {
507 $dquery["forced_version"] = $dquery["version"];
509 $data = @array_merge($dquery, ewiki_database("GET", $dquery));
511 #-- stop here if page is not marked as _TEXT,
512 # perform authentication then, and let only administrators proceed
513 if (!empty($data["flags"]) && (($data["flags"] & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT)) {
514 if (($data["flags"] & EWIKI_DB_F_BINARY) && ($pf = $ewiki_plugins["handler_binary"][0])) {
515 return($pf($id, $data, $action)); //_BINARY entries handled separately
517 elseif (!EWIKI_PROTECTED_MODE || !ewiki_auth($id, $data, $action, 0, 1) && ($ewiki_ring!=0)) {
518 return(ewiki_t("DISABLEDPAGE"));
522 #-- pre-check if actions exist
523 $pf_page = ewiki_array($ewiki_plugins["page"], $id);
525 #-- edit <form> for non-existent pages
526 if (($action==EWIKI_DEFAULT_ACTION) && empty($data["content"]) && empty($pf_page)) {
527 if (EWIKI_AUTO_EDIT) {
528 $action = "edit";
530 else {
531 $data["content"] = ewiki_t("DOESNOTEXIST");
534 #-- more initialization
535 if ($pf_a = @$ewiki_plugins["page_init"]) {
536 ksort($pf_a);
537 foreach ($pf_a as $pf) {
538 $o .= $pf($id, $data, $action);
540 unset($ewiki_plugins["page_init"]);
542 $pf_page = ewiki_array($ewiki_plugins["page"], $id);
544 #-- require auth
545 if (EWIKI_PROTECTED_MODE) {
546 if (!ewiki_auth($id, $data, $action, $ring=false, $force=EWIKI_AUTO_LOGIN)) {
547 return($o.=$ewiki_errmsg);
551 #-- handlers
552 $handler_o = "";
553 if ($pf_a = @$ewiki_plugins["handler"]) {
554 ksort($pf_a);
555 foreach ($pf_a as $pf) {
556 if ($handler_o = $pf($id, $data, $action)) { break; }
559 #-- finished by handler
560 if ($handler_o) {
561 $o .= $handler_o;
563 #-- actions that also work for static and internal pages
564 elseif (($pf = @$ewiki_plugins["action_always"][$action]) && function_exists($pf)) {
565 $o .= $pf($id, $data, $action);
567 #-- internal pages
568 elseif ($pf_page && function_exists($pf_page)) {
569 $o .= $pf_page($id, $data, $action);
571 #-- page actions
572 else {
573 $pf = @$ewiki_plugins["action"][$action];
575 #-- fallback to "view" action
576 if (empty($pf) || !function_exists($pf)) {
578 $pf = "ewiki_page_view";
579 $action = "view"; // we could also allow different (this is a
580 // catch-all) view variants, but this would lead to some problems
583 $o .= $pf($id, $data, $action);
586 #-- error instead of page?
587 if (empty($o) && $ewiki_errmsg) {
588 $o = $ewiki_errmsg;
591 #-- html post processing
592 if ($pf_a = $ewiki_plugins["page_final"]) {
593 ksort($pf_a);
594 foreach ($pf_a as $pf) {
595 if ($action == 'edit' and $pf == 'ewiki_html_tag_balancer') {
596 continue; // balancer breaks htmlarea buttons
598 $pf($o, $id, $data, $action);
602 (EWIKI_ESCAPE_AT) && ($o = str_replace("@", "&#x40;", $o));
604 return($o);
609 #-- HTTP meta headers
610 function ewiki_http_headers(&$o, $id, &$data, $action) {
611 global $ewiki_t;
612 if (EWIKI_HTTP_HEADERS && !headers_sent()) {
613 if (!empty($data)) {
614 if ($uu = @$data["id"]) @header('Content-Disposition: inline; filename="' . urlencode($uu) . '.html"');
615 if ($uu = @$data["version"]) @header('Content-Version: ' . $uu);
616 if ($uu = @$data["lastmodified"]) @header('Last-Modified: ' . gmstrftime($ewiki_t["C"]["DATE"], $uu));
618 if (EWIKI_NO_CACHE) {
619 header('Expires: ' . gmstrftime($ewiki_t["C"]["DATE"], UNIX_MILLENNIUM));
620 header('Pragma: no-cache');
621 header('Cache-Control: no-cache, private, must-revalidate');
622 # change to "C-C: cache, must-revalidate" ??
623 # private only for authenticated users / _PROT_MODE
625 #-- ETag
626 if ($data["version"] && ($etag=ewiki_etag($data)) || ($etag=md5($o))) {
627 $weak = "W/" . urlencode($id) . "." . $data["version"];
628 header("ETag: \"$etag\""); ###, \"$weak\"");
632 function ewiki_etag(&$data) {
633 return( urlencode($data["id"]) . ":" . dechex($data["version"]) . ":ewiki:" .
634 dechex(crc32($data["content"]) & 0x7FFFBFFF) );
639 #-- encloses whole page output with a descriptive <div>
640 function ewiki_page_css_container(&$o, &$id, &$data, &$action) {
641 $o = "<div class=\"wiki $action "
642 . strtr($id, ' ./ --_!"§$%&()=?²³{[]}`+#*;:,<>| @µöäüÖÄÜߤ^°«»\'\\',
643 '- -----------------------------------------------')
644 . "\">\n"
645 . $o . "\n</div>\n";
650 function ewiki_split_title ($id='', $split=EWIKI_SPLIT_TITLE, $entities=1) {
651 strlen($id) or ($id = $GLOBALS["ewiki_id"]);
652 if ($split) {
653 $id = preg_replace("/([".EWIKI_CHARS_L."])([".EWIKI_CHARS_U."]+)/", "$1 $2", $id);
655 return($entities ? s($id) : $id);
660 function ewiki_add_title(&$html, $id, &$data, $action, $go_action="links") {
661 $html = ewiki_make_title($id, '', 1, $action, $go_action) . $html;
665 function ewiki_make_title($id='', $title='', $class=3, $action="view", $go_action="links", $may_split=1) {
667 global $ewiki_config, $ewiki_plugins, $ewiki_title, $ewiki_id;
669 #-- advanced handler
670 if ($pf = @$ewiki_plugins["make_title"][0]) {
671 return($pf($title, $class, $action, $go_action, $may_split));
673 #-- disabled
674 elseif (!$ewiki_config["print_title"]) {
675 return("");
678 #-- get id
679 if (empty($id)) {
680 $id = $ewiki_id;
683 #-- get title
684 if (!strlen($title)) {
685 $title = $ewiki_title; // already in &html; format
687 elseif ($ewiki_config["split_title"] && $may_split) {
688 $title = ewiki_split_title($title, $ewiki_config["split_title"], 0&($title!=$ewiki_title));
690 else {
691 $title = s($title);
694 #-- title mangling
695 if ($pf_a = @$ewiki_plugins["title_transform"]) {
696 foreach ($pf_a as $pf) { $pf($id, $title, $go_action); }
699 #-- clickable link or simple headline
700 if ($class <= $ewiki_config["print_title"]) {
701 if ($uu = @$ewiki_config["link_title_action"][$action]) {
702 $go_action = $uu;
704 if ($uu = @$ewiki_config["link_title_url"]) {
705 $href = $uu;
706 unset($ewiki_config["link_title_url"]);
708 else {
709 $href = ewiki_script($go_action, $id);
711 $o = '<a href="' . $href . '">' . ($title) . '</a>';
713 else {
714 $o = $title;
717 return('<h2 class="page title">' . $o . '</h2>'."\n");
723 function ewiki_page_view($id, &$data, $action, $all=1) {
725 global $ewiki_plugins, $ewiki_config;
726 $o = "";
728 #-- render requested wiki page <-- goal !!!
729 $render_args = array(
730 "scan_links" => 1,
731 "html" => (EWIKI_ALLOW_HTML||(@$data["flags"]&EWIKI_DB_F_HTML)),
733 $o .= $ewiki_plugins["render"][0] ($data["content"], $render_args);
734 if (!$all) {
735 return($o);
737 #### MOODLE CHANGE
738 /// Add Moodle filters to text porion of wiki.
739 global $moodle_format; // from wiki/view.php
740 $o = format_text($o, $moodle_format);
741 $o.= "<br /><br />";
743 #-- control line + other per-page info stuff
744 if ($pf_a = $ewiki_plugins["view_append"]) {
745 ksort($pf_a);
746 foreach ($pf_a as $n => $pf) { $o .= $pf($id, $data, $action); }
748 if ($pf_a = $ewiki_plugins["view_final"]) {
749 ksort($pf_a);
750 foreach ($pf_a as $n => $pf) { $pf($o, $id, $data, $action); }
753 if (!empty($_REQUEST["thankyou"]) && $ewiki_config["edit_thank_you"]) {
754 $o = ewiki_t("THANKSFORCONTRIBUTION") . $o;
758 if (EWIKI_HIT_COUNTING) {
759 ewiki_database("HIT", $data);
762 return($o);
768 #-------------------------------------------------------------------- util ---
771 /* retrieves "$id/$action" string from URL / QueryString / PathInfo,
772 change this in conjunction with ewiki_script() to customize your URLs
773 further whenever desired
775 function ewiki_id() {
776 ($id = @$_REQUEST["id"]) or
777 ($id = @$_REQUEST["name"]) or
778 ($id = @$_REQUEST["page"]) or
779 ($id = @$_REQUEST["file"]) or
780 (EWIKI_USE_PATH_INFO) and ($id = ltrim(@$_SERVER["PATH_INFO"], "/")) or
781 (!isset($_REQUEST["id"])) and ($id = trim(strtok($_SERVER["QUERY_STRING"], "&")));
782 if (!strlen($id) || ($id=="id=")) {
783 $id = EWIKI_PAGE_INDEX;
785 (EWIKI_URLDECODE) && ($id = urldecode($id));
786 return($id);
792 /* replaces EWIKI_SCRIPT, works more sophisticated, and
793 bypasses various design flaws
794 - if only the first parameter is used (old style), it can contain
795 a complete "action/WikiPage" - but this is ambigutious
796 - else $asid is the action, and $id contains the WikiPageName
797 - $ewiki_config["script"] will now be used in favour of the constant
798 - needs more work on _BINARY, should be a separate function
800 ## MOODLE-CHANGE: $asid="", Knows the devil why....
801 function ewiki_script($asid="", $id=false, $params="", $bin=0, $html=1, $script=NULL) {
802 global $ewiki_config, $ewiki_plugins;
804 #-- get base script url from config vars
805 if (empty($script)) {
806 $script = &$ewiki_config[!$bin?"script":"script_binary"];
810 #-- separate $action and $id for old style requests
811 if ($id === false) {
812 if (strpos($asid, EWIKI_ACTION_SEP_CHAR) !== false) {
813 $asid = strtok($asid, EWIKI_ACTION_SEP_CHAR);
814 $id = strtok("\000");
816 else {
817 $id = $asid;
818 $asid = "";
822 #-- prepare params
823 if (is_array($params)) {
824 $uu = $params;
825 $params = "";
826 if ($uu) foreach ($uu as $k=>$v) {
827 $params .= (strlen($params)?"&":"") . rawurlencode($k) . "=" . rawurlencode($v);
830 #-- action= parameter
831 if (EWIKI_USE_ACTION_PARAM >= 2) {
832 $params = "action=$asid" . (strlen($params)?"&":"") . $params;
833 $asid = "";
836 #-- workaround slashes in $id
837 if (empty($asid) && (strpos($id, EWIKI_ACTION_SEP_CHAR) !== false) && !$bin) {
838 $asid = "view";
840 /*paranoia*/ $asid = trim($asid, EWIKI_ACTION_SEP_CHAR);
842 #-- make url
843 if (EWIKI_URLENCODE) {
844 $id = urlencode($id);
845 $asid = urlencode($asid);
847 else {
848 # only urlencode &, %, ? for example
850 $url = $script;
851 if ($asid) {
852 $id = $asid . EWIKI_ACTION_SEP_CHAR . $id; #= "action/PageName"
854 if (strpos($url, "%s") !== false) {
855 $url = str_replace("%s", $id, $url);
857 else {
858 $url .= $id;
861 #-- add url params
862 if (strlen($params)) {
863 $url .= (strpos($url,"?")!==false ? "&":"?") . $params;
865 #-- fin
866 if ($html) {
867 //Don't replace & if it's part of encoded character (bug 2209)
868 $url = preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/","&amp;", $url);
869 } else {
870 //This is going to be used in some header or meta redirect, so It cannot use &amp; (bug 2620)
871 $url = preg_replace('/&amp;/', '&', $url);
873 return($url);
877 /* this ewiki_script() wrapper is used to generate URLs to binary
878 content in the ewiki database
880 function ewiki_script_binary($asid, $id=false, $params=array(), $upload=0) {
882 $upload |= is_string($params) && strlen($params) || count($params);
884 #-- generate URL directly to the plainly saved data file,
885 # see also plugins/binary_store
887 if (defined("EWIKI_DB_STORE_URL") && !$upload) {
888 $url = EWIKI_DB_STORE_URL . rawurlencode($id);
891 #-- else get standard URL (thru ewiki.php) from ewiki_script()
892 else {
893 $url = ewiki_script($asid, $id, $params, "_BINARY=1");
896 return($url);
900 /* this function returns the absolute ewiki_script url, if EWIKI_SCRIPT_URL
901 is set, else it guesses the value
903 function ewiki_script_url() {
905 global $ewiki_action, $ewiki_id, $ewiki_config;
907 $scr_template = $ewiki_config["script"];
908 $scr_current = ewiki_script($ewiki_action, $ewiki_id);
909 $req_uri = $_SERVER["REQUEST_URI"];
911 if ($url = $ewiki_config["script_url"]) {
912 return($url);
914 elseif (strpos($req_uri, $scr_current) !== false) {
915 $url = str_replace($req_uri, $scr_current, $scr_template);
917 elseif (strpos($req_uri, "?") && (strpos($scr_template, "?") !== false)) {
918 $url = substr($req_uri, 0, strpos($req_uri, "?"))
919 . substr($scr_template, strpos($scr_template, "?"));
921 elseif (strpos($req_uri, $sn = $_SERVER["SCRIPT_NAME"])) {
922 $url = $sn . "?id=";
924 else {
925 return(NULL); #-- could not guess it
928 #$url = "http://" . $_SERVER["SERVER_NAME"] . $url;
929 return($url);
935 #------------------------------------------------------------ page plugins ---
939 function ewiki_page_links($id, &$data, $action) {
940 $o = ewiki_make_title($id, ewiki_t("PAGESLINKINGTO", array("title"=>$id)), 1, $action, "", "_MAY_SPLIT=1");
941 if ($pages = ewiki_get_backlinks($id)) {
942 $o .= ewiki_list_pages($pages);
943 } else {
944 $o .= ewiki_t("This page isn't linked from anywhere else.");
946 return($o);
949 function ewiki_get_backlinks($id) {
950 $result = ewiki_database("SEARCH", array("refs" => $id));
951 $pages = array();
952 while ($row = $result->get(0, 0x0020)) {
953 if ( strpos($row["refs"], "\n$id\n") !== false) {
954 $pages[] = $row["id"];
957 return($pages);
960 function ewiki_get_links($id) {
961 if ($data = ewiki_database("GET", array("id"=>$id))) {
962 $refs = explode("\n", trim($data["refs"]));
963 $r = array();
964 foreach (ewiki_database("FIND", $refs) as $id=>$exists) {
965 if ($exists) {
966 $r[] = $id;
969 return($r);
974 function ewiki_list_pages($pages=array(), $limit=EWIKI_LIST_LIMIT,
975 $value_as_title=0, $pf_list=false)
977 global $ewiki_plugins;
978 $o = "";
980 $is_num = !empty($pages[0]);
981 $lines = array();
982 $n = 0;
984 foreach ($pages as $id=>$add_text) {
986 $title = $id;
987 $params = "";
989 if (is_array($add_text)) {
990 list($id, $params, $title, $add_text) = $add_text;
992 elseif ($is_num) {
993 $id = $title = $add_text;
994 $add_text = "";
996 elseif ($value_as_title) {
997 $title = $add_text;
998 $add_text = "";
1001 $lines[] = '<a href="' . ewiki_script("", $id, $params) . '">' . s($title) . '</a> ' . $add_text;
1003 if (($limit > 0) && ($n++ >= $limit)) {
1004 break;
1008 if ($pf_a = @$ewiki_plugins["list_transform"])
1009 foreach ($pf_a as $pf_transform) {
1010 $pf_transform($lines);
1013 if (($pf_list) || ($pf_list = @$ewiki_plugins["list_pages"][0])) {
1014 $o = $pf_list($lines);
1016 elseif($lines) {
1017 $o = "&middot; " . implode("<br />\n&middot; ", $lines) . "<br />\n";
1020 return($o);
1026 function ewiki_page_ordered_list($orderby="created", $asc=0, $print, $title) {
1028 $o = ewiki_make_title("", $title, 2, ".list", "links", 0);
1030 $sorted = array();
1031 $result = ewiki_database("GETALL", array($orderby));
1033 while ($row = $result->get()) {
1034 $row = ewiki_database("GET", array(
1035 "id" => $row["id"],
1036 ($asc >= 0 ? "version" : "uu") => 1 // version 1 is most accurate for {hits}
1038 #-- text page?
1039 if (EWIKI_DB_F_TEXT == ($row["flags"] & EWIKI_DB_F_TYPE)) {
1040 #-- viewing allowed?
1041 if (!EWIKI_PROTECTED_MODE || !EWIKI_PROTECTED_MODE_HIDING || ewiki_auth($row["id"], $row, "view")) {
1042 $sorted[$row["id"]] = $row[$orderby];
1047 if ($asc != 0) { arsort($sorted); }
1048 else { asort($sorted); }
1050 foreach ($sorted as $name => $value) {
1051 if (empty($value)) { $value = "0"; }
1052 ##### BEGIN MOODLE ADDITION #####
1053 #$sorted[$name] = strftime(str_replace('%n', $value, $print), $value);
1054 if($print=="LASTCHANGED") {
1055 $value=strftime("%c",$value);
1057 $sorted[$name] = get_string(strtolower($print),"wiki",$value);
1058 ##### BEGIN MOODLE ADDITION #####
1060 $o .= ewiki_list_pages($sorted);
1062 return($o);
1067 function ewiki_page_newest($id=0, $data=0) {
1068 return( ewiki_page_ordered_list("created", 1, "LASTCHANGED", ewiki_t("NEWESTPAGES")) );
1071 function ewiki_page_updates($id=0, $data=0) {
1072 return( ewiki_page_ordered_list("lastmodified", -1, "LASTCHANGED", EWIKI_PAGE_UPDATES) );
1075 function ewiki_page_hits($id=0, $data=0) {
1076 ##### BEGIN MOODLE ADDITION #####
1077 return( ewiki_page_ordered_list("hits", 1, "hits", EWIKI_PAGE_HITS) );
1080 function ewiki_page_versions($id=0, $data=0) {
1081 return( ewiki_page_ordered_list("version", -1, "changes", EWIKI_PAGE_VERSIONS) );
1082 ##### END MOODLE ADDITION #####
1091 function ewiki_page_search($id, &$data, $action) {
1093 global $CFG;
1095 $o = ewiki_make_title($id, $id, 2, $action);
1097 if (! ($q = @$_REQUEST["q"])) {
1099 $o .= '<form action="' . ewiki_script("", $id) . '" method="post">';
1100 $o .= '<fieldset class="invisiblefieldset">';
1101 $o .= '<input name="q" size="30" /><br /><br />';
1102 $o .= '<input type="submit" value="'.$id.'" />';
1103 $o .= '</fieldset>';
1104 $o .= '</form>';
1106 else {
1107 $found = array();
1109 if ($CFG->unicodedb) {
1110 $q = preg_replace('/\s*[\W]+\s*/u', ' ', $q);
1111 } else {
1112 $q = preg_replace('/\s*[^\w]+\s*/', ' ', $q);
1114 foreach (explode(" ", $q) as $search) {
1116 if (empty($search)) { continue; }
1118 $result = ewiki_database("SEARCH", array("content" => $search));
1120 while ($row = $result->get()) {
1122 #-- show this entry in page listings?
1123 if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $row, "view")) {
1124 continue;
1127 $found[] = $row["id"];
1131 $o .= ewiki_list_pages($found);
1134 return($o);
1144 function ewiki_page_info($id, &$data, $action) {
1146 global $ewiki_plugins, $ewiki_config, $ewiki_links;
1147 global $CFG, $course; // MOODLE HACK
1149 $o = ewiki_make_title($id, ewiki_t("INFOABOUTPAGE")." '{$id}'", 2, $action,"", "_MAY_SPLIT=1");
1151 $flagnames = array(
1152 "TEXT", "BIN", "DISABLED", "HTML", "READONLY", "WRITEABLE",
1153 "APPENDONLY", "SYSTEM",
1155 $show = array(
1156 "version", "author", "userid", "created",
1157 "lastmodified", "refs",
1158 "flags", "meta", "content"
1161 #-- versions to show
1162 $v_start = $data["version"];
1163 if ( ($uu=@$_REQUEST[EWIKI_UP_PAGENUM]) && ($uu<=$v_start) ) {
1164 $v_start = $uu;
1166 $v_end = $v_start - $ewiki_config["list_limit"] + 1;
1167 if ( ($uu=@$_REQUEST[EWIKI_UP_PAGEEND]) && ($uu<=$v_start) ) {
1168 $v_end = $uu;
1170 $v_end = max($v_end, 1);
1172 #-- go
1173 # the very ($first) entry is rendered more verbosely than the others
1174 for ($v=$v_start,$first=1; ($v>=$v_end); $v--,$first=0) {
1176 $current = ewiki_database("GET", array("id"=>$id, "version"=>$v));
1178 if (!strlen(trim($current["id"])) || !$current["version"] || !strlen(trim($current["content"]))) {
1179 continue;
1182 $o .= '<table class="version-info" cellpadding="2" cellspacing="1">' . "\n";
1184 #-- additional info-actions
1185 $commands = '';
1186 foreach ($ewiki_config["action_links"]["info"] as $thisaction=>$title)
1187 if (@$ewiki_plugins["action"][$thisaction] || @$ewiki_plugins["action_always"][$thisaction]) {
1188 ##### BEGIN MOODLE ADDITION #####
1189 if ($commands) {
1190 $commands .= '&nbsp;&nbsp;';
1192 $commands .= '<a href="' .
1193 ewiki_script($thisaction, $id, array("version"=>$current["version"])) .
1194 '">' . get_string($title,"wiki") . '</a>';
1195 ##### END MOODLE ADDITION #####
1198 #-- print page database entry
1199 foreach($show as $i) {
1201 $value = @$current[$i];
1203 #-- show database {fields} differently
1204 if ($i == "meta") {
1205 continue; // MOODLE DOESN'T USE IT
1206 $str = "";
1207 if ($first && $value) { foreach ($value as $n=>$d) {
1208 $str .= s("$n: $d") . "<br />\n";
1210 $value = $str;
1212 elseif ($value >= UNIX_MILLENNIUM) { #-- {lastmodified}, {created}
1213 #### BEGIN MOODLE CHANGE
1214 $value=userdate($value);
1215 #$value = strftime("%c", $value);
1216 #### END MOODLE CHANGE
1218 elseif ($i == "content") {
1219 continue; // MOODLE DOESN'T CARE
1220 $value = strlen(trim($value)) . " bytes";
1221 $i = "content size";
1223 elseif ($first && ($i == "refs") && !(EWIKI_PROTECTED_MODE && (EWIKI_PROTECTED_MODE_HIDING>=2))) {
1224 $a = explode("\n", trim($value));
1225 $ewiki_links = ewiki_database("FIND", $a);
1226 ewiki_merge_links($ewiki_links);
1227 foreach ($a as $n=>$link) {
1228 $a[$n] = ewiki_link_regex_callback(array("$link"), "force_noimg");
1230 $value = trim(implode(", ", $a));
1231 if (!$value) {
1232 continue;
1235 elseif (strpos($value, "\n") !== false) { #-- also for {refs}
1236 $value = str_replace("\n", ", ", trim($value));
1237 if (!$value) {
1238 continue;
1241 elseif ($i == "version") {
1242 $value = '<a href="' .
1243 ewiki_script("", $id, array("version"=>$value)) . '">' .
1244 $value . '</a> '."($commands)";
1246 elseif ($i == "flags") {
1247 continue; // MOODLE DOESN'T USE IT
1248 $fstr = "";
1249 for ($n = 0; $n < 32; $n++) {
1250 if ($value & (1 << $n)) {
1251 if (! ($s=$flagnames[$n])) { $s = "UU$n"; }
1252 $fstr .= $s . " ";
1255 $value = $fstr;
1257 elseif ($i == "author") {
1258 continue;
1259 $ewiki_links=1;
1260 $value = preg_replace_callback("/((\w+:)?([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}[\w\d]*)/", "ewiki_link_regex_callback", $value);
1262 elseif ($i == "userid") {
1263 $i = 'author';
1264 if ($user = get_record('user', 'id', $value)) {
1265 if (!isset($course->id)) {
1266 $course->id = 1;
1268 $picture = print_user_picture($user->id, $course->id, $user->picture, false, true, true);
1269 $value = $picture." <a href=\"$CFG->wwwroot/user/view.php?id=$user->id&amp;course=$course->id\">".fullname($user)."</a>";
1270 } else {
1271 continue;
1272 //$value = @$current['author'];
1276 ##### BEGIN MOODLE ADDITION #####
1277 $o .= '<tr class="page-'.$i.'"><td style="vertical-align:top;text-align:right;white-space: nowrap;"><b>' .ewiki_t($i). ':</b></td>' .
1278 '<td>' . $value . "</td></tr>\n";
1279 ##### END MOODLE ADDITION #####
1283 $o .= "</table><br /><br />\n";
1287 #-- page result split
1288 if ($v >= 1) {
1289 $o .= "<br />\n".get_string('showversions','wiki').' '.ewiki_chunked_page($action, $id, -1, $v, 1, 0, 0) . "\n <br />";
1292 return($o);
1298 function ewiki_chunked_page($action, $id, $dir=-1, $start=10, $end=1, $limit=0, $overlap=0.25, $collapse_last=0.67) {
1300 global $ewiki_config;
1302 if (empty($limit)) {
1303 $limit = $ewiki_config["list_limit"];
1305 if ($overlap < 1) {
1306 $overlap = (int) ($limit * $overlap);
1309 $p = "";
1310 $n = $start;
1312 while ($n) {
1314 $n -= $dir * $overlap;
1316 $e = $n + $dir * ($limit + $overlap) + 1;
1318 if ($dir<0) {
1319 $e = max(1, $e);
1320 if ($e <= $collapse_last * $limit) {
1321 $e = 1;
1324 else {
1325 $e = min($end, $e);
1326 if ($e >= $collapse_last * $limit) {
1327 $e = $end;
1331 $o .= ($o?" &middot; ":"")
1332 . '<a href="'.ewiki_script($action, $id, array(EWIKI_UP_PAGENUM=>$n, EWIKI_UP_PAGEEND=>$e))
1333 . '">'. "$n-$e" . '</a>';
1335 if (($n=$e-1) < $end) {
1336 $n = false;
1340 return('<span class="chunked-result">'. $o .'</span>');
1348 function ewiki_page_edit($id, $data, $action) {
1350 global $ewiki_links, $ewiki_author, $ewiki_plugins, $ewiki_ring, $ewiki_errmsg;
1352 $hidden_postdata = array();
1354 #-- previous version come back
1355 if (@$data["forced_version"]) {
1357 $current = ewiki_database("GET", array("id"=>$id));
1358 $data["version"] = $current["version"];
1359 unset($current);
1361 unset($_REQUEST["content"]);
1362 unset($_REQUEST["version"]);
1365 #-- edit hacks
1366 if ($pf_a = @$ewiki_plugins["edit_hook"]) foreach ($pf_a as $pf) {
1367 if ($output = $pf($id, $data, $hidden_postdata)) {
1368 return($output);
1372 #-- permission checks
1373 if (isset($ewiki_ring)) {
1374 $ring = $ewiki_ring;
1375 } else {
1376 $ring = 3;
1378 $flags = @$data["flags"];
1379 if (!($flags & EWIKI_DB_F_WRITEABLE)) {
1381 #-- perform auth
1382 $edit_ring = (EWIKI_PROTECTED_MODE>=2) ? (2) : (NULL);
1383 if (EWIKI_PROTECTED_MODE && !ewiki_auth($id, $data, $action, $edit_ring, "FORCE")) {
1384 return($ewiki_errmsg);
1387 #-- flag checking
1388 if (($flags & EWIKI_DB_F_READONLY) and ($ring >= 2)) {
1389 return(ewiki_t("CANNOTCHANGEPAGE"));
1391 if (($flags) and (($flags & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT) and ($ring >= 1)) {
1392 return(ewiki_t("CANNOTCHANGEPAGE"));
1396 #-- "Edit Me"
1397 $o = ewiki_make_title($id, ewiki_t("EDITTHISPAGE").(" '{$id}'"), 2, $action, "", "_MAY_SPLIT=1");
1399 #-- preview
1400 if (isset($_REQUEST["preview"])) {
1401 $o .= $ewiki_plugins["edit_preview"][0]($data);
1404 #-- save
1405 if (isset($_REQUEST["save"])) {
1408 #-- normalize to UNIX newlines
1409 $_REQUEST["content"] = str_replace("\015\012", "\012", $_REQUEST["content"]);
1410 $_REQUEST["content"] = str_replace("\015", "\012", $_REQUEST["content"]);
1412 #-- check for concurrent version saving
1413 $error = 0;
1414 if ((@$data["version"] >= 1) && ($data["version"] != @$_REQUEST["version"]) || (@$_REQUEST["version"] < 1)) {
1416 $pf = $ewiki_plugins["edit_patch"][0];
1418 if (!$pf || !$pf($id, $data)) {
1419 $error = 1;
1420 $o .= ewiki_t("ERRVERSIONSAVE") . "<br /><br />";
1424 if (!$error) {
1426 #-- new pages` flags
1427 if (! ($set_flags = @$data["flags"] & EWIKI_DB_F_COPYMASK)) {
1428 $set_flags = 1;
1430 if (EWIKI_ALLOW_HTML) {
1431 $set_flags |= EWIKI_DB_F_HTML;
1434 #-- mk db entry
1435 $save = array(
1436 "id" => $id,
1437 "version" => @$data["version"] + 1,
1438 "flags" => $set_flags,
1439 "content" => $_REQUEST["content"],
1440 "created" => ($uu=@$data["created"]) ? $uu : time(),
1441 "meta" => ($uu=@$data["meta"]) ? $uu : "",
1442 "hits" => ($uu=@$data["hits"]) ? $uu : "0",
1444 ewiki_data_update($save);
1446 #-- edit storage hooks
1447 if ($pf_a = @$ewiki_plugins["edit_save"]) {
1448 foreach ($pf_a as $pf) {
1449 $pf($save, $data);
1453 #-- save
1454 if (!$save || !ewiki_database("WRITE", $save)) {
1456 $o .= $ewiki_errmsg ? $ewiki_errmsg : ewiki_t("ERRORSAVING");
1459 else {
1460 #-- prevent double saving, when ewiki_page() is re-called
1461 $_REQUEST = $_GET = $_POST = array();
1463 $o = ewiki_t("THANKSFORCONTRIBUTION") . "<br /><br />";
1464 $o .= ewiki_page($id);
1466 if (EWIKI_EDIT_REDIRECT) {
1467 $url = ewiki_script("", $id, "thankyou=1", 0, 0, EWIKI_HTTP_HEADERS?ewiki_script_url():0);
1469 if (EWIKI_HTTP_HEADERS && !headers_sent()) {
1470 header("Status: 303 Redirect for GET");
1471 header("Location: $url");
1472 #header("URI: $url");
1473 #header("Refresh: 0; URL=$url");
1475 else {
1476 $o .= '<meta http-equiv="Refresh" content="0; URL='.s($url).'">';
1484 //@REWORK
1485 // header("Reload-Location: " . ewiki_script("", $id, "", 0, 0, ewiki_script_url()) );
1488 else {
1489 #-- Edit <form>
1490 $o .= ewiki_page_edit_form($id, $data, $hidden_postdata);
1492 #-- additional forms
1493 if ($pf_a = $ewiki_plugins["edit_form_final"]) foreach ($pf_a as $pf) {
1494 $pf($o, $id, $data, $action);
1498 return($o);
1502 function ewiki_data_update(&$data, $author="") {
1503 global $USER, $ewiki_links;
1505 #-- add backlinks entry
1506 ewiki_scan_wikiwords($data["content"], $ewiki_links, "_STRIP_EMAIL=1");
1507 $data["refs"] = "\n\n".implode("\n", array_keys($ewiki_links))."\n\n";
1508 $data["lastmodified"] = time();
1509 $data["author"] = ewiki_author($author);
1510 if (isset($USER->id)) {
1511 $data["userid"] = $USER->id;
1517 #-- edit <textarea>
1518 function ewiki_page_edit_form(&$id, &$data, &$hidden_postdata) {
1519 global $ewiki_plugins, $ewiki_config, $moodle_format;
1521 $o='';
1523 #-- previously edited, or db fetched content
1524 if (@$_REQUEST["content"] || @$_REQUEST["version"]) {
1525 $data = array(
1526 "version" => &$_REQUEST["version"],
1527 "content" => &$_REQUEST["content"]
1530 else {
1531 if (empty($data["version"])) {
1532 $data["version"] = 1;
1534 @$data["content"] .= "";
1537 #-- normalize to DOS newlines
1538 $data["content"] = str_replace("\015\012", "\012", $data["content"]);
1539 $data["content"] = str_replace("\015", "\012", $data["content"]);
1540 $data["content"] = str_replace("\012", "\015\012", $data["content"]);
1542 $hidden_postdata["version"] = &$data["version"];
1544 #-- edit textarea/form
1545 // deleted name="ewiki", can not find the reference, and it's breaking xhtml
1546 $o .= ewiki_t("EDIT_FORM_1")
1547 . '<form method="post" enctype="multipart/form-data" action="'
1548 . ewiki_script("edit", $id) . '" '
1549 . ' accept-charset="'.EWIKI_CHARSET.'">' . "\n";
1550 $o .= '<div>';
1551 #-- additional POST vars
1552 foreach ($hidden_postdata as $name => $value) {
1553 $o .= '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
1556 ($cols = strtok($ewiki_config["edit_box_size"], "x*/,;:")) && ($rows = strtok("x, ")) || ($cols=70) && ($rows=15);
1557 global $ewiki_use_editor, $ewiki_editor_content;
1558 $ewiki_editor_content=1;
1559 if($ewiki_use_editor) {
1560 ob_start();
1561 $usehtmleditor = can_use_html_editor();
1562 echo '<table><tr><td>';
1563 if ($usehtmleditor) { //clean and convert before editing
1564 $options = new object();
1565 $options->smiley = false;
1566 $options->filter = false;
1567 $oldtext = format_text(ewiki_format($data["content"]), $moodle_format, $options);
1568 } else {
1569 $oldtext = ewiki_format($data["content"]);
1571 print_textarea($usehtmleditor, $rows, $cols, 680, 400, "content", $oldtext);
1572 echo '</td></tr></table>';
1574 if ($usehtmleditor) {
1575 use_html_editor("content");
1577 $o .= ob_get_contents();
1578 ob_end_clean();
1580 } else {
1581 ##### END MOODLE ADDITION #####
1583 $o .= '<textarea wrap="soft" id="ewiki_content" name="content" rows="'.$rows.'" cols="'.$cols.'">'
1584 . s($data["content"]) . "</textarea>"
1585 . $GLOBALS["ewiki_t"]["C"]["EDIT_TEXTAREA_RESIZE_JS"];
1587 ##### BEGIN MOODLE ADDITION #####
1589 ##### END MOODLE ADDITION #####
1591 #-- more <input> elements before the submit button
1592 if ($pf_a = $ewiki_plugins["edit_form_insert"]) foreach ($pf_a as $pf) {
1593 $o .= $pf($id, $data, $action);
1596 ##### BEGIN MOODLE ADDITION (Cancel Editing into Button) #####
1597 $o .= "\n<br />\n"
1598 . '<input type="submit" name="save" value="'. ewiki_t("SAVE") . '" />'."\n"
1599 . '<input type="submit" name="preview" value="'. ewiki_t("PREVIEW") . '" />' . "\n"
1600 . '<input type="submit" name="canceledit" value="'. ewiki_t("CANCEL_EDIT") . '" />' . "\n";
1601 # . ' &nbsp; <a href="'. ewiki_script("", $id) . '">' . ewiki_t("CANCEL_EDIT") . '</a>';
1602 ##### END MOODLE ADDITION #####
1604 #-- additional form elements
1605 if ($pf_a = $ewiki_plugins["edit_form_append"]) foreach ($pf_a as $pf) {
1606 $o .= $pf($id, $data, $action);
1609 $o .= "\n</div></form>\n";
1610 // . ewiki_t("EDIT_FORM_2"); // MOODLE DELETION
1612 return('<div class="edit-box">'. $o .'</div>');
1617 #-- pic upload form
1618 function ewiki_page_edit_form_final_imgupload(&$o, &$id, &$data, &$action) {
1619 if (EWIKI_SCRIPT_BINARY && EWIKI_UP_UPLOAD && EWIKI_IMAGE_MAXSIZE) {
1620 $o .= "\n<br />\n". '<div class="image-upload">'
1621 . '<form action='
1622 . '"'. ewiki_script_binary("", EWIKI_IDF_INTERNAL, "", "_UPLOAD=1") .'"'
1623 . ' method="post" enctype="multipart/form-data" target="_upload">'
1624 . '<fieldset class="invisiblefieldset">'
1625 . '<input type="hidden" name="MAX_FILE_SIZE" value="'.EWIKI_IMAGE_MAXSIZE.'" />'
1626 . '<input type="file" name="'.EWIKI_UP_UPLOAD.'"'
1627 . (defined("EWIKI_IMAGE_ACCEPT") ? ' accept="'.EWIKI_IMAGE_ACCEPT.'" />' : " />")
1628 . '<input type="hidden" name="'.EWIKI_UP_BINARY.'" value="'.EWIKI_IDF_INTERNAL.'" />'
1629 . '&nbsp;&nbsp;&nbsp;'
1630 . '<input type="submit" value="'.ewiki_t("UPLOAD_PICTURE_BUTTON").'" />'
1631 . '</fieldset></form></div>'. "\n";
1636 function ewiki_page_edit_preview(&$data) {
1637 #### BEGIN MOODLE CHANGES
1638 global $moodle_format;
1639 $preview_text=$GLOBALS["ewiki_plugins"]["render"][0]($_REQUEST["content"], 1, EWIKI_ALLOW_HTML || (@$data["flags"]&EWIKI_DB_F_HTML));
1640 return( '<div class="preview">'
1641 . "<hr noshade>"
1642 . "<div align=\"right\">" . ewiki_t("PREVIEW") . "</div><hr noshade><br />\n"
1643 . format_text($preview_text, $moodle_format)
1644 . "<br /><br /><hr noshade><br />"
1645 . "</div>"
1647 #### END MOODLE CHANGES
1651 function ewiki_control_links($id, &$data, $action) {
1653 global $ewiki_plugins, $ewiki_ring, $ewiki_config;
1654 $action_links = & $ewiki_config["action_links"][$action];
1656 #-- disabled
1657 if (!$ewiki_config["control_line"]) {
1658 return("");
1661 $o = "\n"
1662 . '<div align="right" class="action-links control-links">'
1663 . "\n<br />\n"
1664 . "<hr noshade>" . "\n";
1666 if (@$data["forced_version"]) {
1668 $o .= '<form action="' . ewiki_script("edit", $id) . '" method="post">' .
1669 '<fieldset class="invisiblefieldset">'.
1670 '<input type="hidden" name="edit" value="old" />' .
1671 '<input type="hidden" name="version" value="'.$data["forced_version"].'" />' .
1672 '<input type="submit" value="' . ewiki_t("OLDVERCOMEBACK") . '" /></form> ';
1674 else {
1675 foreach ($action_links as $action => $title)
1676 if (!empty($ewiki_plugins["action"][$action]) || !empty($ewiki_plugins["action_always"][$action]) || strpos($action, ":/"))
1678 if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($id, $data, $action)) { continue; }
1680 $o .= '<a href="'
1681 . (strpos($action, ":/") ? $action : ewiki_script($action, $id))
1682 . '">' . ewiki_t($title) . '</a> &middot; ';
1686 if ($data["lastmodified"] >= UNIX_MILLENNIUM) {
1687 $o .= '<small>' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . '</small>';
1690 $o .= "</div>\n";
1692 return($o);
1699 # ============================================================= rendering ===
1705 ######## ### ### ######### ### ### ### #######
1706 ######## #### ### ######### ### #### ### #######
1707 ### ##### ### ### ##### ### ###
1708 ###### ######### ### #### ### ######### ######
1709 ###### ######### ### #### ### ######### ######
1710 ### ### ##### ### ### ### ### ##### ###
1711 ######## ### #### ######### ### ### #### #######
1712 ######## ### ### ######### ### ### ### #######
1716 The _format() function transforms $wiki_source pages into <html> strings,
1717 also calls various markup and helper plugins during the transformation
1718 process. The $params array can activate various features and extensions.
1719 only accepts UNIX newlines!
1721 function ewiki_format (
1722 $wiki_source,
1723 $params = array()
1726 global $ewiki_links, $ewiki_plugins, $ewiki_config;
1728 #-- state vars
1729 $params = @array_merge($ewiki_config["format_params"], $params);
1730 $s = array(
1731 "in" => 0, # current input $iii[] block array index
1732 "para" => "",
1733 "line" => "",
1734 "post" => "", # string to append after current line/paragraph
1735 "line_i" => 0,
1736 "lines" => array(),
1737 "list" => "", # lists
1738 "tbl" => 0, # open table?
1739 "indent" => 0, # indentation
1740 "close" => array(),
1742 #-- aliases
1743 $in = &$s["in"];
1744 $line = &$s["line"];
1745 $lines = &$s["lines"];
1746 $para = &$s["para"];
1747 $post = &$s["post"];
1748 $list = &$s["list"];
1750 #-- input and output arrays
1751 if ($wiki_source[0] == "<") { # also prepend an empty line
1752 $wiki_source = "\n" . $wiki_source; # for faster strpos() searchs
1754 $iii = array(
1755 0 => array(
1756 0 => $wiki_source."\n", # body + empty line
1757 1 => 0x0FFF, # flags (0x1=WikiMarkup, 0x2=WikiLinks, 0x100=BlockPlugins)
1758 2 => "core", # block plugin name
1761 $ooo = array(
1763 unset($wiki_source);
1765 #-- plugins
1766 $pf_tbl = @$ewiki_plugins["format_table"][0];
1767 $pf_line = @$ewiki_plugins["format_line"];
1769 #-- wikimarkup (wm)
1770 $htmlentities = $ewiki_config["htmlentities"];
1771 $wm_indent = &$ewiki_config["wm_indent"];
1772 $wm_table_defaults = &$ewiki_config["wm_table_defaults"];
1773 $wm_source = &$ewiki_config["wm_source"];
1774 $wm_list = &$ewiki_config["wm_list"];
1775 $wm_list_chars = implode("", array_keys($wm_list));
1776 $wm_style = &$ewiki_config["wm_style"];
1777 $wm_start_end = &$ewiki_config["wm_start_end"];
1779 #-- eleminate html
1780 $iii[0][0] = strtr($iii[0][0], $htmlentities);
1781 unset($htmlentities["&"]);
1783 #-- pre-processing plugins (working on wiki source)
1784 if ($pf_source = $ewiki_plugins["format_source"]) {
1785 foreach ($pf_source as $pf) $pf($iii[0][0]);
1788 #-- simple markup
1789 $iii[0][0] = strtr($iii[0][0], $wm_source);
1791 #-- separate input into blocks ------------------------------------------
1792 foreach ($ewiki_config["format_block"] as $btype => $binfo) {
1794 #-- disabled block plugin?
1795 if ($binfo[2] && !$params[$binfo[2]]) {
1796 continue;
1799 #-- traverse $iii[]
1800 $in = -1;
1801 while ((++$in) < count($iii)) {
1803 #-- search fragment delimeters
1804 if ($iii[$in][1] & 0x0100)
1805 while (
1806 ($c = & $iii[$in][0]) &&
1807 (($l = strpos($c, $binfo[0])) !== false) &&
1808 ($r = strpos($c, $binfo[1], $l)) )
1810 $l_len = strlen($binfo[0]);
1811 $r_len = strlen($binfo[1]);
1813 $repl = array();
1814 // pre-text
1815 if (($l > 0) && trim($text = substr($c, 0, $l))) {
1816 $repl[] = array($text, 0xFFFF, "core");
1818 // the extracted part
1819 if (trim($text = substr($c, $l+$l_len, $r-$l-$r_len))) {
1820 $repl[] = array($text, $binfo[3], "$btype");
1822 // rest
1823 if (($r+$r_len < strlen($c)) && trim($text = substr($c, $r+$r_len))) {
1824 $repl[] = array($text, 0xFFFF, "core");
1826 array_splice($iii, $in, 1, $repl);
1828 $in += 1;
1833 #-- run format_block plugins
1834 $in = -1;
1835 while ((++$in) < count($iii)) {
1836 if (($btype = $iii[$in][2]) && ($pf_a = $ewiki_plugins["format_block"][$btype])) {
1837 $c = &$iii[$in][0];
1838 foreach ($pf_a as $pf) {
1839 # current buffer $c and pointer $in into $iii[] and state $s
1840 $pf($c, $in, $iii, $s, $btype);
1845 #-- wiki markup ------------------------------------------------------
1846 $para = "";
1847 $in = -1;
1848 while ((++$in) < count($iii)) {
1849 #-- wikimarkup
1850 if ($iii[$in][1] & 0x0001) {
1852 #-- input $lines buffer, and output buffer $ooo array
1853 $lines = explode("\n", $iii[$in][0]);
1854 $ooo[$in] = array(
1855 0 => "",
1856 1 => $iii[$in][1]
1858 $out = &$ooo[$in][0];
1859 $s["block"] = ($iii[$in][2] != "core"); # disables indentation & paragraphs
1861 #-- walk through wiki source lines
1862 $line_max = count($lines);
1863 foreach ($lines as $s["line_i"]=>$line) {
1864 //echo "<pre>line={$s[line_i]}:".htmlspecialchars($line).":".htmlspecialchars($line[0])."</pre>";
1866 #-- empty lines separate paragraphs
1867 if (!strlen($line)) {
1868 ewiki_format_close_para($ooo, $s);
1869 ewiki_format_close_tags($ooo, $s);
1870 if (!$s["block"]) {
1871 $out .= "\n";
1874 #-- horiz bar
1875 if (!strncmp($line, "----", 4)) {
1876 $out .= "<hr noshade>\n";
1877 continue;
1879 #-- html comment
1880 #if (!strncmp($line, "&lt;!--", 7)) {
1881 # $out .= "<!-- " . htmlentities(str_replace("--", "__", substr($line, 7))) . " -->\n";
1882 # continue;
1885 ($c0 = $line[0])
1886 or ($c0 = "\000");
1888 #-- tables
1889 ### MOODLE CHANGE: TRIM
1890 if (($c0 == "|") && ($line[strlen(trim($line))-1] == "|")) {
1891 if (!$s["tbl"]) {
1892 ewiki_format_close_para($ooo, $s);
1893 ewiki_format_close_tags($ooo, $s);
1894 $s["list"] = "";
1896 $line = substr($line, 1, -1);
1897 if ($pf_tbl) {
1898 $pf_tbl($line, $ooo, $s);
1900 else {
1901 if (!$s["tbl"]) {
1902 $out .= "<table " . $wm_table_defaults . ">\n";
1903 $s["close"][] = "\n</table>";
1905 $line = "<tr>\n<td>" . str_replace("|", "</td>\n<td>", $line) . "</td>\n</tr>";
1907 $s["tbl"] = 1;
1908 $para = false;
1910 elseif ($s["tbl"]) {
1911 $s["tbl"] = 0;
1915 #-- headlines
1916 if (($c0 == "!") && ($excl = strspn($line, "!"))) {
1917 if ($excl > 3) {
1918 $excl = 3;
1920 $line = substr($line, $excl);
1921 $excl = 5 - $excl;
1922 $line = "<h$excl>" . $line . "</h$excl>";
1923 if ($para) {
1924 ewiki_format_close_para($ooo, $s);
1926 ewiki_format_close_tags($ooo, $s);
1927 $para = false;
1930 #-- whole-line markup
1931 # ???
1934 #-- indentation (space/tab markup)
1935 $n_indent = 0;
1936 if (!$list && (!$s["block"]) && ($n_indent = strspn($line, " "))) {
1937 $n_indent = (int) ($n_indent / 2.65);
1938 while ($n_indent > $s["indent"]) {
1939 $out .= $wm_indent;
1940 $s["indent"]++;
1943 while ($n_indent < $s["indent"]) {
1944 $out .= "";
1945 $s["indent"]--;
1949 #-- text style triggers
1950 foreach ($wm_style as $find=>$replace) {
1951 $find_len = strlen($find);
1952 $loop = 20;
1953 while(($loop--) && (($l = strpos($line, $find)) !== false) && ($r = strpos($line, $find, $l + $find_len))) {
1954 $line = substr($line, 0, $l) . $replace[0] .
1955 substr($line, $l + strlen($find), $r - $l - $find_len) .
1956 $replace[1] . substr($line, $r + $find_len);
1961 #-- list markup
1962 if (isset($wm_list[$c0])) {
1963 if (!$list) {
1964 ewiki_format_close_para($ooo, $s);
1965 ewiki_format_close_tags($ooo, $s);
1967 $new_len = strspn($line, $wm_list_chars);
1968 $new_list = substr($line, 0, $new_len);
1969 $old_len = strlen($list);
1970 $lchar = $new_list[$new_len-1];
1971 list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
1973 #-- cut line
1974 $line = substr($line, $new_len);
1975 $lspace = "";
1976 $linsert = "";
1977 if ($ltag1) {
1978 $linsert = "<$ltag1>" . strtok($line, $lchar) . "</$ltag1> ";
1979 $line = strtok("\000");
1982 #-- add another <li>st entry
1983 if ($new_len == $old_len) {
1984 $lspace = str_repeat(" ", $new_len);
1985 $out .= "</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
1987 #-- add list
1988 elseif ($new_len > $old_len) {
1989 while ($new_len > ($old_len=strlen($list))) {
1990 $lchar = $new_list[$old_len];
1991 $list .= $lchar;
1992 list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
1993 $lclose = strtok($lopen, " ");
1994 $lspace = str_repeat(" ", $new_len);
1996 $out .= "\n$lspace<$lopen>\n" . "$lspace". $linsert . "<$ltag2>";
1997 $s["close"][] = "$lspace</$lclose>";
1998 $s["close"][] = "$lspace</$ltag2>";
2001 #-- close lists
2002 else {
2003 while ($new_len < ($old_len=strlen($list))) {
2004 $remove = $old_len-$new_len;
2005 ewiki_format_close_tags($ooo, $s, 2*$remove);
2006 $list = substr($list, 0, -$remove);
2008 if ($new_len) {
2009 $lspace = str_repeat(" ", $new_len);
2010 $out .= "$lspace</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
2014 $list = $new_list;
2015 $para = false;
2017 elseif ($list) {
2018 if ($c0 == " ") {
2019 $para = false;
2021 else {
2022 ewiki_format_close_tags($ooo, $s);
2023 $list = "";
2028 #-- start-end markup
2029 foreach ($wm_start_end as $d) {
2030 $len0 = strlen($d[0]);
2031 $loop = 20;
2032 while(($loop--) && (($l = strpos($line, $d[0])) !== false) && ($r = strpos($line, $d[1], $l + $len0))) {
2033 $len1 = strlen($d[1]);
2034 $line = substr($line, 0, $l) . $d[2] .
2035 substr($line, $l + $len0, $r - $l - $len0) .
2036 $replace[1] . substr($line, $r + $len1);
2040 #-- call wiki source formatting plugins that work on current line
2041 if ($pf_line) {
2042 foreach ($pf_line as $pf) $pf($out, $line, $post);
2047 #-- add formatted line to page-output
2048 $line .= $post;
2049 if ($para === false) {
2050 $out .= $line;
2051 $para = "";
2053 else {
2054 $para .= $line . "\n";
2059 #-- last block, or next not WikiSource?
2060 if (!isset($iii[$in+1]) || !($iii[$in+1][1] & 0x0011)) {
2061 ewiki_format_close_para($ooo, $s);
2062 ewiki_format_close_tags($ooo, $s);
2065 #-- copy as is into output buffer
2066 else {
2067 $ooo[$in] = $iii[$in];
2069 $iii[$in] = array();
2072 #-- wiki linking ------------------------------------------------------
2073 $scan_src = "";
2074 for ($in=0; $in<count($ooo); $in++) {
2075 if (EWIKI_HTML_CHARS && ($ooo[$in][1] & 0x0004)) { # html character entities
2076 $ooo[$in][0] = str_replace("&amp;#", "&#", $ooo[$in][0]);
2078 if ($ooo[$in][1] & 0x0022) {
2079 #-- join together multiple WikiSource blocks
2080 while (isset($ooo[$in+1]) && ($ooo[$in][1] & 0x0002) && ($ooo[$in+1][1] & 0x0002)) {
2081 $ooo[$in] = array(
2082 0 => $ooo[$in][0] . "\n" . $ooo[$in+1][0],
2083 1 => $ooo[$in][1] | $ooo[$in+1][1],
2085 array_splice($ooo, $in+1, 1);
2088 $scan_src .= $ooo[$in][0];
2092 #-- pre-scan
2093 if (1+$params["scan_links"]) {
2094 ewiki_scan_wikiwords($scan_src, $ewiki_links);
2096 if ($pf_linkprep = $ewiki_plugins["format_prepare_linking"]) {
2097 foreach ($pf_linkprep as $pf) $pf($scan_src);
2099 $scan_src = NULL;
2101 #-- finally the link-detection-regex
2102 for ($in=0; $in<count($ooo); $in++) {
2103 if ($ooo[$in][1] & 0x0002) {
2104 ##### BEGIN MOODLE ADDITION #####
2105 # No WikiLinks in Editor
2106 #################################
2107 global $ewiki_use_editor, $ewiki_editor_content;
2108 if(!($ewiki_use_editor && $ewiki_editor_content)) {
2109 ##### END MOODLE ADDITION #####
2110 ewiki_render_wiki_links($ooo[$in][0]);
2111 ##### BEGIN MOODLE ADDITION #####
2113 ##### END MOODLE ADDITION #####
2117 #-- fin: combine all blocks into html string ----------------------------
2118 $html = "";
2119 for ($in=0; $in<count($ooo); $in++) {
2120 $html .= $ooo[$in][0] . "\n";
2121 $ooo[$in] = 0;
2123 #-- call post processing plugins
2124 if ($pf_final = $ewiki_plugins["format_final"]) {
2125 foreach ($pf_final as $pf) $pf($html);
2127 return($html);
2132 function ewiki_format_close_para(&$ooo, &$s) {
2133 $out = &$ooo[$s["in"]][0];
2134 #-- output text block
2135 if (trim($s["para"])) {
2136 if (!$s["block"]) {
2137 #### MOODLE CHANGES
2138 global $ewiki_use_editor;
2139 if(!$ewiki_use_editor) {
2140 $s["para"] = "\n<p>\n" . ltrim($s["para"], "\n") . "</p>\n";
2142 #### MOODLE CHANGES
2144 #-- paragraph formation plugins
2145 if ($pf_a = $GLOBALS["ewiki_plugins"]["format_para"]) {
2146 foreach ($pf_a as $pf) {
2147 $pf($s["para"], $ooo, $s);
2150 $out .= $s["para"];
2151 $s["para"] = "";
2153 #-- indentation
2154 while ($s["indent"]) {
2155 $out .= "";
2156 $s["indent"]--;
2161 function ewiki_format_close_tags(&$ooo, &$s, $count=100) {
2162 $out = &$ooo[$s["in"]][0];
2163 if (!is_array($s) || !is_array($s["close"])) {
2164 die("\$s is garbaged == $s!!");
2166 while (($count--) && ($add = array_pop($s["close"]))) {
2167 $out .= $add . "\n";
2172 function ewiki_format_pre(&$str, &$in, &$iii, &$s, $btype) {
2173 $str = "<pre class=\"markup $btype\">" . $str . "</pre>";
2177 function ewiki_format_html(&$str, &$in, &$iii, &$s) {
2178 $he = array_reverse($GLOBALS["ewiki_config"]["htmlentities"]);
2179 $str = strtr($str, array_flip($he));
2180 $str = "<span class=\"markup html\">" . $str . "\n</span>\n";
2184 function ewiki_format_comment(&$str, &$in, &$iii, &$s, $btype) {
2185 $str = "<!-- " . str_replace("--", "¯¯", $str) . " -->";
2191 /* unclean pre-scanning for WikiWords in a page,
2192 pre-query to the db */
2193 function ewiki_scan_wikiwords(&$wiki_source, &$ewiki_links, $se=0) {
2195 global $ewiki_config;
2197 #-- find matches
2198 preg_match_all($ewiki_config["wiki_pre_scan_regex"], $wiki_source, $uu);
2199 $uu = @array_merge($uu[1], $uu[2], $uu[3], $uu[4], (array)@$uu[5]);
2201 #-- clean up list, trim() spaces (allows more unclean regex) - page id unification
2202 foreach ($uu as $i=>$id) {
2203 $uu[$i] = trim($id);
2205 unset($uu[""]);
2206 $uu = array_unique($uu);
2208 #-- query db
2209 $ewiki_links = ewiki_database("FIND", $uu);
2211 #-- strip email adresses
2212 if ($se) {
2213 foreach ($ewiki_links as $c=>$uu) {
2214 if (strpos($c, "@") && (strpos($c, ".") || strpos($c, ":"))) {
2215 unset($ewiki_links[$c]);
2224 /* regex on page content,
2225 handled by callback (see below)
2227 function ewiki_render_wiki_links(&$o) {
2229 global $ewiki_links, $ewiki_config, $ewiki_plugins;
2231 #-- merge with dynamic pages list
2232 ewiki_merge_links($ewiki_links);
2234 #-- replace WikiWords
2235 $link_regex = &$ewiki_config["wiki_link_regex"];
2236 $o = preg_replace_callback($link_regex, "ewiki_link_regex_callback", $o);
2238 #-- cleanup
2239 unset($ewiki_links);
2244 combines with page plugin list,
2245 and makes all case-insensitive
2247 function ewiki_merge_links(&$ewiki_links) {
2248 global $ewiki_plugins;
2249 #### BEGIN MOODLE CHANGES
2250 global $ewiki_link_case;
2251 $ewiki_link_case=array();
2252 #### END MOODLE CHANGES
2253 if ($ewiki_links !== true) {
2254 foreach ($ewiki_plugins["page"] as $page=>$uu) {
2255 $ewiki_links[$page] = 1;
2257 #### BEGIN MOODLE CHANGES
2258 foreach($ewiki_links as $page => $uu) {
2259 if($uu) {
2260 $ewiki_link_case[strtolower($page)]=$page;
2263 #### END MOODLE CHANGES
2264 $ewiki_links = ewiki_array($ewiki_links);
2271 /* link rendering (p)regex callback
2272 (ooutch, this is a complicated one)
2274 function ewiki_link_regex_callback($uu, $force_noimg=0) {
2275 #print "<pre>"; print_r($uu); print "</pre>";
2276 global $ewiki_links, $ewiki_plugins, $ewiki_config, $ewiki_id;
2278 $str = trim($uu[0]);
2279 $type = array();
2280 $states = array();
2282 #-- link bracket '[' escaped with '!' or '~'
2283 if (($str[0] == "!") || ($str[0] == "~")) {
2284 return(substr($str, 1));
2286 if ($str[0] == "#") {
2287 $states["define"] = 1;
2288 $str = substr($str, 1);
2290 if ($str[0] == "[") {
2291 $states["brackets"] = 1;
2292 $str = substr($str, 1, -1);
2295 #-- explicit title given via [ title | WikiLink ]
2296 $href = $title = strtok($str, "|");
2297 if ($uu = strtok("|")) {
2298 $href = $uu;
2299 $states["titled"] = 1;
2301 #-- title and href swapped: swap back
2302 if (strpos("://", $title) || strpos($title, ":") && !strpos($href, ":")) {
2303 $uu = $title; $title = $href; $href = $uu;
2306 #-- new entitling scheme [ url "title" ]
2307 if ((($l=strpos($str, '"')) < ($r=strrpos($str, '"'))) && ($l!==false) ) {
2308 $title = substr($str, $l + 1, $r - $l - 1);
2309 $href = substr($str, 0, $l) . substr($str, $r + 1);
2310 $states["titled"] = 1;
2313 #-- strip spaces
2314 $spaces_l = ($href[0]==" ") ?1:0;
2315 $spaces_r = ($href[strlen($href)-1]==" ") ?1:0;
2316 $title = ltrim(trim($title), "^");
2317 $href = ltrim(trim($href), "^");
2319 #-- strip_htmlentities()
2320 if (1&& (strpos($href, "&")!==false) && strpos($href, ";")) {
2321 foreach (array("&lt;"=>"<", "&gt;"=>">", "&amp;"=>"&") as $f=>$t) {
2322 $href = str_replace($f, $t, $href);
2326 #-- anchors
2327 $href2 = "";
2328 if (($p = strrpos($href, "#")) && ($p) && ($href[$p-1] != "&")) {
2329 $href2 = trim(substr($href, $p));
2330 $href = trim(substr($href, 0, $p));
2332 elseif ($p === 0) {
2333 $states["define"] = 1;
2335 if ($href == ".") {
2336 $href = $ewiki_id;
2339 #-- for case-insensitivines
2340 $href_i = EWIKI_CASE_INSENSITIVE ? strtolower($href) : ($href);
2342 #-- injected URLs
2343 if (strpos($inj_url = $ewiki_links[$href_i], "://")) {
2344 if ($href==$title) { $href = $inj_url; }
2347 #-- interwiki links
2348 if (strpos($href, ":") && ($uu = ewiki_interwiki($href, $type))) {
2349 $href = $uu;
2350 $str = "<a href=\"$href$href2\">$title</a>";
2352 #-- action:WikiLinks
2353 elseif ($ewiki_plugins["action"][$a=strtolower(strtok($href, ":"))]) {
2354 $type = array($a, "action", "wikipage");
2355 $str = '<a href="' . ewiki_script($a, strtok("\000")) . '">' . $title . '</a>';
2357 #-- page anchor definitions, if ($href[0]=="#")
2358 elseif (@$states["define"]) {
2359 $type = array("anchor");
2360 if ($title==$href) { $title="&nbsp;"; }
2361 $str = '<a name="' . s(ltrim($href, "#")) . '">' . ltrim($title, "#") . '</a>';
2363 #-- inner page anchor jumps
2364 elseif (strlen($href2) && ($href==$ewiki_id) || ($href[0]=="#") && ($href2=&$href)) {
2365 $type = array("jump");
2366 $str = '<a href="' . s($href2) . '">' . $title . '</a>';
2368 #-- ordinary internal WikiLinks
2369 elseif (($ewiki_links === true) || @$ewiki_links[$href_i]) {
2370 $type = array("wikipage");
2371 #### BEGIN MOODLE CHANGES
2372 global $ewiki_link_case;
2373 $href_realcase=array_key_exists($href_i,$ewiki_link_case) ? $ewiki_link_case[$href_i] : $href;
2374 $str = '<a href="' . ewiki_script("", $href_realcase) . s($href2)
2375 . '">' . $title . '</a>';
2376 #### END MOODLE CHANGES
2378 #-- guess for mail@addresses, convert to URI if
2379 elseif (strpos($href, "@") && !strpos($href, ":")) {
2380 $type = array("email");
2381 $href = "mailto:" . $href;
2383 #-- not found fallback
2384 else {
2385 $str = "";
2386 #-- a plugin may take care
2387 if ($pf_a = $ewiki_plugins["link_notfound"]) {
2388 foreach ($pf_a as $pf) {
2389 if ($str = $pf($title, $href, $href2, $type)) {
2390 break;
2394 #-- (QuestionMarkLink to edit/ action)
2395 if (!$str) {
2396 $type = array("notfound");
2397 $str = '<span class="NotFound"><b>' . $title . '</b><a href="' .
2398 ewiki_script("", $href) . '">?</a></span>';
2402 #-- convert standard URLs
2403 foreach ($ewiki_config["idf"]["url"] as $find)
2404 if (strpos($href, $find)===0) {
2405 $type[-2] = "url";
2406 $type[-1] = strtok($find, ":");
2408 #-- URL plugins
2409 if ($pf_a = $ewiki_plugins["link_url"]) foreach ($pf_a as $pf) {
2410 if ($str = $pf($href, $title)) { break 2; }
2412 $meta = @$ewiki_links[$href];
2414 #-- check for image files
2415 $ext = substr($href, strrpos($href,"."));
2416 $nocache = strpos($ext, "no");
2417 $ext = strtok($ext, "?&#");
2418 $obj = in_array($ext, $ewiki_config["idf"]["obj"]);
2419 $img = $obj || in_array($ext, $ewiki_config["idf"]["img"]);
2421 #-- internal:// references (binary files)
2422 if (EWIKI_SCRIPT_BINARY && ((strpos($href, EWIKI_IDF_INTERNAL)===0) ||
2423 EWIKI_IMAGE_MAXSIZE && EWIKI_CACHE_IMAGES && $img && !$nocache) )
2425 $type = array("binary");
2426 $href = ewiki_script_binary("", $href);
2429 #-- output html reference
2430 if (!$img || $force_noimg || !$states["brackets"] || (strpos($href, EWIKI_IDF_INTERNAL) === 0)) {
2431 $str = '<a href="' . $href . '">' . $title . '</a>';
2433 #-- img tag
2434 else {
2435 if (is_string($meta)) {
2436 $meta = unserialize($meta);
2438 $type = array("image");
2439 #-- uploaded images size
2440 $x = $meta["width"];
2441 $y = $meta["height"];
2442 if ($p = strpos('?', $href)) { #-- width/height given in url
2443 parse_str(str_replace("&amp;", "&", substr($href, $p)), $meta);
2444 ($uu = $meta["x"] . $meta["width"]) and ($x = $uu);
2445 ($uu = $meta["y"] . $meta["height"]) and ($y = $uu);
2446 if ($scale = $meta["r"] . $meta["scale"]) {
2447 ($p = strpos($scale, "%")) and ($scale = strpos($scale, 0, $p) / 100);
2448 $x *= $scale; $y *= $scale;
2451 $align = array('', ' align="right"', ' align="left"', ' align="center"');
2452 $align = $align[$spaces_l + 2*$spaces_r];
2453 $str = ($obj ? '<embed width="70%"' : '<img') . ' src="' . $href . '"' .
2454 ' alt="' . ($title) . '"' .
2455 (@$states["titled"] ? ' title="' . ($title) . '"' : '').
2456 ($x && $y ? " width=\"$x\" height=\"$y\"" : "") .
2457 $align . " />" . ($obj ? "</embed>" : "");
2458 # htmlentities($title)
2461 break;
2464 #-- icon/transform plugins
2465 ksort($type);
2466 if ($pf_a = @$ewiki_plugins["link_final"]) {
2467 foreach ($pf_a as $pf) { $pf($str, $type, $href, $title); }
2470 return($str);
2475 Returns URL if it encounters an InterWiki:Link or workalike.
2477 function ewiki_interwiki($href, &$type) {
2478 global $ewiki_config, $ewiki_plugins;
2480 if (strpos($href, ":") and !strpos($href, "//")
2481 and ($p1 = strtok($href, ":"))) {
2483 $page = strtok("\000");
2485 if (($p1 = ewiki_array($ewiki_config["interwiki"], $p1)) !== NULL) {
2486 $type = array("interwiki", $uu);
2487 while ($p1_alias = $ewiki_config["interwiki"][$p1]) {
2488 $type[] = $p1;
2489 $p1 = $p1_alias;
2491 if (!strpos($p1, "%s")) {
2492 $p1 .= "%s";
2494 $href = str_replace("%s", $page, $p1);
2495 return($href);
2497 elseif ($pf = $ewiki_plugins["intermap"][$p1]) {
2498 return($pf($p1, $page));
2505 implements FeatureWiki:InterMapWalking
2507 function ewiki_intermap_walking($id, &$data, $action) {
2508 if (empty($data["version"]) && ($href = ewiki_interwiki($id, $uu))) {
2509 header("Location: $href");
2510 return("<a href=\"$href\">$href</a>");
2516 # =========================================================================
2520 ##### ## ## ## ## ##### ## ##
2521 ###### ## ### ## #### ###### ## ##
2522 ## ## ## ### ## ###### ## ## ## ##
2523 ##### ## #### ## ## ## ###### ######
2524 ##### ## ####### ###### #### ####
2525 ## ### ## ## #### ###### ##### ##
2526 ## ### ## ## ### ## ## ## ### ##
2527 ###### ## ## ### ## ## ## ## ##
2528 ###### ## ## ## ## ## ## ## ##
2533 /* fetch & store
2535 function ewiki_binary($break=0) {
2536 global $ewiki_plugins;
2537 global $USER; // MOODLE
2539 #-- reject calls
2540 if (!strlen($id = @$_REQUEST[EWIKI_UP_BINARY]) || !EWIKI_IDF_INTERNAL) {
2541 return(false);
2543 if (headers_sent()) die("ewiki-binary configuration error");
2545 #-- upload requests
2546 $upload_file = @$_FILES[EWIKI_UP_UPLOAD];
2547 $add_meta = array();
2548 if ($orig_name = @$upload_file["name"]) {
2549 $add_meta["Content-Location"] = urlencode($orig_name);
2550 $add_meta["Content-Disposition"] = 'inline; filename="'.urlencode(basename("remote://$orig_name")).'"';
2553 #-- what are we doing here?
2554 if (($id == EWIKI_IDF_INTERNAL) && ($upload_file)) {
2555 $do = "upload";
2557 else {
2558 $data = ewiki_database("GET", array("id" => $id));
2559 $flags = @$data["flags"];
2560 if (EWIKI_DB_F_BINARY == ($flags & EWIKI_DB_F_TYPE)) {
2561 $do = "get";
2563 elseif (empty($data["version"]) and EWIKI_CACHE_IMAGES) {
2564 $do = "cache";
2566 else {
2567 $do = "nop";
2571 #-- auth only happens when enforced with _PROTECTED_MODE_XXL setting
2572 # (authentication for inline images in violation of the WWW spirit)
2573 if ((EWIKI_PROTECTED_MODE>=5) && !ewiki_auth($id, $data, "binary-{$do}")) {
2574 return($_REQUEST["id"]="view/BinaryPermissionError");
2577 #-- upload an image
2578 if ($do == "upload"){
2579 $id = ewiki_binary_save_image($upload_file["tmp_name"], "", $return=0, $add_meta);
2580 @unlink($upload_file["tmp_name"]);
2581 ($title = trim($orig_name, "/")) && ($title = preg_replace("/[^-._\w\d]+/", "_", substr(substr($orig_name, strrpos($title, "/")), 0, 20)))
2582 && ($title = '"'.$title.'"') || ($title="");
2584 if ($id) {
2585 echo<<<EOF
2586 <html><head><title>File/Picture Upload</title><script type="text/javascript"><!--
2587 opener.document.forms["ewiki"].elements["content"].value += "\\nUPLOADED PICTURE: [$id$title]\\n";
2588 window.setTimeout("self.close()", 5000);
2589 //--></script></head><body bgcolor="#440707" text="#FFFFFF">Your uploaded file was saved as<br /><big><b>
2590 [$id]
2591 </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>
2592 EOF;
2596 #-- request for contents from the db
2597 elseif ($do == "get") {
2598 #### CHANGED FOR MOODLE
2599 if (EWIKI_HIT_COUNTING) {
2600 $tmp["id"]=$id;
2601 ewiki_database("HIT", $tmp);
2603 #### CHANGED FOR MOODLE
2605 #-- send http_headers from meta
2606 if (is_array($data["meta"])) {
2607 foreach ($data["meta"] as $hdr=>$val) {
2608 if (($hdr[0] >= "A") && ($hdr[0] <= "Z")) {
2609 header("$hdr: $val");
2614 #-- fetch from binary store
2615 if ($pf_a = $ewiki_plugins["binary_get"]) {
2616 #### CHANGED FOR MOODLE
2617 foreach ($pf_a as $pf) { $pf($id, $data["meta"]); }
2619 #### END CHANGED FOR MOODLE
2622 #-- else fpassthru
2623 echo $data["content"];
2626 #-- fetch & cache requested URL,
2627 elseif ($do == "cache") {
2629 #-- check for standard protocol names, to prevent us from serving
2630 # evil requests for '/etc/passwd.jpeg' or '../.htaccess.gif'
2631 if (preg_match('@^\w?(http|ftp|https|ftps|sftp)\w?://@', $id)) {
2633 #-- generate local copy
2634 $filename = tempnam(EWIKI_TMP, "ewiki.local.temp.");
2635 if (($i = fopen($id, "rb")) && ($o = fopen($filename, "wb"))) {
2637 while (!feof($i)) {
2638 fwrite($o, fread($i, 65536));
2641 fclose($i);
2642 fclose($o);
2644 $add_meta = array(
2645 "Content-Location" => urlencode($id),
2646 "Content-Disposition" => 'inline; filename="'.urlencode(basename($id)).'"'
2649 $result = ewiki_binary_save_image($filename, $id, "RETURN", $add_meta);
2653 #-- deliver
2654 if ($result && !$break) {
2655 ewiki_binary($break=1);
2657 #-- mark URL as unavailable
2658 else {
2659 $data = array(
2660 "id" => $id,
2661 "version" => 1,
2662 "flags" => EWIKI_DB_F_DISABLED,
2663 "lastmodified" => time(),
2664 "created" => time(),
2665 "author" => ewiki_author("ewiki_binary_cache"),
2666 "userid" => $USER->id,
2667 "content" => "",
2668 "meta" => array("Status"=>"404 Absent"),
2670 ewiki_database("WRITE", $data);
2671 header("Location: $id");
2672 ewiki_log("imgcache: did not find '$id', and marked it now in database as DISABLED", 2);
2677 #-- "we don't sell this!"
2678 else {
2679 if (strpos($id, EWIKI_IDF_INTERNAL) === false) {
2680 header("Status: 301 Located SomeWhere Else");
2681 header("Location: $id");
2683 else {
2684 header("Status: 404 Absent");
2685 header("X-Broken-URI: $id");
2689 // you should not remove this one, it is really a good idea to use it!
2690 die();
2698 function ewiki_binary_save_image($filename, $id="", $return=0,
2699 $add_meta=array(), $accept_all=EWIKI_ACCEPT_BINARY, $care_for_images=1)
2701 global $ewiki_plugins;
2702 global $USER; // MOODLE
2704 #-- break on empty files
2705 if (!filesize($filename)) {
2706 return(false);
2709 #-- check for image type and size
2710 $mime_types = array(
2711 "application/octet-stream",
2712 "image/gif",
2713 "image/jpeg",
2714 "image/png",
2715 "application/x-shockwave-flash"
2717 $ext_types = array(
2718 "bin", "gif", "jpeg", "png", "swf"
2720 list($width, $height, $mime_i, $uu) = getimagesize($filename);
2721 (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
2723 #-- images expected
2724 if ($care_for_images) {
2726 #-- mime type
2727 if (!$mime_i && !$accept_all || !filesize($filename)) {
2728 ewiki_die(ewiki_t("BIN_NOIMG"), $return);
2729 return;
2732 #-- resize image
2733 if (strpos($mime,"image/")!==false) {
2734 if ($pf_a = $ewiki_plugins["image_resize"]) {
2735 foreach ($pf_a as $pf) {
2736 if (EWIKI_IMAGE_RESIZE && (filesize($filename) > EWIKI_IMAGE_MAXSIZE)) {
2737 $pf($filename, $mime, $return);
2738 clearstatcache();
2739 }}}}
2741 #-- reject image if too large
2742 if (strlen($content) > EWIKI_IMAGE_MAXSIZE) {
2743 ewiki_die(ewiki_t("BIN_IMGTOOLARGE"), $return);
2744 return;
2747 #-- again check mime type and image sizes
2748 list($width, $height, $mime_i, $uu) = getimagesize($filename);
2749 (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
2752 ($ext = $ext_types[$mime_i]) or ($ext = $ext_types[0]);
2754 #-- binary files
2755 if ((!$mime_i) && ($pf = $ewiki_plugins["mime_magic"][0])) {
2756 if ($tmp = $pf($content)) {
2757 $mime = $tmp;
2760 if (!strlen($mime)) {
2761 $mime = $mime_types[0];
2764 #-- store size of binary file
2765 $add_meta["size"] = filesize($filename);
2766 $content = "";
2768 #-- handler for (large/) binary content?
2769 if ($pf_a = $ewiki_plugins["binary_store"]) {
2770 foreach ($pf_a as $pf) {
2771 $pf($filename, $id, $add_meta, $ext);
2775 #-- read file into memory (2MB), to store it into the database
2776 if ($filename) {
2777 $f = fopen($filename, "rb");
2778 $content = fread($f, 1<<21);
2779 fclose($f);
2782 #-- generate db file name
2783 if (empty($id)) {
2784 $md5sum = md5($content);
2785 $id = EWIKI_IDF_INTERNAL . $md5sum . ".$ext";
2786 ewiki_log("generated md5sum '$md5sum' from file content");
2789 #-- prepare meta data
2790 $meta = @array_merge(array(
2791 "class" => $mime_i ? "image" : "file",
2792 "Content-Type" => $mime,
2793 "Pragma" => "cache",
2794 ), $add_meta);
2795 if ($mime_i) {
2796 $meta["width"] = $width;
2797 $meta["height"] = $height;
2800 #-- database entry
2801 $data = array(
2802 "id" => $id,
2803 "version" => "1",
2804 "author" => ewiki_author(),
2805 "userid" => $USER->id,
2806 "flags" => EWIKI_DB_F_BINARY | EWIKI_DB_F_READONLY,
2807 "created" => time(),
2808 "lastmodified" => time(),
2809 "meta" => &$meta,
2810 "content" => &$content,
2813 #-- write if not exist
2814 $exists = ewiki_database("FIND", array($id));
2815 if (! $exists[$id] ) {
2816 $result = ewiki_database("WRITE", $data);
2817 ewiki_log("saving of '$id': " . ($result ? "ok" : "error"));
2819 else {
2820 ewiki_log("binary_save_image: '$id' was already in the database", 2);
2823 return($id);
2829 # =========================================================================
2832 #### #### #### ######## ########
2833 ##### ##### #### ########## ##########
2834 ###### ###### #### #### ### #### ###
2835 ############# #### ####
2836 ############# #### ######## ####
2837 #### ### #### #### ######## ####
2838 #### # #### #### #### ####
2839 #### #### #### ### #### #### ###
2840 #### #### #### ######### ##########
2841 #### #### #### ####### ########
2845 /* yes! it is not neccessary to annoy users with country flags, if the
2846 http already provides means to determine preferred languages!
2848 function ewiki_localization() {
2850 global $ewiki_t, $ewiki_plugins;
2852 $deflangs = ','.@$_ENV["LANGUAGE"] . ','.@$_ENV["LANG"]
2853 . ",".EWIKI_DEFAULT_LANG . ",en,C";
2855 foreach (explode(",", @$_SERVER["HTTP_ACCEPT_LANGUAGE"].$deflangs) as $l) {
2857 $l = strtok($l, ";");
2858 $l = strtok($l, "-"); $l = strtok($l, "_"); $l = strtok($l, ".");
2859 $l = trim($l);
2861 $ewiki_t["languages"][] = strtolower($l);
2868 /* poor mans gettext, $repl is an array of string replacements to get
2869 applied to the fetched text chunk,
2870 "$const" is either an entry from $ewiki_t[] or a larger text block
2871 containing _{text} replacement braces of the form "_{...}"
2873 function ewiki_t($const, $repl=array(), $pref_langs=array()) {
2874 ##### BEGIN MOODLE ADDITION #####
2875 $replacechars=array("." => "",
2876 "," => "",
2877 "!" => "",
2878 ";" => "",
2879 ":" => "",
2880 "'" => "",
2881 '"' => "",
2882 "-" => "",
2883 "_" => "",
2884 " " => "",
2885 "+" => "");
2887 $translation=get_string(strtolower(strtr($const,$replacechars)),"wiki",$repl);
2888 return $translation;
2889 ##### END MOODLE ADDITION #####
2891 /* global $ewiki_t;
2893 #-- use default language wishes
2894 if (empty($pref_langs)) {
2895 $pref_langs = $ewiki_t["languages"];
2898 #-- large text snippet replaceing
2899 if (strpos($const, "_{") !== false) {
2900 while ( (($l=strpos($const,"_{")) || ($l===0)) && ($r=strpos($const,"}",$l)) ) {
2901 $const = substr($const, 0, $l)
2902 . ewiki_t(substr($const, $l+2, $r-$l-2))
2903 . substr($const,$r+1);
2907 #-- just one string
2908 else foreach ($pref_langs as $l) {
2910 if (is_string($r = @$ewiki_t[$l][$const]) || ($r = @$ewiki_t[$l][strtoupper($const)])) {
2912 foreach ($repl as $key=>$value) {
2913 if ($key[0] != '$') {
2914 $key = '$'.$key;
2916 $r = str_replace($key, $value, $r);
2918 return($r);
2923 return($const);*/
2931 function ewiki_log($msg, $error_type=3) {
2933 if ((EWIKI_LOGLEVEL >= 0) && ($error_type <= EWIKI_LOGLEVEL)) {
2935 $msg = time() . " - " .
2936 getremoteaddr() . ":" . $_SERVER["REMOTE_PORT"] . " - " .
2937 $_SERVER["REQUEST_METHOD"] . " " . $_SERVER["REQUEST_URI"] . " - " .
2938 strtr($msg, "\n\r\000\377\t\f", "\r\r\r\r\t\f") . "\n";
2939 error_log($msg, 3, EWIKI_LOGFILE);
2946 function ewiki_die($msg, $return=0) {
2947 ewiki_log($msg, 1);
2948 if ($return) {
2949 return($GLOBALS["ewiki_error"] = $msg);
2951 else {
2952 die($msg);
2958 function ewiki_array_hash(&$a) {
2959 return(count($a) . ":" . implode(":", array_keys(array_slice($a, 0, 3))));
2964 /* provides an case-insensitive in_array replacement to search a page name
2965 in a list of others;
2966 the supplied $array WILL be lowercased afterwards, unless $dn was set
2968 function ewiki_in_array($value, &$array, $dn=0, $ci=EWIKI_CASE_INSENSITIVE) {
2970 static $as = array();
2972 #-- work around pass-by-reference
2973 if ($dn && $ci) { $dest = array(); }
2974 else { $dest = &$array; }
2976 #-- make everything lowercase
2977 if ($ci) {
2978 $value = strtolower($value);
2979 if (empty($as[ewiki_array_hash($array)])) { // prevent working on the
2980 foreach ($array as $i=>$v) { // same array multiple times
2981 $dest[$i] = strtolower($v);
2983 $as[ewiki_array_hash($dest)] = 1;
2987 #-- search in values
2988 return(in_array($value, $dest));
2993 /* case-insensitively retrieves an entry from an $array,
2994 or returns the given $array lowercased if $key was obmitted
2996 function ewiki_array($array, $key=false, $am=1, $ci=EWIKI_CASE_INSENSITIVE) {
2998 #-- make everything lowercase
2999 if ($ci) {
3000 $key = strtolower($key);
3002 $r = array();
3003 foreach ($array as $i=>$v) {
3004 $i = strtolower($i);
3005 if (!$am || empty($r[$i])) {
3006 $r[$i] = $v;
3008 else {
3009 $r[$i] .= $v; //RET: doubling for images`meta won't happen
3010 } // but should be "+" here for integers
3012 $array = &$r;
3015 #-- search in values
3016 if ($key) {
3017 return(@$array[$key]);
3019 else {
3020 return($array);
3029 function ewiki_author($defstr="") {
3031 $author = @$GLOBALS["ewiki_author"];
3032 ($ip = getremoteaddr()) or ($ip = "127.0.0.0");
3033 ($port = $_SERVER["REMOTE_PORT"]) or ($port = "null");
3034 $hostname = $ip;
3035 $remote = (($ip != $hostname) ? $hostname . " " : "")
3036 . $ip . ":" . $port;
3038 (empty($author)) && (
3039 ($author = $defstr) ||
3040 ($author = $_SERVER["HTTP_FROM"]) || // RFC2068 sect 14.22
3041 ($author = $_SERVER["PHP_AUTH_USER"])
3044 (empty($author))
3045 && ($author = $remote)
3046 || ($author = addslashes($author) . " (" . $remote . ")" );
3048 return($author);
3055 /* Returns a value of (true) if the currently logged in user (this must
3056 be handled by one of the plugin backends) is authenticated to do the
3057 current $action, or to view the current $id page.
3058 - alternatively just checks current authentication $ring permission level
3059 - errors are returned via the global $ewiki_errmsg
3061 function ewiki_auth($id, &$data, $action, $ring=false, $request_auth=0) {
3063 global $ewiki_plugins, $ewiki_ring, $ewiki_author, $ewiki_errmsg;
3064 $ok = true;
3065 $ewiki_errmsg="";
3067 #echo "_a($id,dat,$action,$ring,$request_auth)<br />\n";
3069 if (EWIKI_PROTECTED_MODE) {
3071 #-- set required vars
3072 if (!isset($ewiki_ring)) {
3073 $ewiki_ring = (int)EWIKI_AUTH_DEFAULT_RING;
3075 if ($ring===false) {
3076 $ring = NULL;
3079 #-- plugins to call
3080 $pf_login = @$ewiki_plugins["auth_query"][0];
3081 $pf_perm = $ewiki_plugins["auth_perm"][0];
3083 #-- nobody is currently logged in, so try to fetch username,
3084 # the login <form> is not yet enforced
3085 if ($pf_login && empty($ewiki_auth_user)) {
3086 $pf_login($data, 0);
3089 #-- check permission for current request (page/action/ring)
3090 if ($pf_perm) {
3092 #-- via _auth handler
3093 $ok = $pf_perm($id, $data, $action, $ring, $request_auth);
3095 #-- if it failed, we really depend on the login <form>,
3096 # and then recall the _perm plugin
3097 if ($pf_login && (($request_auth >= 2) || !$ok && $request_auth && (empty($ewiki_auth_user) || EWIKI_AUTO_LOGIN) && empty($ewiki_errmsg))) {
3098 //@FIXME: complicated if() - strip empty(errmsg) ??
3099 $pf_login($data, $request_auth);
3100 $ok = $pf_perm($id, $data, $action, $ring, $request_auth=0);
3103 else {
3104 $ok = !isset($ring) || isset($ring) && ($ewiki_ring <= $ring);
3107 #-- return error string
3108 if (!$ok && empty($ewiki_errmsg)) {
3109 $ewiki_errmsg = ewiki_t("FORBIDDEN");
3113 return($ok);
3118 Queries all registered ["auth_userdb"] plugins for the given
3119 username, and compares password to against "db" value, sets
3120 $ewiki_ring and returns(true) if valid.
3122 function ewiki_auth_user($username, $password) {
3123 global $ewiki_ring, $ewiki_errmsg, $ewiki_auth_user, $ewiki_plugins, $ewiki_author;
3125 if (empty($username)) {
3126 return(false);
3128 if (($password[0] == "$") || (strlen($password) > 12)) {
3129 ewiki_log("_auth_userdb: password was transmitted in encoded form, or is just too long (login attemp for user '$username')", 2);
3130 return(false);
3133 if ($pf_u = $ewiki_plugins["auth_userdb"])
3134 foreach ($pf_u as $pf) {
3136 if (function_exists($pf) && ($entry = $pf($username, $password))) {
3138 #-- get and compare password
3139 if ($entry = (array) $entry) {
3140 $enc_pw = $entry[0];
3142 $success = false
3143 || ($enc_pw == substr($password, 0, 12))
3144 || ($enc_pw == md5($password))
3145 || ($enc_pw == crypt($password, substr($enc_pw, 0, 2)))
3146 || function_exists("sha1") && ($enc_pw == sha1($password));
3147 $success &= $enc_pw != "*";
3149 #-- return if it matches
3150 if ($success) {
3151 if (isset($entry[1])) {
3152 $ewiki_ring = (int)($entry[1]);
3153 } else {
3154 $ewiki_ring = 2; //(EWIKI_AUTH_DEFAULT_RING - 1);
3156 if (empty($ewiki_author)) {
3157 ($ewiki_author = $entry[2]) or
3158 ($ewiki_author = $username);
3160 return($success && ($ewiki_auth_user=$username));
3165 if ($username || $password) {
3166 ewiki_log("_auth_userdb: wrong password supplied for user '$username', not verified against any userdb", 3);
3167 $ewiki_errmsg = "wrong username and/or password";
3168 # ewiki_auth($uu, $uu, $uu, $uu, 2);
3170 return(false);
3177 /* reads all files from "./init-pages/" into the database,
3178 when ewiki is run for the very first time and the FrontPage
3179 does not yet exist in the database
3181 function ewiki_eventually_initialize(&$id, &$data, &$action) {
3183 global $USER;
3185 #-- initialize database only if frontpage missing
3186 if (($id==EWIKI_PAGE_INDEX) && ($action=="edit") && empty($data["version"])) {
3188 ewiki_database("INIT", array());
3189 #### BEGIN MOODLE CHANGE
3190 $path=EWIKI_INIT_PAGES;
3191 if (!empty($path)) {
3192 if ($dh = @opendir($path=EWIKI_INIT_PAGES)) {
3193 while (false !== ($filename = readdir($dh))) {
3194 #### MOODLE CHANGE TO SOLVE BUG #3830. Original doesn't support dots in names.
3195 //Orig->if (preg_match('/^(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+\w*)+/', $filename)) {
3196 if ($filename == clean_filename($filename) && !is_dir($path.'/'.$filename)) {
3197 #### END OF MOODLE CHANGE TO SOLVE BUG #3830. Original doesn't support dots in names.
3198 $found = ewiki_database("FIND", array($filename));
3199 if (! $found[$filename]) {
3200 $content = implode("", file("$path/$filename"));
3201 ewiki_scan_wikiwords($content, $ewiki_links, "_STRIP_EMAIL=1");
3202 $refs = "\n\n" . implode("\n", array_keys($ewiki_links)) . "\n\n";
3203 $save = array(
3204 "id" => "$filename",
3205 "version" => "1",
3206 "flags" => "1",
3207 "content" => $content,
3208 "author" => ewiki_author("ewiki_initialize"),
3209 "userid" => $USER->id,
3210 "refs" => $refs,
3211 "lastmodified" => filemtime("$path/$filename"),
3212 "created" => filectime("$path/$filename") // (not exact)
3214 ewiki_database("WRITE", $save);
3218 closedir($dh);
3220 else {
3221 echo "<b>ewiki error</b>: could not read from directory ". realpath($path) ."<br />\n";
3224 #### END MOODLE CHANGE
3226 #-- try to view/ that newly inserted page
3227 if ($data = ewiki_database("GET", array("id"=>$id))) {
3228 $action = "view";
3236 #---------------------------------------------------------------------------
3240 ######## ### ######## ### ######## ### ###### ########
3241 ######## ### ######## ### ######## ### ###### ########
3242 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3243 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3244 ## ## ## ## ## ## ## ## ## ## ## ## ##
3245 ## ## ## ## ## ## ## ## ## ## ## ## ##
3246 ## ## ## ## ## ## ## ######## ## ## ###### ######
3247 ## ## ## ## ## ## ## ######## ## ## ###### ######
3248 ## ## ######### ## ######### ## ## ######### ## ##
3249 ## ## ######### ## ######### ## ## ######### ## ##
3250 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3251 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3252 ######## ## ## ## ## ## ######## ## ## ###### ########
3253 ######## ## ## ## ## ## ######## ## ## ###### ########
3258 /* wrapper
3260 function ewiki_database($action, $args, $sw1=0, $sw2=0, $pf=false) {
3262 #-- normalize (fetch bad parameters)
3263 if (($action=="GET") && !is_array($args) && is_string($args)) {
3264 $args = array("id" => $args);
3267 #-- treat special
3268 switch ($action) {
3270 case "GETALL":
3271 $args = array_unique(@array_merge($args, array("flags", "version")));
3272 $args = array_diff($args, array("id"));
3273 break;
3275 case "SEARCH":
3276 # unset($args["version"]);
3277 # unset($args["flags"]);
3278 break;
3280 default:
3281 break;
3284 #-- handle {meta} sub array as needed
3285 if (is_array(@$args["meta"])) {
3286 $args["meta"] = serialize($args["meta"]);
3289 #-- database plugin
3290 if (($pf) || ($pf = @$GLOBALS["ewiki_plugins"]["database"][0])) {
3291 $r = $pf($action, $args, $sw1, $sw2);
3293 else {
3294 ewiki_log("DB layer: no backend!", 0);
3295 $r = false;
3298 #-- database layer generation 2 abstraction
3299 if (is_array($r) && (($action=="SEARCH") || ($action=="GETALL"))) {
3300 $z = new ewiki_dbquery_result(array_keys($args));
3301 foreach ($r as $id=>$row) {
3302 $z->add($row);
3304 $r = $z;
3307 #-- extract {meta} sub array
3308 if (is_array($r) && !is_array(@$r["meta"]) && strlen(@$r["meta"])) {
3309 $r["meta"] = unserialize($r["meta"]);
3312 return($r);
3317 /* returned for SEARCH and GETALL queries, as those operations are
3318 otherwise too memory exhaustive
3320 class ewiki_dbquery_result {
3322 var $keys = array();
3323 var $entries = array();
3324 var $buffer = EWIKI_DBQUERY_BUFFER;
3325 var $size = 0;
3327 function ewiki_dbquery_result($keys) {
3328 $keys = @array_merge($keys, array(-50=>"id", "version", "flags"));
3329 $this->keys = array_unique($keys);
3332 function add($row) {
3333 if (is_array($row)) {
3334 if ($this->buffer) {
3335 $this->size += strlen(serialize($row));
3336 $this->buffer = $this->size <= EWIKI_DBQUERY_BUFFER;
3338 else {
3339 $row = $row["id"];
3342 $this->entries[] = $row;
3345 function get($all=0, $flags=0x00) {
3346 $row = array();
3348 $prot_hide = ($flags&0x0020) && EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING;
3349 do {
3350 if (count($this->entries)) {
3352 #-- fetch very first entry from $entries list
3353 $r = array_shift($this->entries);
3355 #-- finish if buffered entry
3356 if (is_array($r) && !$all) {
3357 $row = $r;
3359 #-- else refetch complete entry from database
3360 else {
3361 if (is_array($r)) {
3362 $r = $r["id"];
3364 $r = ewiki_database("GET", array("id"=>$r));
3365 if (!$all) {
3366 foreach ($this->keys as $key) {
3367 $row[$key] = $r[$key];
3369 } else {
3370 $row = $r;
3373 unset($r);
3375 else {
3376 return(NULL); // no more entries
3379 #-- expand {meta} field
3380 if (is_array($row) && is_string(@$row["meta"])) {
3381 $row["meta"] = unserialize($row["meta"]);
3384 #-- drop unwanted results
3385 if ($prot_hide && !ewiki_auth($row["id"], $row, $ewiki_action)) {
3386 $row = array();
3388 } while ($prot_hide && empty($row));
3390 return($row);
3393 function count() {
3394 return(count($this->entries));
3400 /* MySQL database backend
3401 (default)
3402 Note: this is of course an abuse of the relational database scheme,
3403 but neccessary for real db independence and abstraction
3405 function ewiki_database_mysql($action, &$args, $sw1, $sw2) {
3407 #-- reconnect to the database (if multiple are used)
3408 #<off># mysql_ping($GLOBALS["db"]);
3410 #-- result array
3411 $r = array();
3413 switch($action) {
3415 /* Returns database entry as array for the page whose name was given
3416 with the "id" key in the $args array, usually fetches the latest
3417 version of a page, unless a specific "version" was requested in
3418 the $args array.
3420 case "GET":
3421 $id = "'" . mysql_escape_string($args["id"]) . "'";
3422 ($version = 0 + @$args["version"]) and ($version = "AND (version=$version)") or ($version="");
3423 $result = mysql_query("SELECT * FROM " . EWIKI_DB_TABLE_NAME
3424 . " WHERE (pagename=$id) $version ORDER BY version DESC LIMIT 1"
3426 if ($result && ($r = mysql_fetch_array($result, MYSQL_ASSOC))) {
3427 $r["id"] = $r["pagename"];
3428 unset($r["pagename"]);
3430 if (strlen($r["meta"])) {
3431 $r["meta"] = @unserialize($r["meta"]);
3433 break;
3437 /* Increases the hit counter for the page name given in $args array
3438 with "id" index key.
3440 case "HIT":
3441 mysql_query("UPDATE " . EWIKI_DB_TABLE_NAME . " SET hits=(hits+1) WHERE pagename='" . mysql_escape_string($args["id"]) . "'");
3442 break;
3446 /* Stores the $data array into the database, while not overwriting
3447 existing entries (using WRITE); returns 0 on failure and 1 if
3448 saved correctly.
3450 case "OVERWRITE": // fall-through
3451 $COMMAND = "REPLACE";
3453 case "WRITE":
3454 $args["pagename"] = $args["id"];
3455 unset($args["id"]);
3457 if (is_array($args["meta"])) {
3458 $args["meta"] = serialize($args["meta"]);
3461 $sql1 = $sql2 = "";
3462 foreach ($args as $index => $value) {
3463 if (is_int($index)) {
3464 continue;
3466 $a = ($sql1 ? ', ' : '');
3467 $sql1 .= $a . $index;
3468 $sql2 .= $a . "'" . mysql_escape_string($value) . "'";
3471 strlen(@$COMMAND) || ($COMMAND = "INSERT");
3473 $result = mysql_query("$COMMAND INTO " . EWIKI_DB_TABLE_NAME .
3474 " (" . $sql1 . ") VALUES (" . $sql2 . ")"
3477 return($result && mysql_affected_rows() ?1:0);
3478 break;
3482 /* Checks for existence of the WikiPages whose names are given in
3483 the $args array. Returns an array with the specified WikiPageNames
3484 associated with values of "0" or "1" (stating if the page exists
3485 in the database). For images/binary db entries returns the "meta"
3486 field instead of an "1".
3488 case "FIND":
3489 $sql = "";
3490 foreach (array_values($args) as $id) if (strlen($id)) {
3491 $r[$id] = 0;
3492 $sql .= ($sql ? " OR " : "") .
3493 "(pagename='" . mysql_escape_string($id) . "')";
3495 $result = mysql_query($sql = "SELECT pagename AS id, meta FROM " .
3496 EWIKI_DB_TABLE_NAME . " WHERE $sql "
3498 while ($result && ($row = mysql_fetch_row($result))) {
3499 $r[$row[0]] = strpos($row[1], 's:5:"image"') ? $row[1] : 1;
3501 break;
3505 /* Returns an array of __all__ pages, where each entry is made up
3506 of the fields from the database requested with the $args array,
3507 e.g. array("flags","meta","lastmodified");
3509 case "GETALL":
3510 $result = mysql_query("SELECT pagename AS id, ".
3511 implode(", ", $args) .
3512 " FROM ". EWIKI_DB_TABLE_NAME .
3513 " GROUP BY id, version DESC"
3515 $r = new ewiki_dbquery_result($args);
3516 $drop = "";
3517 while ($result && ($row = mysql_fetch_array($result, MYSQL_ASSOC))) {
3518 $i = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
3519 if ($i != $drop) {
3520 $drop = $i;
3521 $r->add($row);
3524 break;
3528 /* Returns array of database entries (also arrays), where the one
3529 specified column matches the specified content string, for example
3530 $args = array("content" => "text...piece")
3531 is not guaranteed to only search/return the latest version of a page
3533 case "SEARCH":
3534 $field = implode("", array_keys($args));
3535 $content = strtolower(implode("", $args));
3536 if ($field == "id") { $field = "pagename"; }
3538 $result = mysql_query("SELECT pagename AS id, version, flags" .
3539 (EWIKI_DBQUERY_BUFFER && ($field!="pagename") ? ", $field" : "") .
3540 " FROM " . EWIKI_DB_TABLE_NAME .
3541 " WHERE LOCATE('" . mysql_escape_string($content) . "', LCASE($field)) " .
3542 " GROUP BY id, version DESC"
3544 $r = new ewiki_dbquery_result(array("id","version",$field));
3545 $drop = "";
3546 while ($result && ($row = mysql_fetch_array($result, MYSQL_ASSOC))) {
3547 $i = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
3548 if ($i != $drop) {
3549 $drop = $i;
3550 $r->add($row);
3553 break;
3557 case "DELETE":
3558 $id = mysql_escape_string($args["id"]);
3559 $version = $args["version"];
3560 mysql_query("DELETE FROM " . EWIKI_DB_TABLE_NAME ."
3561 WHERE pagename='$id' AND version=$version");
3562 break;
3566 case "INIT":
3567 mysql_query("CREATE TABLE " . EWIKI_DB_TABLE_NAME ."
3568 (pagename VARCHAR(160) NOT NULL,
3569 version INTEGER UNSIGNED NOT NULL DEFAULT 0,
3570 flags INTEGER UNSIGNED DEFAULT 0,
3571 content MEDIUMTEXT,
3572 author VARCHAR(100) DEFAULT 'ewiki',
3573 userid INTEGER UNSIGNED DEFAULT 0,
3574 created INTEGER UNSIGNED DEFAULT ".time().",
3575 lastmodified INTEGER UNSIGNED DEFAULT 0,
3576 refs MEDIUMTEXT,
3577 meta MEDIUMTEXT,
3578 hits INTEGER UNSIGNED DEFAULT 0,
3579 PRIMARY KEY id (pagename, version) )
3581 echo mysql_error();
3582 break;
3584 default:
3587 return($r);