MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / mod / wiki / ewiki / ewiki.php
blobeeeb2f00a2ac6d9ac101c2296cfa3547ac1835b4
1 <script language="PHP"> @define("EWIKI_VERSION", "R1.01d");
3 /*
5 ErfurtWiki - an embedable, fast and user-friendly wiki engine
6 ����������
7 This is Public Domain (no license, no warranty); but feel free
8 to redistribute it under GPL or anything else you like.
10 http://erfurtwiki.sourceforge.net/
11 Mario Salzer <mario*erphesfurt�de> and many others(tm)
14 Use it from inside yoursite.php like that:
15 <html><body>...
16 <?php
17 include("ewiki.php");
18 echo ewiki_page();
23 #-- you could also establish a mysql connection in here, of course:
24 // mysql_connect(":/var/run/mysqld/mysqld.sock", "user", "pw")
25 // and mysql_query("USE mydatabase");
28 #-------------------------------------------------------- config ---
30 #-- I'm sorry for that, but all the @ annoy me
31 error_reporting(0x0000377 & error_reporting());
32 # error_reporting(E_ALL^E_NOTICE);
34 #-- the position of your ewiki-wrapper script
35 define("EWIKI_SCRIPT", "?id="); # relative/absolute to docroot
36 # define("EWIKI_SCRIPT_URL", "http://...?id="); # absolute URL
38 #-- change to your needs (site lang)
39 define("EWIKI_NAME", "ErfurtWiki");
40 define("EWIKI_PAGE_INDEX", "ErfurtWiki");
41 define("EWIKI_PAGE_NEWEST", "NewestPages");
42 define("EWIKI_PAGE_SEARCH", "SearchPages");
43 define("EWIKI_PAGE_HITS", "MostVisitedPages");
44 define("EWIKI_PAGE_VERSIONS", "MostOftenChangedPages");
45 define("EWIKI_PAGE_UPDATES", "UpdatedPages");
47 #-- default settings are good settings - most often ;)
48 #- look & feel
49 define("EWIKI_PRINT_TITLE", 1); # <h2>WikiPageName</h2> on top
50 define("EWIKI_SPLIT_TITLE", 0); # <h2>Wiki Page Name</h2>
51 define("EWIKI_CONTROL_LINE", 1); # EditThisPage-link at bottom
52 define("EWIKI_LIST_LIMIT", 20); # listing limit
53 #- behaviour
54 define("EWIKI_AUTO_EDIT", 1); # edit box for non-existent pages
55 define("EWIKI_EDIT_REDIRECT", 1); # redirect after edit save
56 define("EWIKI_DEFAULT_ACTION", "view"); # (keep!)
57 define("EWIKI_CASE_INSENSITIVE", 1); # wikilink case sensitivity
58 define("EWIKI_HIT_COUNTING", 1);
59 define("UNIX_MILLENNIUM", 1000000000);
60 #- rendering
61 define("EWIKI_ALLOW_HTML", 0); # often a very bad idea
62 define("EWIKI_HTML_CHARS", 1); # allows for &#200;
63 define("EWIKI_ESCAPE_AT", 1); # "@" -> "&#x40;"
64 #- http/urls
65 define("EWIKI_HTTP_HEADERS", 1); # most often a good thing
66 define("EWIKI_NO_CACHE", 1); # browser+proxy shall not cache
67 define("EWIKI_URLENCODE", 1); # disable when _USE_PATH_INFO
68 define("EWIKI_URLDECODE", 1);
69 define("EWIKI_USE_PATH_INFO", 1 &&!strstr($_SERVER["SERVER_SOFTWARE"],"Apache"));
70 define("EWIKI_USE_ACTION_PARAM", 1);
71 define("EWIKI_ACTION_SEP_CHAR", "/");
72 define("EWIKI_UP_PAGENUM", "n"); # _UP_ means "url parameter"
73 define("EWIKI_UP_PAGEEND", "e");
74 define("EWIKI_UP_BINARY", "binary");
75 define("EWIKI_UP_UPLOAD", "upload");
76 #- other stuff
77 define("EWIKI_DEFAULT_LANG", "en");
78 define("EWIKI_CHARSET", "UTF-8");
79 #- user permissions
80 define("EWIKI_PROTECTED_MODE", 0); # disable funcs + require auth
81 define("EWIKI_PROTECTED_MODE_HIDING", 0); # hides disallowed actions
82 define("EWIKI_AUTH_DEFAULT_RING", 3); # 0=root 1=priv 2=user 3=view
83 define("EWIKI_AUTO_LOGIN", 1); # [auth_query] on startup
85 #-- allowed WikiPageNameCharacters
87 #### BEGIN MOODLE CHANGES - to remove auto-camelcase linking.
88 global $moodle_disable_camel_case;
89 if ($moodle_disable_camel_case) {
90 define("EWIKI_CHARS_L", "");
91 define("EWIKI_CHARS_U", "");
93 else {
94 #### END MOODLE CHANGES
96 define("EWIKI_CHARS_L", "a-z_��$\337-\377");
97 define("EWIKI_CHARS_U", "A-Z0-9\300-\336");
99 #### BEGIN MOODLE CHANGES
101 #### END MOODLE CHANGES
103 define("EWIKI_CHARS", EWIKI_CHARS_L.EWIKI_CHARS_U);
105 #-- database
106 define("EWIKI_DB_TABLE_NAME", "ewiki"); # MySQL / ADOdb
107 define("EWIKI_DBFILES_DIRECTORY", "/tmp"); # see "db_flat_files.php"
108 define("EWIKI_DBA", "/tmp/ewiki.dba"); # see "db_dba.php"
109 define("EWIKI_DBQUERY_BUFFER", 512*1024); # 512K
110 define("EWIKI_INIT_PAGES", "./init-pages"); # for initialization
112 define("EWIKI_DB_F_TEXT", 1<<0);
113 define("EWIKI_DB_F_BINARY", 1<<1);
114 define("EWIKI_DB_F_DISABLED", 1<<2);
115 define("EWIKI_DB_F_HTML", 1<<3);
116 define("EWIKI_DB_F_READONLY", 1<<4);
117 define("EWIKI_DB_F_WRITEABLE", 1<<5);
118 define("EWIKI_DB_F_APPENDONLY", 1<<6); #nyi
119 define("EWIKI_DB_F_SYSTEM", 1<<7);
120 define("EWIKI_DB_F_PART", 1<<8);
121 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);
122 define("EWIKI_DB_F_ACCESS", EWIKI_DB_F_READONLY | EWIKI_DB_F_WRITEABLE | EWIKI_DB_F_APPENDONLY);
123 define("EWIKI_DB_F_COPYMASK", EWIKI_DB_F_TYPE | EWIKI_DB_F_ACCESS);
125 define("EWIKI_DBFILES_NLR", '\\n');
126 define("EWIKI_DBFILES_ENCODE", 0 || (DIRECTORY_SEPARATOR != "/"));
127 define("EWIKI_DBFILES_GZLEVEL", "2");
129 #-- internal
130 define("EWIKI_ADDPARAMDELIM", (strstr(EWIKI_SCRIPT,"?") ? "&" : "?"));
132 #-- binary content (images)
133 define("EWIKI_SCRIPT_BINARY", /*"/binary.php?binary="*/ ltrim(strtok(" ".EWIKI_SCRIPT,"?"))."?".EWIKI_UP_BINARY."=" );
134 define("EWIKI_CACHE_IMAGES", 1 &&!headers_sent());
135 define("EWIKI_IMAGE_MAXSIZE", 64 *1024);
136 define("EWIKI_IMAGE_MAXWIDTH", 3072);
137 define("EWIKI_IMAGE_MAXHEIGHT", 2048);
138 define("EWIKI_IMAGE_MAXALLOC", 1<<19);
139 define("EWIKI_IMAGE_RESIZE", 1);
140 define("EWIKI_IMAGE_ACCEPT", "image/jpeg,image/png,image/gif,application/x-shockwave-flash");
141 define("EWIKI_IDF_INTERNAL", "internal://");
142 define("EWIKI_ACCEPT_BINARY", 0); # for arbitrary binary data files
144 #-- misc
145 define("EWIKI_TMP", $_SERVER["TEMP"] ? $_SERVER["TEMP"] : "/tmp");
146 define("EWIKI_LOGLEVEL", -1); # 0=error 1=warn 2=info 3=debug
147 define("EWIKI_LOGFILE", "/tmp/ewiki.log");
149 #-- plugins (tasks mapped to function names)
150 $ewiki_plugins["database"][] = "ewiki_database_mysql";
151 $ewiki_plugins["edit_preview"][] = "ewiki_page_edit_preview";
152 $ewiki_plugins["render"][] = "ewiki_format";
153 $ewiki_plugins["init"][-5] = "ewiki_localization";
154 $ewiki_plugins["init"][-1] = "ewiki_binary";
155 $ewiki_plugins["handler"][-105] = "ewiki_eventually_initialize";
156 $ewiki_plugins["handler"][] = "ewiki_intermap_walking";
157 $ewiki_plugins["view_append"][-1] = "ewiki_control_links";
158 $ewiki_plugins["view_final"][-1] = "ewiki_add_title";
159 $ewiki_plugins["page_final"][] = "ewiki_http_headers";
160 $ewiki_plugins["page_final"][99115115] = "ewiki_page_css_container";
161 $ewiki_plugins["edit_form_final"][] = "ewiki_page_edit_form_final_imgupload";
162 $ewiki_plugins["format_block"]["pre"][] = "ewiki_format_pre";
163 $ewiki_plugins["format_block"]["code"][] = "ewiki_format_pre";
164 $ewiki_plugins["format_block"]["htm"][] = "ewiki_format_html";
165 $ewiki_plugins["format_block"]["html"][] = "ewiki_format_html";
166 $ewiki_plugins["format_block"]["comment"][] = "ewiki_format_comment";
169 #-- internal pages
170 $ewiki_plugins["page"][EWIKI_PAGE_NEWEST] = "ewiki_page_newest";
171 $ewiki_plugins["page"][EWIKI_PAGE_SEARCH] = "ewiki_page_search";
172 if (EWIKI_HIT_COUNTING) $ewiki_plugins["page"][EWIKI_PAGE_HITS] = "ewiki_page_hits";
173 $ewiki_plugins["page"][EWIKI_PAGE_VERSIONS] = "ewiki_page_versions";
174 $ewiki_plugins["page"][EWIKI_PAGE_UPDATES] = "ewiki_page_updates";
176 #-- page actions
177 $ewiki_plugins["action"]["edit"] = "ewiki_page_edit";
178 $ewiki_plugins["action_always"]["links"] = "ewiki_page_links";
179 $ewiki_plugins["action"]["info"] = "ewiki_page_info";
180 $ewiki_plugins["action"]["view"] = "ewiki_page_view";
182 #-- helper vars ---------------------------------------------------
183 $ewiki_config["idf"]["url"] = array("http://", "mailto:", "internal://", "ftp://", "https://", "irc://", "telnet://", "news://", "chrome://", "file://", "gopher://", "httpz://");
184 $ewiki_config["idf"]["img"] = array(".jpeg", ".png", ".jpg", ".gif", ".j2k");
185 $ewiki_config["idf"]["obj"] = array(".swf", ".svg");
187 #-- entitle actions
188 $ewiki_config["action_links"]["view"] = @array_merge(array(
189 "edit" => "EDITTHISPAGE", # ewiki_t() is called on these
190 "links" => "BACKLINKS",
191 "info" => "PAGEHISTORY",
192 "like" => "LIKEPAGES",
193 ), @$ewiki_config["action_links"]["view"]
195 $ewiki_config["action_links"]["info"] = @array_merge(array(
196 "view" => "browse",
197 "edit" => "fetchback",
198 ), @$ewiki_config["action_links"]["info"]
201 #-- variable configuration settings (go into '$ewiki_config')
202 $ewiki_config_DEFAULTSTMP = array(
203 "edit_thank_you" => 1,
204 "edit_box_size" => "70x15",
205 "print_title" => EWIKI_PRINT_TITLE,
206 "split_title" => EWIKI_SPLIT_TITLE,
207 "control_line" => EWIKI_CONTROL_LINE,
208 "list_limit" => EWIKI_LIST_LIMIT,
209 "script" => EWIKI_SCRIPT,
210 "script_url" => (defined("EWIKI_SCRIPT_URL")?EWIKI_SCRIPT_URL:NULL),
211 "script_binary" => EWIKI_SCRIPT_BINARY,
212 #-- heart of the wiki -- don't try to read this! ;)
214 "wiki_pre_scan_regex" => '/
215 (?<![~!])
216 ((?:(?:\w+:)*['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2,}[\w\d]*)
217 |\^([-'.EWIKI_CHARS_L.EWIKI_CHARS_U.']{3,})
218 |\[ (?:"[^\]\"]+" | \s+ | [^:\]#]+\|)* ([^\|\"\[\]\#]+) (?:\s+ | "[^\]\"]+")* [\]\#]
219 |(\w{3,9}:\/\/[^?#\s\[\]\'\"\)\,<]+) /x',
221 "wiki_link_regex" => "\007 [!~]?(
222 \#?\[[^<>\[\]\n]+\] |
223 \^[-".EWIKI_CHARS_U.EWIKI_CHARS_L."]{3,} |
224 \b([\w]{3,}:)*([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}\#?[\w\d]* |
225 ([a-z]{2,9}://|mailto:)[^\s\[\]\'\"\)\,<]+ |
226 \w[-_.+\w]+@(\w[-_\w]+[.])+\w{2,} ) \007x",
228 #-- rendering ruleset
229 "wm_indent" => '<div style="margin-left:15px;" class="indent">',
230 "wm_table_defaults" => 'cellpadding="2" border="1" cellspacing="0"',
231 "wm_whole_line" => array(),
232 "htmlentities" => array(
233 "&" => "&amp;",
234 ">" => "&gt;",
235 "<" => "&lt;",
237 "wm_source" => array(
238 "%%%" => "<br />",
239 "\t" => " ",
240 "\n;:" => "\n ", # workaround, replaces the old ;:
242 "wm_list" => array(
243 "-" => array('ul type="square"', "", "li"),
244 "*" => array('ul type="circle"', "", "li"),
245 "#" => array("ol", "", "li"),
246 ":" => array("dl", "dt", "dd"),
247 #<out># ";" => array("dl", "dt", "dd"),
249 "wm_style" => array(
250 "'''''" => array("<b><i>", "</i></b>"),
251 "'''" => array("<b>", "</b>"),
252 "___" => array("<i><b>", "</b></i>"),
253 "''" => array("<em>", "</em>"),
254 "__" => array("<strong>", "</strong>"),
255 "^^" => array("<sup>", "</sup>"),
256 "==" => array("<tt>", "</tt>"),
257 #<off># "***" => array("<b><i>", "</i></b>"),
258 #<off># "###" => array("<big><b>", "</b></big>"),
259 "**" => array("<b>", "</b>"),
260 "##" => array("<big>", "</big>"),
261 "��" => array("<small>", "</small>"),
263 "wm_start_end" => array(
265 #-- rendering plugins
266 "format_block" => array(
267 "html" => array("&lt;html&gt;", "&lt;/html&gt;", "html", 0x0000),
268 "htm" => array("&lt;htm&gt;", "&lt;/htm&gt;", "html", 0x0003),
269 "code" => array("&lt;code&gt;", "&lt;/code&gt;", false, 0x0000),
270 "pre" => array("&lt;pre&gt;", "&lt;/pre&gt;", false, 0x003F),
271 "comment" => array("\n&lt;!--", "--&gt;", false, 0x0030),
272 # "verbatim" => array("&lt;verbatim&gt;", "&lt;/verbatim&gt;", false, 0x0000),
274 "format_params" => array(
275 "scan_links" => 1,
276 "html" => EWIKI_ALLOW_HTML,
277 "mpi" => 1,
280 foreach ($ewiki_config_DEFAULTSTMP as $set => $val) {
281 if (!isset($ewiki_config[$set])) {
282 $ewiki_config[$set] = $val;
284 elseif (is_array($val)) foreach ($val as $vali=>$valv) {
285 if (is_int($vali)) {
286 $ewiki_config[$set][] = $valv;
288 elseif (!isset($ewiki_config[$set][$vali])) {
289 $ewiki_config[$set][$vali] = $valv;
293 $ewiki_config_DEFAULTSTMP = $valv = $vali = $val = NULL;
295 #-- init stuff, autostarted parts
296 ksort($ewiki_plugins["init"]);
297 if ($pf_a = $ewiki_plugins["init"]) foreach ($pf_a as $pf) {
298 // Binary Handling starts here
299 #### MOODLE CHANGE TO BE COMPATIBLE WITH PHP 4.1
300 #if(headers_sent($file,$line)) {
301 # error("Headers already sent: $file:$line");
302 if(headers_sent()) {
303 error("Headers already sent.");
305 $pf($GLOBALS);
307 unset($ewiki_plugins["init"]);
309 #-- text (never remove the "C" or "en" sections!)
311 $ewiki_t["C"] = @array_merge(@$ewiki_t["C"], array(
312 "DATE" => "%a, %d %b %G %T %Z",
313 "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>',
316 $ewiki_t["en"] = @array_merge(@$ewiki_t["en"], array(
317 "EDITTHISPAGE" => "EditThisPage",
318 "APPENDTOPAGE" => "Add to",
319 "BACKLINKS" => "BackLinks",
320 "PAGESLINKINGTO" => "Pages linking to \$title",
321 "PAGEHISTORY" => "PageInfo",
322 "INFOABOUTPAGE" => "Information about page",
323 "LIKEPAGES" => "Pages like this",
324 "NEWESTPAGES" => "Newest Pages",
325 "LASTCHANGED" => "last changed on %c",
326 "DOESNOTEXIST" => "This page does not yet exist, please click on EditThisPage if you'd like to create it.",
327 "DISABLEDPAGE" => "This page is currently not available.",
328 "ERRVERSIONSAVE" => "Sorry, while you edited this page someone else
329 did already save a changed version. Please go back to the
330 previous screen and copy your changes to your computers
331 clipboard to insert it again after you reload the edit
332 screen.",
333 "ERRORSAVING" => "An error occoured while saving your changes. Please try again.",
334 "THANKSFORCONTRIBUTION" => "Thank you for your contribution!",
335 "CANNOTCHANGEPAGE" => "This page cannot be changed.",
336 "OLDVERCOMEBACK" => "Make this old version come back to replace the current one",
337 "PREVIEW" => "Preview",
338 "SAVE" => "Save",
339 "CANCEL_EDIT" => "CancelEditing",
340 "UPLOAD_PICTURE_BUTTON" => "upload picture &gt;&gt;&gt;",
341 "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GoodStyle\">GoodStyle</a> is to
342 write what comes to your mind. Don't care about how it
343 looks too much now. You can add <a href=\"".EWIKI_SCRIPT."WikiMarkup\">WikiMarkup</a>
344 also later if you think it is necessary.<br />",
345 "EDIT_FORM_2" => "<br />Please do not write things, which may make other
346 people angry. And please keep in mind that you are not all that
347 anonymous in the internet (find out more about your computers
348 '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' at Google).",
349 "BIN_IMGTOOLARGE" => "Image file is too large!",
350 "BIN_NOIMG" => "This is no image file (inacceptable file format)!",
351 "FORBIDDEN" => "You are not authorized to access this page.",
354 $ewiki_t["es"] = @array_merge(@$ewiki_t["es"], array(
355 "EDITTHISPAGE" => "EditarEstaP�gina",
356 "BACKLINKS" => "EnlacesInversos",
357 "PAGESLINKINGTO" => "P�ginas enlazando \$title",
358 "PAGEHISTORY" => "InfoP�gina",
359 "INFOABOUTPAGE" => "Informaci�n sobre la p�gina",
360 "LIKEPAGES" => "P�ginas como esta",
361 "NEWESTPAGES" => "P�ginas m�s nuevas",
362 "LASTCHANGED" => "�ltima modificaci�n %d/%m/%Y a las %H:%M",
363 "DOESNOTEXIST" => "Esta p�gina a�n no existe, por favor eliga EditarEstaP�gina si desea crearla.",
364 "DISABLEDPAGE" => "Esta p�gina no est� disponible en este momento.",
365 "ERRVERSIONSAVE" => "Disculpe, mientras editaba esta p�gina algui�n m�s
366 salv� una versi�n modificada. Por favor regrese a
367 a la pantalla anterior y copie sus cambios a su computador
368 para insertalos nuevamente despu�s de que cargue
369 la pantalla de edici�n.",
370 "ERRORSAVING" => "Ocurri� un error mientras se salvavan sus cambios. Por favor intente de nuevo.",
371 "THANKSFORCONTRIBUTION" => "Gracias por su contribuci�n!",
372 "CANNOTCHANGEPAGE" => "Esta p�gina no puede ser modificada.",
373 "OLDVERCOMEBACK" => "Hacer que esta versi�n antigua regrese a remplazar la actual",
374 "PREVIEW" => "Previsualizar",
375 "SAVE" => "Salvar",
376 "CANCEL_EDIT" => "CancelarEdici�n",
377 "UPLOAD_PICTURE_BUTTON" => "subir gr�fica &gt;&gt;&gt;",
378 "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."BuenEstilo\">BuenEstilo</a> es
379 escribir lo que viene a su mente. No se preocupe mucho
380 por la apariencia. Tambi�n puede agregar <a href=\"".EWIKI_SCRIPT."ReglasDeMarcadoWiki\">ReglasDeMarcadoWiki</a>
381 m�s adelante si piensa que es necesario.<br />",
382 "EDIT_FORM_2" => "<br />Por favor no escriba cosas, que puedan
383 enfadar a otras personas. Y por favor tenga en mente que
384 usted no es del todo an�nimo en Internet
385 (encuentre m�s sobre
386 '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' de su computador con Google).",
387 "BIN_IMGTOOLARGE" => "�La gr�fica es demasiado grande!",
388 "BIN_NOIMG" => "�No es un archivo con una gr�fica (formato de archivo inaceptable)!",
389 "FORBIDDEN" => "No est� autorizado para acceder a esta p�gina.",
392 $ewiki_t["de"] = @array_merge(@$ewiki_t["de"], array(
393 "EDITTHISPAGE" => "DieseSeite�ndern",
394 "APPENDTOPAGE" => "Erg�nze",
395 "BACKLINKS" => "Zur�ckLinks",
396 "PAGESLINKINGTO" => "Verweise zur Seite \$title",
397 "PAGEHISTORY" => "SeitenInfo",
398 "INFOABOUTPAGE" => "Informationen �ber Seite",
399 "LIKEPAGES" => "�hnliche Seiten",
400 "NEWESTPAGES" => "Neueste Seiten",
401 "LASTCHANGED" => "zuletzt ge�ndert am %d.%m.%Y um %H:%M",
402 "DISABLEDPAGE" => "Diese Seite kann momentan nicht angezeigt werden.",
403 "ERRVERSIONSAVE" => "Entschuldige, aber w�hrend Du an der Seite
404 gearbeitet hast, hat bereits jemand anders eine ge�nderte
405 Fassung gespeichert. Damit nichts verloren geht, browse bitte
406 zur�ck und speichere Deine �nderungen in der Zwischenablage
407 (Bearbeiten->Kopieren) um sie dann wieder an der richtigen
408 Stelle einzuf�gen, nachdem du die EditBoxSeite nocheinmal
409 geladen hast.<br />
410 Vielen Dank f�r Deine M�he.",
411 "ERRORSAVING" => "Beim Abspeichern ist ein Fehler aufgetreten. Bitte versuche es erneut.",
412 "THANKSFORCONTRIBUTION" => "Vielen Dank f�r Deinen Beitrag!",
413 "CANNOTCHANGEPAGE" => "Diese Seite kann nicht ge�ndert werden.",
414 "OLDVERCOMEBACK" => "Diese alte Version der Seite wieder zur Aktuellen machen",
415 "PREVIEW" => "Vorschau",
416 "SAVE" => "Speichern",
417 "CANCEL_EDIT" => "�nderungenVerwerfen",
418 "UPLOAD_PICTURE_BUTTON" => "Bild hochladen &gt;&gt;&gt;",
419 "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GuterStil\">GuterStil</a> ist es,
420 ganz einfach das zu schreiben, was einem gerade in den
421 Sinn kommt. Du solltest dich jetzt noch nicht so sehr
422 darum k�mmern, wie die Seite aussieht. Du kannst sp�ter
423 immernoch zur�ckkommen und den Text mit <a href=\"".EWIKI_SCRIPT."FormatierungsRegeln\">WikiTextFormatierungsRegeln</a>
424 aufputschen.<br />",
425 "EDIT_FORM_2" => "<br />Bitte schreib keine Dinge, die andere Leute
426 ver�rgern k�nnten. Und bedenke auch, da� es schnell auf
427 dich zur�ckfallen kann wenn du verschiedene andere Dinge sagst (mehr Informationen zur
428 '<a href=\"http://google.de/search?q=computer+IP+adresse\">IP Adresse</a>'
429 deines Computers findest du bei Google).",
432 #-- InterWiki:Links
433 $ewiki_config["interwiki"] = @array_merge(
434 @$ewiki_config["interwiki"],
435 array(
436 "javascript" => "", # this actually protects from javascript: links
437 "url" => "",
438 # "self" => "this",
439 "this" => EWIKI_SCRIPT, # better was absolute _URL to ewiki wrapper
440 "jump" => "",
441 "ErfurtWiki" => "http://erfurtwiki.sourceforge.net/?id=",
442 "InterWiki" => "InterWikiSearch",
443 "InterWikiSearch" => "http://sunir.org/apps/meta.pl?",
444 "Wiki" => "WardsWiki",
445 "WardsWiki" => "http://www.c2.com/cgi/wiki?",
446 "WikiFind" => "http://c2.com/cgi/wiki?FindPage&amp;value=",
447 "WikiPedia" => "http://www.wikipedia.com/wiki.cgi?",
448 "MeatBall" => "MeatballWiki",
449 "MeatballWiki" => "http://www.usemod.com/cgi-bin/mb.pl?",
450 "UseMod" => "http://www.usemod.com/cgi-bin/wiki.pl?",
451 "PhpWiki" => "http://phpwiki.sourceforge.net/phpwiki/index.php3?",
452 "LinuxWiki" => "http://linuxwiki.de/",
453 "OpenWiki" => "http://openwiki.com/?",
454 "Tavi" => "http://andstuff.org/tavi/",
455 "TWiki" => "http://twiki.sourceforge.net/cgi-bin/view/",
456 "MoinMoin" => "http://www.purl.net/wiki/moin/",
457 "Google" => "http://google.com/search?q=",
458 "ISBN" => "http://www.amazon.com/exec/obidos/ISBN=",
459 "icq" => "http://www.icq.com/",
466 #-------------------------------------------------------------------- main ---
468 /* this is the main function, which you should preferrably call to
469 integrate the ewiki into your web site; it chains to most other
470 parts and plugins (including the edit box);
471 if you do not supply the requested pages "$id" we will fetch it
472 from the pre-defined possible URL parameters.
474 function ewiki_page($id=false) {
476 global $ewiki_links, $ewiki_plugins, $ewiki_ring, $ewiki_t, $ewiki_errmsg;
477 #-- output var
478 $o = "";
480 #-- selected page
481 if (!isset($_REQUEST)) {
482 $_REQUEST = @array_merge($_GET, $_POST);
484 if (!strlen($id)) {
485 $id = ewiki_id();
487 $id = format_string($id,true);
488 #-- page action
489 $action = EWIKI_DEFAULT_ACTION;
490 if ($delim = strpos($id, EWIKI_ACTION_SEP_CHAR)) {
491 $action = substr($id, 0, $delim);
492 $id = substr($id, $delim + 1);
494 elseif (EWIKI_USE_ACTION_PARAM && isset($_REQUEST["action"])) {
495 $action = $_REQUEST["action"];
497 $GLOBALS["ewiki_id"] = $id;
498 $GLOBALS["ewiki_title"] = ewiki_split_title($id);
499 $GLOBALS["ewiki_action"] = $action;
501 #-- fetch from db
502 $dquery = array(
503 "id" => $id
505 if (!isset($_REQUEST["content"]) && ($dquery["version"] = @$_REQUEST["version"])) {
506 $dquery["forced_version"] = $dquery["version"];
508 $data = @array_merge($dquery, ewiki_database("GET", $dquery));
510 #-- stop here if page is not marked as _TEXT,
511 # perform authentication then, and let only administrators proceed
512 if (!empty($data["flags"]) && (($data["flags"] & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT)) {
513 if (($data["flags"] & EWIKI_DB_F_BINARY) && ($pf = $ewiki_plugins["handler_binary"][0])) {
514 return($pf($id, $data, $action)); //_BINARY entries handled separately
516 elseif (!EWIKI_PROTECTED_MODE || !ewiki_auth($id, $data, $action, 0, 1) && ($ewiki_ring!=0)) {
517 return(ewiki_t("DISABLEDPAGE"));
521 #-- pre-check if actions exist
522 $pf_page = ewiki_array($ewiki_plugins["page"], $id);
524 #-- edit <form> for non-existent pages
525 if (($action==EWIKI_DEFAULT_ACTION) && empty($data["content"]) && empty($pf_page)) {
526 if (EWIKI_AUTO_EDIT) {
527 $action = "edit";
529 else {
530 $data["content"] = ewiki_t("DOESNOTEXIST");
533 #-- more initialization
534 if ($pf_a = @$ewiki_plugins["page_init"]) {
535 ksort($pf_a);
536 foreach ($pf_a as $pf) {
537 $o .= $pf($id, $data, $action);
539 unset($ewiki_plugins["page_init"]);
541 $pf_page = ewiki_array($ewiki_plugins["page"], $id);
543 #-- require auth
544 if (EWIKI_PROTECTED_MODE) {
545 if (!ewiki_auth($id, $data, $action, $ring=false, $force=EWIKI_AUTO_LOGIN)) {
546 return($o.=$ewiki_errmsg);
550 #-- handlers
551 $handler_o = "";
552 if ($pf_a = @$ewiki_plugins["handler"]) {
553 ksort($pf_a);
554 foreach ($pf_a as $pf) {
555 if ($handler_o = $pf($id, $data, $action)) { break; }
558 #-- finished by handler
559 if ($handler_o) {
560 $o .= $handler_o;
562 #-- actions that also work for static and internal pages
563 elseif (($pf = @$ewiki_plugins["action_always"][$action]) && function_exists($pf)) {
564 $o .= $pf($id, $data, $action);
566 #-- internal pages
567 elseif ($pf_page && function_exists($pf_page)) {
568 $o .= $pf_page($id, $data, $action);
570 #-- page actions
571 else {
572 $pf = @$ewiki_plugins["action"][$action];
574 #-- fallback to "view" action
575 if (empty($pf) || !function_exists($pf)) {
577 $pf = "ewiki_page_view";
578 $action = "view"; // we could also allow different (this is a
579 // catch-all) view variants, but this would lead to some problems
582 $o .= $pf($id, $data, $action);
585 #-- error instead of page?
586 if (empty($o) && $ewiki_errmsg) {
587 $o = $ewiki_errmsg;
590 #-- html post processing
591 if ($pf_a = $ewiki_plugins["page_final"]) {
592 ksort($pf_a);
593 foreach ($pf_a as $pf) {
594 $pf($o, $id, $data, $action);
598 (EWIKI_ESCAPE_AT) && ($o = str_replace("@", "&#x40;", $o));
600 return($o);
605 #-- HTTP meta headers
606 function ewiki_http_headers(&$o, $id, &$data, $action) {
607 global $ewiki_t;
608 if (EWIKI_HTTP_HEADERS && !headers_sent()) {
609 if (!empty($data)) {
610 if ($uu = @$data["id"]) @header('Content-Disposition: inline; filename="' . urlencode($uu) . '.html"');
611 if ($uu = @$data["version"]) @header('Content-Version: ' . $uu);
612 if ($uu = @$data["lastmodified"]) @header('Last-Modified: ' . gmstrftime($ewiki_t["C"]["DATE"], $uu));
614 if (EWIKI_NO_CACHE) {
615 header('Expires: ' . gmstrftime($ewiki_t["C"]["DATE"], UNIX_MILLENNIUM));
616 header('Pragma: no-cache');
617 header('Cache-Control: no-cache, private, must-revalidate');
618 # change to "C-C: cache, must-revalidate" ??
619 # private only for authenticated users / _PROT_MODE
621 #-- ETag
622 if ($data["version"] && ($etag=ewiki_etag($data)) || ($etag=md5($o))) {
623 $weak = "W/" . urlencode($id) . "." . $data["version"];
624 header("ETag: \"$etag\""); ###, \"$weak\"");
628 function ewiki_etag(&$data) {
629 return( urlencode($data["id"]) . ":" . dechex($data["version"]) . ":ewiki:" .
630 dechex(crc32($data["content"]) & 0x7FFFBFFF) );
635 #-- encloses whole page output with a descriptive <div>
636 function ewiki_page_css_container(&$o, &$id, &$data, &$action) {
637 $o = "<div class=\"wiki $action "
638 . strtr($id, ' ./ --_!"�$%&()=?��{[]}`+#*;:,<>| @�������ߤ^���\'\\',
639 '- -----------------------------------------------')
640 . "\">\n"
641 . $o . "\n</div>\n";
646 function ewiki_split_title ($id='', $split=EWIKI_SPLIT_TITLE, $entities=1) {
647 strlen($id) or ($id = $GLOBALS["ewiki_id"]);
648 if ($split) {
649 $id = preg_replace("/([".EWIKI_CHARS_L."])([".EWIKI_CHARS_U."]+)/", "$1 $2", $id);
651 return($entities ? s($id) : $id);
656 function ewiki_add_title(&$html, $id, &$data, $action, $go_action="links") {
657 $html = ewiki_make_title($id, '', 1, $action, $go_action) . $html;
661 function ewiki_make_title($id='', $title='', $class=3, $action="view", $go_action="links", $may_split=1) {
663 global $ewiki_config, $ewiki_plugins, $ewiki_title, $ewiki_id;
665 #-- advanced handler
666 if ($pf = @$ewiki_plugins["make_title"][0]) {
667 return($pf($title, $class, $action, $go_action, $may_split));
669 #-- disabled
670 elseif (!$ewiki_config["print_title"]) {
671 return("");
674 #-- get id
675 if (empty($id)) {
676 $id = $ewiki_id;
679 #-- get title
680 if (!strlen($title)) {
681 $title = $ewiki_title; // already in &html; format
683 elseif ($ewiki_config["split_title"] && $may_split) {
684 $title = ewiki_split_title($title, $ewiki_config["split_title"], 0&($title!=$ewiki_title));
686 else {
687 $title = s($title);
690 #-- title mangling
691 if ($pf_a = @$ewiki_plugins["title_transform"]) {
692 foreach ($pf_a as $pf) { $pf($id, $title, $go_action); }
695 #-- clickable link or simple headline
696 if ($class <= $ewiki_config["print_title"]) {
697 if ($uu = @$ewiki_config["link_title_action"][$action]) {
698 $go_action = $uu;
700 if ($uu = @$ewiki_config["link_title_url"]) {
701 $href = $uu;
702 unset($ewiki_config["link_title_url"]);
704 else {
705 $href = ewiki_script($go_action, $id);
707 $o = '<a href="' . $href . '">' . ($title) . '</a>';
709 else {
710 $o = $title;
713 return('<h2 class="page title">' . $o . '</h2>'."\n");
719 function ewiki_page_view($id, &$data, $action, $all=1) {
721 global $ewiki_plugins, $ewiki_config;
722 $o = "";
724 #-- render requested wiki page <-- goal !!!
725 $render_args = array(
726 "scan_links" => 1,
727 "html" => (EWIKI_ALLOW_HTML||(@$data["flags"]&EWIKI_DB_F_HTML)),
729 $o .= $ewiki_plugins["render"][0] ($data["content"], $render_args);
730 if (!$all) {
731 return($o);
733 #### MOODLE CHANGE
734 /// Add Moodle filters to text porion of wiki.
735 global $moodle_format; // from wiki/view.php
736 $o = format_text($o, $moodle_format);
737 $o.= "<br /><br />";
739 #-- control line + other per-page info stuff
740 if ($pf_a = $ewiki_plugins["view_append"]) {
741 ksort($pf_a);
742 foreach ($pf_a as $n => $pf) { $o .= $pf($id, $data, $action); }
744 if ($pf_a = $ewiki_plugins["view_final"]) {
745 ksort($pf_a);
746 foreach ($pf_a as $n => $pf) { $pf($o, $id, $data, $action); }
749 if (!empty($_REQUEST["thankyou"]) && $ewiki_config["edit_thank_you"]) {
750 $o = ewiki_t("THANKSFORCONTRIBUTION") . $o;
754 if (EWIKI_HIT_COUNTING) {
755 ewiki_database("HIT", $data);
758 return($o);
764 #-------------------------------------------------------------------- util ---
767 /* retrieves "$id/$action" string from URL / QueryString / PathInfo,
768 change this in conjunction with ewiki_script() to customize your URLs
769 further whenever desired
771 function ewiki_id() {
772 ($id = @$_REQUEST["id"]) or
773 ($id = @$_REQUEST["name"]) or
774 ($id = @$_REQUEST["page"]) or
775 ($id = @$_REQUEST["file"]) or
776 (EWIKI_USE_PATH_INFO) and ($id = ltrim(@$_SERVER["PATH_INFO"], "/")) or
777 (!isset($_REQUEST["id"])) and ($id = trim(strtok($_SERVER["QUERY_STRING"], "&")));
778 if (!strlen($id) || ($id=="id=")) {
779 $id = EWIKI_PAGE_INDEX;
781 (EWIKI_URLDECODE) && ($id = urldecode($id));
782 return($id);
788 /* replaces EWIKI_SCRIPT, works more sophisticated, and
789 bypasses various design flaws
790 - if only the first parameter is used (old style), it can contain
791 a complete "action/WikiPage" - but this is ambigutious
792 - else $asid is the action, and $id contains the WikiPageName
793 - $ewiki_config["script"] will now be used in favour of the constant
794 - needs more work on _BINARY, should be a separate function
796 ## MOODLE-CHANGE: $asid="", Knows the devil why....
797 function ewiki_script($asid="", $id=false, $params="", $bin=0, $html=1, $script=NULL) {
798 global $ewiki_config, $ewiki_plugins;
800 #-- get base script url from config vars
801 if (empty($script)) {
802 $script = &$ewiki_config[!$bin?"script":"script_binary"];
806 #-- separate $action and $id for old style requests
807 if ($id === false) {
808 if (strpos($asid, EWIKI_ACTION_SEP_CHAR) !== false) {
809 $asid = strtok($asid, EWIKI_ACTION_SEP_CHAR);
810 $id = strtok("\000");
812 else {
813 $id = $asid;
814 $asid = "";
818 #-- prepare params
819 if (is_array($params)) {
820 $uu = $params;
821 $params = "";
822 if ($uu) foreach ($uu as $k=>$v) {
823 $params .= (strlen($params)?"&":"") . rawurlencode($k) . "=" . rawurlencode($v);
826 #-- action= parameter
827 if (EWIKI_USE_ACTION_PARAM >= 2) {
828 $params = "action=$asid" . (strlen($params)?"&":"") . $params;
829 $asid = "";
832 #-- workaround slashes in $id
833 if (empty($asid) && (strpos($id, EWIKI_ACTION_SEP_CHAR) !== false) && !$bin) {
834 $asid = "view";
836 /*paranoia*/ $asid = trim($asid, EWIKI_ACTION_SEP_CHAR);
838 #-- make url
839 if (EWIKI_URLENCODE) {
840 $id = urlencode($id);
841 $asid = urlencode($asid);
843 else {
844 # only urlencode &, %, ? for example
846 $url = $script;
847 if ($asid) {
848 $id = $asid . EWIKI_ACTION_SEP_CHAR . $id; #= "action/PageName"
850 if (strpos($url, "%s") !== false) {
851 $url = str_replace("%s", $id, $url);
853 else {
854 $url .= $id;
857 #-- add url params
858 if (strlen($params)) {
859 $url .= (strpos($url,"?")!==false ? "&":"?") . $params;
862 #-- fin
863 if ($html) {
864 //Don't replace & if it's part of encoded character (bug 2209)
865 $url = preg_replace("/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/","&amp;", $url);
866 } else {
867 //This is going to be used in some header or meta redirect, so It cannot use &amp; (bug 2620)
868 $url = preg_replace('/&amp;/', '&', $url);
870 return($url);
874 /* this ewiki_script() wrapper is used to generate URLs to binary
875 content in the ewiki database
877 function ewiki_script_binary($asid, $id=false, $params=array(), $upload=0) {
879 $upload |= is_string($params) && strlen($params) || count($params);
881 #-- generate URL directly to the plainly saved data file,
882 # see also plugins/binary_store
884 if (defined("EWIKI_DB_STORE_URL") && !$upload) {
885 $url = EWIKI_DB_STORE_URL . rawurlencode($id);
888 #-- else get standard URL (thru ewiki.php) from ewiki_script()
889 else {
890 $url = ewiki_script($asid, $id, $params, "_BINARY=1");
893 return($url);
897 /* this function returns the absolute ewiki_script url, if EWIKI_SCRIPT_URL
898 is set, else it guesses the value
900 function ewiki_script_url() {
902 global $ewiki_action, $ewiki_id, $ewiki_config;
904 $scr_template = $ewiki_config["script"];
905 $scr_current = ewiki_script($ewiki_action, $ewiki_id);
906 $req_uri = $_SERVER["REQUEST_URI"];
908 if ($url = $ewiki_config["script_url"]) {
909 return($url);
911 elseif (strpos($req_uri, $scr_current) !== false) {
912 $url = str_replace($req_uri, $scr_current, $scr_template);
914 elseif (strpos($req_uri, "?") && (strpos($scr_template, "?") !== false)) {
915 $url = substr($req_uri, 0, strpos($req_uri, "?"))
916 . substr($scr_template, strpos($scr_template, "?"));
918 elseif (strpos($req_uri, $sn = $_SERVER["SCRIPT_NAME"])) {
919 $url = $sn . "?id=";
921 else {
922 return(NULL); #-- could not guess it
925 #$url = "http://" . $_SERVER["SERVER_NAME"] . $url;
926 return($url);
932 #------------------------------------------------------------ page plugins ---
936 function ewiki_page_links($id, &$data, $action) {
937 $o = ewiki_make_title($id, ewiki_t("PAGESLINKINGTO", array("title"=>$id)), 1, $action, "", "_MAY_SPLIT=1");
938 if ($pages = ewiki_get_backlinks($id)) {
939 $o .= ewiki_list_pages($pages);
940 } else {
941 $o .= ewiki_t("This page isn't linked from anywhere else.");
943 return($o);
946 function ewiki_get_backlinks($id) {
947 $result = ewiki_database("SEARCH", array("refs" => $id));
948 $pages = array();
949 while ($row = $result->get(0, 0x0020)) {
950 if ( strpos($row["refs"], "\n$id\n") !== false) {
951 $pages[] = $row["id"];
954 return($pages);
957 function ewiki_get_links($id) {
958 if ($data = ewiki_database("GET", array("id"=>$id))) {
959 $refs = explode("\n", trim($data["refs"]));
960 $r = array();
961 foreach (ewiki_database("FIND", $refs) as $id=>$exists) {
962 if ($exists) {
963 $r[] = $id;
966 return($r);
971 function ewiki_list_pages($pages=array(), $limit=EWIKI_LIST_LIMIT,
972 $value_as_title=0, $pf_list=false)
974 global $ewiki_plugins;
975 $o = "";
977 $is_num = !empty($pages[0]);
978 $lines = array();
979 $n = 0;
981 foreach ($pages as $id=>$add_text) {
983 $title = $id;
984 $params = "";
986 if (is_array($add_text)) {
987 list($id, $params, $title, $add_text) = $add_text;
989 elseif ($is_num) {
990 $id = $title = $add_text;
991 $add_text = "";
993 elseif ($value_as_title) {
994 $title = $add_text;
995 $add_text = "";
998 $lines[] = '<a href="' . ewiki_script("", $id, $params) . '">' . s($title) . '</a> ' . $add_text;
1000 if (($limit > 0) && ($n++ >= $limit)) {
1001 break;
1005 if ($pf_a = @$ewiki_plugins["list_transform"])
1006 foreach ($pf_a as $pf_transform) {
1007 $pf_transform($lines);
1010 if (($pf_list) || ($pf_list = @$ewiki_plugins["list_pages"][0])) {
1011 $o = $pf_list($lines);
1013 elseif($lines) {
1014 $o = "&middot; " . implode("<br />\n&middot; ", $lines) . "<br />\n";
1017 return($o);
1023 function ewiki_page_ordered_list($orderby="created", $asc=0, $print, $title) {
1025 $o = ewiki_make_title("", $title, 2, ".list", "links", 0);
1027 $sorted = array();
1028 $result = ewiki_database("GETALL", array($orderby));
1030 while ($row = $result->get()) {
1031 $row = ewiki_database("GET", array(
1032 "id" => $row["id"],
1033 ($asc >= 0 ? "version" : "uu") => 1 // version 1 is most accurate for {hits}
1035 #-- text page?
1036 if (EWIKI_DB_F_TEXT == ($row["flags"] & EWIKI_DB_F_TYPE)) {
1037 #-- viewing allowed?
1038 if (!EWIKI_PROTECTED_MODE || !EWIKI_PROTECTED_MODE_HIDING || ewiki_auth($row["id"], $row, "view")) {
1039 $sorted[$row["id"]] = $row[$orderby];
1044 if ($asc != 0) { arsort($sorted); }
1045 else { asort($sorted); }
1047 foreach ($sorted as $name => $value) {
1048 if (empty($value)) { $value = "0"; }
1049 ##### BEGIN MOODLE ADDITION #####
1050 #$sorted[$name] = strftime(str_replace('%n', $value, $print), $value);
1051 if($print=="LASTCHANGED") {
1052 $value=strftime("%c",$value);
1054 $sorted[$name] = get_string(strtolower($print),"wiki",$value);
1055 ##### BEGIN MOODLE ADDITION #####
1057 $o .= ewiki_list_pages($sorted);
1059 return($o);
1064 function ewiki_page_newest($id=0, $data=0) {
1065 return( ewiki_page_ordered_list("created", 1, "LASTCHANGED", ewiki_t("NEWESTPAGES")) );
1068 function ewiki_page_updates($id=0, $data=0) {
1069 return( ewiki_page_ordered_list("lastmodified", -1, "LASTCHANGED", EWIKI_PAGE_UPDATES) );
1072 function ewiki_page_hits($id=0, $data=0) {
1073 ##### BEGIN MOODLE ADDITION #####
1074 return( ewiki_page_ordered_list("hits", 1, "hits", EWIKI_PAGE_HITS) );
1077 function ewiki_page_versions($id=0, $data=0) {
1078 return( ewiki_page_ordered_list("version", -1, "changes", EWIKI_PAGE_VERSIONS) );
1079 ##### END MOODLE ADDITION #####
1088 function ewiki_page_search($id, &$data, $action) {
1090 global $CFG;
1092 $o = ewiki_make_title($id, $id, 2, $action);
1094 if (! ($q = @$_REQUEST["q"])) {
1096 $o .= '<form action="' . ewiki_script("", $id) . '" method="post">';
1097 $o .= '<fieldset class="invisiblefieldset">';
1098 $o .= '<input name="q" size="30" /><br /><br />';
1099 $o .= '<input type="submit" value="'.$id.'" />';
1100 $o .= '</fieldset>';
1101 $o .= '</form>';
1103 else {
1104 $found = array();
1106 if ($CFG->unicodedb) {
1107 $q = preg_replace('/\s*[\W]+\s*/u', ' ', $q);
1108 } else {
1109 $q = preg_replace('/\s*[^\w]+\s*/', ' ', $q);
1111 foreach (explode(" ", $q) as $search) {
1113 if (empty($search)) { continue; }
1115 $result = ewiki_database("SEARCH", array("content" => $search));
1117 while ($row = $result->get()) {
1119 #-- show this entry in page listings?
1120 if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $row, "view")) {
1121 continue;
1124 $found[] = $row["id"];
1128 $o .= ewiki_list_pages($found);
1131 return($o);
1141 function ewiki_page_info($id, &$data, $action) {
1143 global $ewiki_plugins, $ewiki_config, $ewiki_links;
1144 global $CFG, $course; // MOODLE HACK
1146 $o = ewiki_make_title($id, ewiki_t("INFOABOUTPAGE")." '{$id}'", 2, $action,"", "_MAY_SPLIT=1");
1148 $flagnames = array(
1149 "TEXT", "BIN", "DISABLED", "HTML", "READONLY", "WRITEABLE",
1150 "APPENDONLY", "SYSTEM",
1152 $show = array(
1153 "version", "author", "userid", "created",
1154 "lastmodified", "refs",
1155 "flags", "meta", "content"
1158 #-- versions to show
1159 $v_start = $data["version"];
1160 if ( ($uu=@$_REQUEST[EWIKI_UP_PAGENUM]) && ($uu<=$v_start) ) {
1161 $v_start = $uu;
1163 $v_end = $v_start - $ewiki_config["list_limit"] + 1;
1164 if ( ($uu=@$_REQUEST[EWIKI_UP_PAGEEND]) && ($uu<=$v_start) ) {
1165 $v_end = $uu;
1167 $v_end = max($v_end, 1);
1169 #-- go
1170 # the very ($first) entry is rendered more verbosely than the others
1171 for ($v=$v_start,$first=1; ($v>=$v_end); $v--,$first=0) {
1173 $current = ewiki_database("GET", array("id"=>$id, "version"=>$v));
1175 if (!strlen(trim($current["id"])) || !$current["version"] || !strlen(trim($current["content"]))) {
1176 continue;
1179 $o .= '<table class="version-info" cellpadding="2" cellspacing="1">' . "\n";
1181 #-- additional info-actions
1182 $commands = '';
1183 foreach ($ewiki_config["action_links"]["info"] as $thisaction=>$title)
1184 if (@$ewiki_plugins["action"][$thisaction] || @$ewiki_plugins["action_always"][$thisaction]) {
1185 ##### BEGIN MOODLE ADDITION #####
1186 if ($commands) {
1187 $commands .= '&nbsp;&nbsp;';
1189 $commands .= '<a href="' .
1190 ewiki_script($thisaction, $id, array("version"=>$current["version"])) .
1191 '">' . get_string($title,"wiki") . '</a>';
1192 ##### END MOODLE ADDITION #####
1195 #-- print page database entry
1196 foreach($show as $i) {
1198 $value = @$current[$i];
1200 #-- show database {fields} differently
1201 if ($i == "meta") {
1202 continue; // MOODLE DOESN'T USE IT
1203 $str = "";
1204 if ($first && $value) { foreach ($value as $n=>$d) {
1205 $str .= s("$n: $d") . "<br />\n";
1207 $value = $str;
1209 elseif ($value >= UNIX_MILLENNIUM) { #-- {lastmodified}, {created}
1210 #### BEGIN MOODLE CHANGE
1211 $value=userdate($value);
1212 #$value = strftime("%c", $value);
1213 #### END MOODLE CHANGE
1215 elseif ($i == "content") {
1216 continue; // MOODLE DOESN'T CARE
1217 $value = strlen(trim($value)) . " bytes";
1218 $i = "content size";
1220 elseif ($first && ($i == "refs") && !(EWIKI_PROTECTED_MODE && (EWIKI_PROTECTED_MODE_HIDING>=2))) {
1221 $a = explode("\n", trim($value));
1222 $ewiki_links = ewiki_database("FIND", $a);
1223 ewiki_merge_links($ewiki_links);
1224 foreach ($a as $n=>$link) {
1225 $a[$n] = ewiki_link_regex_callback(array("$link"), "force_noimg");
1227 $value = trim(implode(", ", $a));
1228 if (!$value) {
1229 continue;
1232 elseif (strpos($value, "\n") !== false) { #-- also for {refs}
1233 $value = str_replace("\n", ", ", trim($value));
1234 if (!$value) {
1235 continue;
1238 elseif ($i == "version") {
1239 $value = '<a href="' .
1240 ewiki_script("", $id, array("version"=>$value)) . '">' .
1241 $value . '</a> '."($commands)";
1243 elseif ($i == "flags") {
1244 continue; // MOODLE DOESN'T USE IT
1245 $fstr = "";
1246 for ($n = 0; $n < 32; $n++) {
1247 if ($value & (1 << $n)) {
1248 if (! ($s=$flagnames[$n])) { $s = "UU$n"; }
1249 $fstr .= $s . " ";
1252 $value = $fstr;
1254 elseif ($i == "author") {
1255 continue;
1256 $ewiki_links=1;
1257 $value = preg_replace_callback("/((\w+:)?([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}[\w\d]*)/", "ewiki_link_regex_callback", $value);
1259 elseif ($i == "userid") {
1260 $i = 'author';
1261 if ($user = get_record('user', 'id', $value)) {
1262 if (!isset($course->id)) {
1263 $course->id = 1;
1265 $picture = print_user_picture($user->id, $course->id, $user->picture, false, true, true);
1266 $value = $picture." <a href=\"$CFG->wwwroot/user/view.php?id=$user->id&amp;course=$course->id\">".fullname($user)."</a>";
1267 } else {
1268 continue;
1269 //$value = @$current['author'];
1273 ##### BEGIN MOODLE ADDITION #####
1274 $o .= '<tr class="page-'.$i.'"><td style="vertical-align:top;text-align:right;white-space: nowrap;"><b>' .ewiki_t($i). ':</b></td>' .
1275 '<td>' . $value . "</td></tr>\n";
1276 ##### END MOODLE ADDITION #####
1280 $o .= "</table><br /><br />\n";
1284 #-- page result split
1285 if ($v >= 1) {
1286 $o .= "<br />\n".get_string('showversions','wiki').' '.ewiki_chunked_page($action, $id, -1, $v, 1, 0, 0) . "\n <br />";
1289 return($o);
1295 function ewiki_chunked_page($action, $id, $dir=-1, $start=10, $end=1, $limit=0, $overlap=0.25, $collapse_last=0.67) {
1297 global $ewiki_config;
1299 if (empty($limit)) {
1300 $limit = $ewiki_config["list_limit"];
1302 if ($overlap < 1) {
1303 $overlap = (int) ($limit * $overlap);
1306 $p = "";
1307 $n = $start;
1309 while ($n) {
1311 $n -= $dir * $overlap;
1313 $e = $n + $dir * ($limit + $overlap) + 1;
1315 if ($dir<0) {
1316 $e = max(1, $e);
1317 if ($e <= $collapse_last * $limit) {
1318 $e = 1;
1321 else {
1322 $e = min($end, $e);
1323 if ($e >= $collapse_last * $limit) {
1324 $e = $end;
1328 $o .= ($o?" &middot; ":"")
1329 . '<a href="'.ewiki_script($action, $id, array(EWIKI_UP_PAGENUM=>$n, EWIKI_UP_PAGEEND=>$e))
1330 . '">'. "$n-$e" . '</a>';
1332 if (($n=$e-1) < $end) {
1333 $n = false;
1337 return('<span class="chunked-result">'. $o .'</span>');
1345 function ewiki_page_edit($id, $data, $action) {
1347 global $ewiki_links, $ewiki_author, $ewiki_plugins, $ewiki_ring, $ewiki_errmsg;
1349 $hidden_postdata = array();
1351 #-- previous version come back
1352 if (@$data["forced_version"]) {
1354 $current = ewiki_database("GET", array("id"=>$id));
1355 $data["version"] = $current["version"];
1356 unset($current);
1358 unset($_REQUEST["content"]);
1359 unset($_REQUEST["version"]);
1362 #-- edit hacks
1363 if ($pf_a = @$ewiki_plugins["edit_hook"]) foreach ($pf_a as $pf) {
1364 if ($output = $pf($id, $data, $hidden_postdata)) {
1365 return($output);
1369 #-- permission checks
1370 if (isset($ewiki_ring)) {
1371 $ring = $ewiki_ring;
1372 } else {
1373 $ring = 3;
1375 $flags = @$data["flags"];
1376 if (!($flags & EWIKI_DB_F_WRITEABLE)) {
1378 #-- perform auth
1379 $edit_ring = (EWIKI_PROTECTED_MODE>=2) ? (2) : (NULL);
1380 if (EWIKI_PROTECTED_MODE && !ewiki_auth($id, $data, $action, $edit_ring, "FORCE")) {
1381 return($ewiki_errmsg);
1384 #-- flag checking
1385 if (($flags & EWIKI_DB_F_READONLY) and ($ring >= 2)) {
1386 return(ewiki_t("CANNOTCHANGEPAGE"));
1388 if (($flags) and (($flags & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT) and ($ring >= 1)) {
1389 return(ewiki_t("CANNOTCHANGEPAGE"));
1393 #-- "Edit Me"
1394 $o = ewiki_make_title($id, ewiki_t("EDITTHISPAGE").(" '{$id}'"), 2, $action, "", "_MAY_SPLIT=1");
1396 #-- preview
1397 if (isset($_REQUEST["preview"])) {
1398 $o .= $ewiki_plugins["edit_preview"][0]($data);
1401 #-- save
1402 if (isset($_REQUEST["save"])) {
1405 #-- normalize to UNIX newlines
1406 $_REQUEST["content"] = str_replace("\015\012", "\012", $_REQUEST["content"]);
1407 $_REQUEST["content"] = str_replace("\015", "\012", $_REQUEST["content"]);
1409 #-- check for concurrent version saving
1410 $error = 0;
1411 if ((@$data["version"] >= 1) && ($data["version"] != @$_REQUEST["version"]) || (@$_REQUEST["version"] < 1)) {
1413 $pf = $ewiki_plugins["edit_patch"][0];
1415 if (!$pf || !$pf($id, $data)) {
1416 $error = 1;
1417 $o .= ewiki_t("ERRVERSIONSAVE") . "<br /><br />";
1421 if (!$error) {
1423 #-- new pages` flags
1424 if (! ($set_flags = @$data["flags"] & EWIKI_DB_F_COPYMASK)) {
1425 $set_flags = 1;
1427 if (EWIKI_ALLOW_HTML) {
1428 $set_flags |= EWIKI_DB_F_HTML;
1431 #-- mk db entry
1432 $save = array(
1433 "id" => $id,
1434 "version" => @$data["version"] + 1,
1435 "flags" => $set_flags,
1436 "content" => $_REQUEST["content"],
1437 "created" => ($uu=@$data["created"]) ? $uu : time(),
1438 "meta" => ($uu=@$data["meta"]) ? $uu : "",
1439 "hits" => ($uu=@$data["hits"]) ? $uu : "0",
1441 ewiki_data_update($save);
1443 #-- edit storage hooks
1444 if ($pf_a = @$ewiki_plugins["edit_save"]) {
1445 foreach ($pf_a as $pf) {
1446 $pf($save, $data);
1450 #-- save
1451 if (!$save || !ewiki_database("WRITE", $save)) {
1453 $o .= $ewiki_errmsg ? $ewiki_errmsg : ewiki_t("ERRORSAVING");
1456 else {
1457 #-- prevent double saving, when ewiki_page() is re-called
1458 $_REQUEST = $_GET = $_POST = array();
1460 $o = ewiki_t("THANKSFORCONTRIBUTION") . "<br /><br />";
1461 $o .= ewiki_page($id);
1463 if (EWIKI_EDIT_REDIRECT) {
1464 $url = ewiki_script("", $id, "thankyou=1", 0, 0, EWIKI_HTTP_HEADERS?ewiki_script_url():0);
1466 if (EWIKI_HTTP_HEADERS && !headers_sent()) {
1467 header("Status: 303 Redirect for GET");
1468 header("Location: $url");
1469 #header("URI: $url");
1470 #header("Refresh: 0; URL=$url");
1472 else {
1473 $o .= '<meta http-equiv="Refresh" content="0; URL='.s($url).'">';
1481 //@REWORK
1482 // header("Reload-Location: " . ewiki_script("", $id, "", 0, 0, ewiki_script_url()) );
1485 else {
1486 #-- Edit <form>
1487 $o .= ewiki_page_edit_form($id, $data, $hidden_postdata);
1489 #-- additional forms
1490 if ($pf_a = $ewiki_plugins["edit_form_final"]) foreach ($pf_a as $pf) {
1491 $pf($o, $id, $data, $action);
1495 return($o);
1499 function ewiki_data_update(&$data, $author="") {
1500 global $USER, $ewiki_links;
1502 #-- add backlinks entry
1503 ewiki_scan_wikiwords($data["content"], $ewiki_links, "_STRIP_EMAIL=1");
1504 $data["refs"] = "\n\n".implode("\n", array_keys($ewiki_links))."\n\n";
1505 $data["lastmodified"] = time();
1506 $data["author"] = ewiki_author($author);
1507 if (isset($USER->id)) {
1508 $data["userid"] = $USER->id;
1514 #-- edit <textarea>
1515 function ewiki_page_edit_form(&$id, &$data, &$hidden_postdata) {
1516 global $ewiki_plugins, $ewiki_config, $moodle_format;
1518 $o='';
1520 #-- previously edited, or db fetched content
1521 if (@$_REQUEST["content"] || @$_REQUEST["version"]) {
1522 $data = array(
1523 "version" => &$_REQUEST["version"],
1524 "content" => &$_REQUEST["content"]
1527 else {
1528 if (empty($data["version"])) {
1529 $data["version"] = 1;
1531 @$data["content"] .= "";
1534 #-- normalize to DOS newlines
1535 $data["content"] = str_replace("\015\012", "\012", $data["content"]);
1536 $data["content"] = str_replace("\015", "\012", $data["content"]);
1537 $data["content"] = str_replace("\012", "\015\012", $data["content"]);
1539 $hidden_postdata["version"] = &$data["version"];
1541 #-- edit textarea/form
1542 // deleted name="ewiki", can not find the reference, and it's breaking xhtml
1543 $o .= ewiki_t("EDIT_FORM_1")
1544 . '<form method="post" enctype="multipart/form-data" action="'
1545 . ewiki_script("edit", $id) . '" '
1546 . ' accept-charset="'.EWIKI_CHARSET.'">' . "\n";
1547 $o .= '<div>';
1548 #-- additional POST vars
1549 foreach ($hidden_postdata as $name => $value) {
1550 $o .= '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
1553 ($cols = strtok($ewiki_config["edit_box_size"], "x*/,;:")) && ($rows = strtok("x, ")) || ($cols=70) && ($rows=15);
1554 global $ewiki_use_editor, $ewiki_editor_content;
1555 $ewiki_editor_content=1;
1556 if($ewiki_use_editor) {
1557 ob_start();
1558 $usehtmleditor = can_use_html_editor();
1559 echo '<table><tr><td>';
1560 if ($usehtmleditor) { //clean and convert before editing
1561 $options = new object();
1562 $options->smiley = false;
1563 $options->filter = false;
1564 $oldtext = format_text(ewiki_format($data["content"]), $moodle_format, $options);
1565 } else {
1566 $oldtext = ewiki_format($data["content"]);
1568 print_textarea($usehtmleditor, $rows, $cols, 680, 400, "content", $oldtext);
1569 echo '</td></tr></table>';
1571 if ($usehtmleditor) {
1572 use_html_editor("content");
1574 $o .= ob_get_contents();
1575 ob_end_clean();
1577 } else {
1578 ##### END MOODLE ADDITION #####
1580 $o .= '<textarea wrap="soft" id="ewiki_content" name="content" rows="'.$rows.'" cols="'.$cols.'">'
1581 . s($data["content"]) . "</textarea>"
1582 . $GLOBALS["ewiki_t"]["C"]["EDIT_TEXTAREA_RESIZE_JS"];
1584 ##### BEGIN MOODLE ADDITION #####
1586 ##### END MOODLE ADDITION #####
1588 #-- more <input> elements before the submit button
1589 if ($pf_a = $ewiki_plugins["edit_form_insert"]) foreach ($pf_a as $pf) {
1590 $o .= $pf($id, $data, $action);
1593 ##### BEGIN MOODLE ADDITION (Cancel Editing into Button) #####
1594 $o .= "\n<br />\n"
1595 . '<input type="submit" name="save" value="'. ewiki_t("SAVE") . '" />'."\n"
1596 . '<input type="submit" name="preview" value="'. ewiki_t("PREVIEW") . '" />' . "\n"
1597 . '<input type="submit" name="canceledit" value="'. ewiki_t("CANCEL_EDIT") . '" />' . "\n";
1598 # . ' &nbsp; <a href="'. ewiki_script("", $id) . '">' . ewiki_t("CANCEL_EDIT") . '</a>';
1599 ##### END MOODLE ADDITION #####
1601 #-- additional form elements
1602 if ($pf_a = $ewiki_plugins["edit_form_append"]) foreach ($pf_a as $pf) {
1603 $o .= $pf($id, $data, $action);
1606 $o .= "\n</div></form>\n";
1607 // . ewiki_t("EDIT_FORM_2"); // MOODLE DELETION
1609 return('<div class="edit-box">'. $o .'</div>');
1614 #-- pic upload form
1615 function ewiki_page_edit_form_final_imgupload(&$o, &$id, &$data, &$action) {
1616 if (EWIKI_SCRIPT_BINARY && EWIKI_UP_UPLOAD && EWIKI_IMAGE_MAXSIZE) {
1617 $o .= "\n<br />\n". '<div class="image-upload">'
1618 . '<form action='
1619 . '"'. ewiki_script_binary("", EWIKI_IDF_INTERNAL, "", "_UPLOAD=1") .'"'
1620 . ' method="post" enctype="multipart/form-data" target="_upload">'
1621 . '<fieldset class="invisiblefieldset">'
1622 . '<input type="hidden" name="MAX_FILE_SIZE" value="'.EWIKI_IMAGE_MAXSIZE.'" />'
1623 . '<input type="file" name="'.EWIKI_UP_UPLOAD.'"'
1624 . (defined("EWIKI_IMAGE_ACCEPT") ? ' accept="'.EWIKI_IMAGE_ACCEPT.'" />' : " />")
1625 . '<input type="hidden" name="'.EWIKI_UP_BINARY.'" value="'.EWIKI_IDF_INTERNAL.'" />'
1626 . '&nbsp;&nbsp;&nbsp;'
1627 . '<input type="submit" value="'.ewiki_t("UPLOAD_PICTURE_BUTTON").'" />'
1628 . '</fieldset></form></div>'. "\n";
1633 function ewiki_page_edit_preview(&$data) {
1634 #### BEGIN MOODLE CHANGES
1635 global $moodle_format;
1636 $preview_text=$GLOBALS["ewiki_plugins"]["render"][0]($_REQUEST["content"], 1, EWIKI_ALLOW_HTML || (@$data["flags"]&EWIKI_DB_F_HTML));
1637 return( '<div class="preview">'
1638 . "<hr noshade>"
1639 . "<div align=\"right\">" . ewiki_t("PREVIEW") . "</div><hr noshade><br />\n"
1640 . format_text($preview_text, $moodle_format)
1641 . "<br /><br /><hr noshade><br />"
1642 . "</div>"
1644 #### END MOODLE CHANGES
1648 function ewiki_control_links($id, &$data, $action) {
1650 global $ewiki_plugins, $ewiki_ring, $ewiki_config;
1651 $action_links = & $ewiki_config["action_links"][$action];
1653 #-- disabled
1654 if (!$ewiki_config["control_line"]) {
1655 return("");
1658 $o = "\n"
1659 . '<div align="right" class="action-links control-links">'
1660 . "\n<br />\n"
1661 . "<hr noshade>" . "\n";
1663 if (@$data["forced_version"]) {
1665 $o .= '<form action="' . ewiki_script("edit", $id) . '" method="post">' .
1666 '<fieldset class="invisiblefieldset">'.
1667 '<input type="hidden" name="edit" value="old" />' .
1668 '<input type="hidden" name="version" value="'.$data["forced_version"].'" />' .
1669 '<input type="submit" value="' . ewiki_t("OLDVERCOMEBACK") . '" /></form> ';
1671 else {
1672 foreach ($action_links as $action => $title)
1673 if (!empty($ewiki_plugins["action"][$action]) || !empty($ewiki_plugins["action_always"][$action]) || strpos($action, ":/"))
1675 if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($id, $data, $action)) { continue; }
1677 $o .= '<a href="'
1678 . (strpos($action, ":/") ? $action : ewiki_script($action, $id))
1679 . '">' . ewiki_t($title) . '</a> &middot; ';
1683 if ($data["lastmodified"] >= UNIX_MILLENNIUM) {
1684 $o .= '<small>' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . '</small>';
1687 $o .= "</div>\n";
1689 return($o);
1696 # ============================================================= rendering ===
1702 ######## ### ### ######### ### ### ### #######
1703 ######## #### ### ######### ### #### ### #######
1704 ### ##### ### ### ##### ### ###
1705 ###### ######### ### #### ### ######### ######
1706 ###### ######### ### #### ### ######### ######
1707 ### ### ##### ### ### ### ### ##### ###
1708 ######## ### #### ######### ### ### #### #######
1709 ######## ### ### ######### ### ### ### #######
1713 The _format() function transforms $wiki_source pages into <html> strings,
1714 also calls various markup and helper plugins during the transformation
1715 process. The $params array can activate various features and extensions.
1716 only accepts UNIX newlines!
1718 function ewiki_format (
1719 $wiki_source,
1720 $params = array()
1723 global $ewiki_links, $ewiki_plugins, $ewiki_config;
1725 #-- state vars
1726 $params = @array_merge($ewiki_config["format_params"], $params);
1727 $s = array(
1728 "in" => 0, # current input $iii[] block array index
1729 "para" => "",
1730 "line" => "",
1731 "post" => "", # string to append after current line/paragraph
1732 "line_i" => 0,
1733 "lines" => array(),
1734 "list" => "", # lists
1735 "tbl" => 0, # open table?
1736 "indent" => 0, # indentation
1737 "close" => array(),
1739 #-- aliases
1740 $in = &$s["in"];
1741 $line = &$s["line"];
1742 $lines = &$s["lines"];
1743 $para = &$s["para"];
1744 $post = &$s["post"];
1745 $list = &$s["list"];
1747 #-- input and output arrays
1748 if ($wiki_source[0] == "<") { # also prepend an empty line
1749 $wiki_source = "\n" . $wiki_source; # for faster strpos() searchs
1751 $iii = array(
1752 0 => array(
1753 0 => $wiki_source."\n", # body + empty line
1754 1 => 0x0FFF, # flags (0x1=WikiMarkup, 0x2=WikiLinks, 0x100=BlockPlugins)
1755 2 => "core", # block plugin name
1758 $ooo = array(
1760 unset($wiki_source);
1762 #-- plugins
1763 $pf_tbl = @$ewiki_plugins["format_table"][0];
1764 $pf_line = @$ewiki_plugins["format_line"];
1766 #-- wikimarkup (wm)
1767 $htmlentities = $ewiki_config["htmlentities"];
1768 $wm_indent = &$ewiki_config["wm_indent"];
1769 $wm_table_defaults = &$ewiki_config["wm_table_defaults"];
1770 $wm_source = &$ewiki_config["wm_source"];
1771 $wm_list = &$ewiki_config["wm_list"];
1772 $wm_list_chars = implode("", array_keys($wm_list));
1773 $wm_style = &$ewiki_config["wm_style"];
1774 $wm_start_end = &$ewiki_config["wm_start_end"];
1776 #-- eleminate html
1777 $iii[0][0] = strtr($iii[0][0], $htmlentities);
1778 unset($htmlentities["&"]);
1780 #-- pre-processing plugins (working on wiki source)
1781 if ($pf_source = $ewiki_plugins["format_source"]) {
1782 foreach ($pf_source as $pf) $pf(&$iii[0][0]);
1785 #-- simple markup
1786 $iii[0][0] = strtr($iii[0][0], $wm_source);
1788 #-- separate input into blocks ------------------------------------------
1789 foreach ($ewiki_config["format_block"] as $btype => $binfo) {
1791 #-- disabled block plugin?
1792 if ($binfo[2] && !$params[$binfo[2]]) {
1793 continue;
1796 #-- traverse $iii[]
1797 $in = -1;
1798 while ((++$in) < count($iii)) {
1800 #-- search fragment delimeters
1801 if ($iii[$in][1] & 0x0100)
1802 while (
1803 ($c = & $iii[$in][0]) &&
1804 (($l = strpos($c, $binfo[0])) !== false) &&
1805 ($r = strpos($c, $binfo[1], $l)) )
1807 $l_len = strlen($binfo[0]);
1808 $r_len = strlen($binfo[1]);
1810 $repl = array();
1811 // pre-text
1812 if (($l > 0) && trim($text = substr($c, 0, $l))) {
1813 $repl[] = array($text, 0xFFFF, "core");
1815 // the extracted part
1816 if (trim($text = substr($c, $l+$l_len, $r-$l-$r_len))) {
1817 $repl[] = array($text, $binfo[3], "$btype");
1819 // rest
1820 if (($r+$r_len < strlen($c)) && trim($text = substr($c, $r+$r_len))) {
1821 $repl[] = array($text, 0xFFFF, "core");
1823 array_splice($iii, $in, 1, $repl);
1825 $in += 1;
1830 #-- run format_block plugins
1831 $in = -1;
1832 while ((++$in) < count($iii)) {
1833 if (($btype = $iii[$in][2]) && ($pf_a = $ewiki_plugins["format_block"][$btype])) {
1834 $c = &$iii[$in][0];
1835 foreach ($pf_a as $pf) {
1836 # current buffer $c and pointer $in into $iii[] and state $s
1837 $pf($c, $in, $iii, $s, $btype);
1842 #-- wiki markup ------------------------------------------------------
1843 $para = "";
1844 $in = -1;
1845 while ((++$in) < count($iii)) {
1846 #-- wikimarkup
1847 if ($iii[$in][1] & 0x0001) {
1849 #-- input $lines buffer, and output buffer $ooo array
1850 $lines = explode("\n", $iii[$in][0]);
1851 $ooo[$in] = array(
1852 0 => "",
1853 1 => $iii[$in][1]
1855 $out = &$ooo[$in][0];
1856 $s["block"] = ($iii[$in][2] != "core"); # disables indentation & paragraphs
1858 #-- walk through wiki source lines
1859 $line_max = count($lines);
1860 foreach ($lines as $s["line_i"]=>$line) {
1861 //echo "<pre>line={$s[line_i]}:".htmlspecialchars($line).":".htmlspecialchars($line[0])."</pre>";
1863 #-- empty lines separate paragraphs
1864 if (!strlen($line)) {
1865 ewiki_format_close_para($ooo, $s);
1866 ewiki_format_close_tags($ooo, $s);
1867 if (!$s["block"]) {
1868 $out .= "\n";
1871 #-- horiz bar
1872 if (!strncmp($line, "----", 4)) {
1873 $out .= "<hr noshade>\n";
1874 continue;
1876 #-- html comment
1877 #if (!strncmp($line, "&lt;!--", 7)) {
1878 # $out .= "<!-- " . htmlentities(str_replace("--", "__", substr($line, 7))) . " -->\n";
1879 # continue;
1882 ($c0 = $line[0])
1883 or ($c0 = "\000");
1885 #-- tables
1886 ### MOODLE CHANGE: TRIM
1887 if (($c0 == "|") && ($line[strlen(trim($line))-1] == "|")) {
1888 if (!$s["tbl"]) {
1889 ewiki_format_close_para($ooo, $s);
1890 ewiki_format_close_tags($ooo, $s);
1891 $s["list"] = "";
1893 $line = substr($line, 1, -1);
1894 if ($pf_tbl) {
1895 $pf_tbl($line, $ooo, $s);
1897 else {
1898 if (!$s["tbl"]) {
1899 $out .= "<table " . $wm_table_defaults . ">\n";
1900 $s["close"][] = "\n</table>";
1902 $line = "<tr>\n<td>" . str_replace("|", "</td>\n<td>", $line) . "</td>\n</tr>";
1904 $s["tbl"] = 1;
1905 $para = false;
1907 elseif ($s["tbl"]) {
1908 $s["tbl"] = 0;
1912 #-- headlines
1913 if (($c0 == "!") && ($excl = strspn($line, "!"))) {
1914 if ($excl > 3) {
1915 $excl = 3;
1917 $line = substr($line, $excl);
1918 $excl = 5 - $excl;
1919 $line = "<h$excl>" . $line . "</h$excl>";
1920 if ($para) {
1921 ewiki_format_close_para($ooo, $s);
1923 ewiki_format_close_tags($ooo, $s);
1924 $para = false;
1927 #-- whole-line markup
1928 # ???
1931 #-- indentation (space/tab markup)
1932 $n_indent = 0;
1933 if (!$list && (!$s["block"]) && ($n_indent = strspn($line, " "))) {
1934 $n_indent = (int) ($n_indent / 2.65);
1935 while ($n_indent > $s["indent"]) {
1936 $out .= $wm_indent;
1937 $s["indent"]++;
1940 while ($n_indent < $s["indent"]) {
1941 $out .= "</div>\n";
1942 $s["indent"]--;
1946 #-- text style triggers
1947 foreach ($wm_style as $find=>$replace) {
1948 $find_len = strlen($find);
1949 $loop = 20;
1950 while(($loop--) && (($l = strpos($line, $find)) !== false) && ($r = strpos($line, $find, $l + $find_len))) {
1951 $line = substr($line, 0, $l) . $replace[0] .
1952 substr($line, $l + strlen($find), $r - $l - $find_len) .
1953 $replace[1] . substr($line, $r + $find_len);
1958 #-- list markup
1959 if (isset($wm_list[$c0])) {
1960 if (!$list) {
1961 ewiki_format_close_para($ooo, $s);
1962 ewiki_format_close_tags($ooo, $s);
1964 $new_len = strspn($line, $wm_list_chars);
1965 $new_list = substr($line, 0, $new_len);
1966 $old_len = strlen($list);
1967 $lchar = $new_list[$new_len-1];
1968 list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
1970 #-- cut line
1971 $line = substr($line, $new_len);
1972 $lspace = "";
1973 $linsert = "";
1974 if ($ltag1) {
1975 $linsert = "<$ltag1>" . strtok($line, $lchar) . "</$ltag1> ";
1976 $line = strtok("\000");
1979 #-- add another <li>st entry
1980 if ($new_len == $old_len) {
1981 $lspace = str_repeat(" ", $new_len);
1982 $out .= "</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
1984 #-- add list
1985 elseif ($new_len > $old_len) {
1986 while ($new_len > ($old_len=strlen($list))) {
1987 $lchar = $new_list[$old_len];
1988 $list .= $lchar;
1989 list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
1990 $lclose = strtok($lopen, " ");
1991 $lspace = str_repeat(" ", $new_len);
1993 $out .= "\n$lspace<$lopen>\n" . "$lspace". $linsert . "<$ltag2>";
1994 $s["close"][] = "$lspace</$lclose>";
1995 $s["close"][] = "$lspace</$ltag2>";
1998 #-- close lists
1999 else {
2000 while ($new_len < ($old_len=strlen($list))) {
2001 $remove = $old_len-$new_len;
2002 ewiki_format_close_tags($ooo, $s, 2*$remove);
2003 $list = substr($list, 0, -$remove);
2005 if ($new_len) {
2006 $lspace = str_repeat(" ", $new_len);
2007 $out .= "$lspace</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
2011 $list = $new_list;
2012 $para = false;
2014 elseif ($list) {
2015 if ($c0 == " ") {
2016 $para = false;
2018 else {
2019 ewiki_format_close_tags($ooo, $s);
2020 $list = "";
2025 #-- start-end markup
2026 foreach ($wm_start_end as $d) {
2027 $len0 = strlen($d[0]);
2028 $loop = 20;
2029 while(($loop--) && (($l = strpos($line, $d[0])) !== false) && ($r = strpos($line, $d[1], $l + $len0))) {
2030 $len1 = strlen($d[1]);
2031 $line = substr($line, 0, $l) . $d[2] .
2032 substr($line, $l + $len0, $r - $l - $len0) .
2033 $replace[1] . substr($line, $r + $len1);
2037 #-- call wiki source formatting plugins that work on current line
2038 if ($pf_line) {
2039 foreach ($pf_line as $pf) $pf($out, $line, $post);
2044 #-- add formatted line to page-output
2045 $line .= $post;
2046 if ($para === false) {
2047 $out .= $line;
2048 $para = "";
2050 else {
2051 $para .= $line . "\n";
2056 #-- last block, or next not WikiSource?
2057 if (!isset($iii[$in+1]) || !($iii[$in+1][1] & 0x0011)) {
2058 ewiki_format_close_para($ooo, $s);
2059 ewiki_format_close_tags($ooo, $s);
2062 #-- copy as is into output buffer
2063 else {
2064 $ooo[$in] = $iii[$in];
2066 $iii[$in] = array();
2069 #-- wiki linking ------------------------------------------------------
2070 $scan_src = "";
2071 for ($in=0; $in<count($ooo); $in++) {
2072 if (EWIKI_HTML_CHARS && ($ooo[$in][1] & 0x0004)) { # html character entities
2073 $ooo[$in][0] = str_replace("&amp;#", "&#", $ooo[$in][0]);
2075 if ($ooo[$in][1] & 0x0022) {
2076 #-- join together multiple WikiSource blocks
2077 while (isset($ooo[$in+1]) && ($ooo[$in][1] & 0x0002) && ($ooo[$in+1][1] & 0x0002)) {
2078 $ooo[$in] = array(
2079 0 => $ooo[$in][0] . "\n" . $ooo[$in+1][0],
2080 1 => $ooo[$in][1] | $ooo[$in+1][1],
2082 array_splice($ooo, $in+1, 1);
2085 $scan_src .= $ooo[$in][0];
2089 #-- pre-scan
2090 if (1+$params["scan_links"]) {
2091 ewiki_scan_wikiwords($scan_src, $ewiki_links);
2093 if ($pf_linkprep = $ewiki_plugins["format_prepare_linking"]) {
2094 foreach ($pf_linkprep as $pf) $pf($scan_src);
2096 $scan_src = NULL;
2098 #-- finally the link-detection-regex
2099 for ($in=0; $in<count($ooo); $in++) {
2100 if ($ooo[$in][1] & 0x0002) {
2101 ##### BEGIN MOODLE ADDITION #####
2102 # No WikiLinks in Editor
2103 #################################
2104 global $ewiki_use_editor, $ewiki_editor_content;
2105 if(!($ewiki_use_editor && $ewiki_editor_content)) {
2106 ##### END MOODLE ADDITION #####
2107 ewiki_render_wiki_links($ooo[$in][0]);
2108 ##### BEGIN MOODLE ADDITION #####
2110 ##### END MOODLE ADDITION #####
2114 #-- fin: combine all blocks into html string ----------------------------
2115 $html = "";
2116 for ($in=0; $in<count($ooo); $in++) {
2117 $html .= $ooo[$in][0] . "\n";
2118 $ooo[$in] = 0;
2120 #-- call post processing plugins
2121 if ($pf_final = $ewiki_plugins["format_final"]) {
2122 foreach ($pf_final as $pf) $pf($html);
2124 return($html);
2129 function ewiki_format_close_para(&$ooo, &$s) {
2130 $out = &$ooo[$s["in"]][0];
2131 #-- output text block
2132 if (trim($s["para"])) {
2133 if (!$s["block"]) {
2134 #### MOODLE CHANGES
2135 global $ewiki_use_editor;
2136 if(!$ewiki_use_editor) {
2137 $s["para"] = "\n<p>\n" . ltrim($s["para"], "\n") . "</p>\n";
2139 #### MOODLE CHANGES
2141 #-- paragraph formation plugins
2142 if ($pf_a = $GLOBALS["ewiki_plugins"]["format_para"]) {
2143 foreach ($pf_a as $pf) {
2144 $pf($s["para"], $ooo, $s);
2147 $out .= $s["para"];
2148 $s["para"] = "";
2150 #-- indentation
2151 while ($s["indent"]) {
2152 $out .= "</div>";
2153 $s["indent"]--;
2158 function ewiki_format_close_tags(&$ooo, &$s, $count=100) {
2159 $out = &$ooo[$s["in"]][0];
2160 if (!is_array($s) || !is_array($s["close"])) {
2161 die("\$s is garbaged == $s!!");
2163 while (($count--) && ($add = array_pop($s["close"]))) {
2164 $out .= $add . "\n";
2169 function ewiki_format_pre(&$str, &$in, &$iii, &$s, $btype) {
2170 $str = "<pre class=\"markup $btype\">" . $str . "</pre>";
2174 function ewiki_format_html(&$str, &$in, &$iii, &$s) {
2175 $he = array_reverse($GLOBALS["ewiki_config"]["htmlentities"]);
2176 $str = strtr($str, array_flip($he));
2177 $str = "<span class=\"markup html\">" . $str . "\n</span>\n";
2181 function ewiki_format_comment(&$str, &$in, &$iii, &$s, $btype) {
2182 $str = "<!-- " . str_replace("--", "��", $str) . " -->";
2188 /* unclean pre-scanning for WikiWords in a page,
2189 pre-query to the db */
2190 function ewiki_scan_wikiwords(&$wiki_source, &$ewiki_links, $se=0) {
2192 global $ewiki_config;
2194 #-- find matches
2195 preg_match_all($ewiki_config["wiki_pre_scan_regex"], $wiki_source, $uu);
2196 $uu = @array_merge($uu[1], $uu[2], $uu[3], $uu[4], (array)@$uu[5]);
2198 #-- clean up list, trim() spaces (allows more unclean regex) - page id unification
2199 foreach ($uu as $i=>$id) {
2200 $uu[$i] = trim($id);
2202 unset($uu[""]);
2203 $uu = array_unique($uu);
2205 #-- query db
2206 $ewiki_links = ewiki_database("FIND", $uu);
2208 #-- strip email adresses
2209 if ($se) {
2210 foreach ($ewiki_links as $c=>$uu) {
2211 if (strpos($c, "@") && (strpos($c, ".") || strpos($c, ":"))) {
2212 unset($ewiki_links[$c]);
2221 /* regex on page content,
2222 handled by callback (see below)
2224 function ewiki_render_wiki_links(&$o) {
2226 global $ewiki_links, $ewiki_config, $ewiki_plugins;
2228 #-- merge with dynamic pages list
2229 ewiki_merge_links($ewiki_links);
2231 #-- replace WikiWords
2232 $link_regex = &$ewiki_config["wiki_link_regex"];
2233 $o = preg_replace_callback($link_regex, "ewiki_link_regex_callback", $o);
2235 #-- cleanup
2236 unset($ewiki_links);
2241 combines with page plugin list,
2242 and makes all case-insensitive
2244 function ewiki_merge_links(&$ewiki_links) {
2245 global $ewiki_plugins;
2246 #### BEGIN MOODLE CHANGES
2247 global $ewiki_link_case;
2248 $ewiki_link_case=array();
2249 #### END MOODLE CHANGES
2250 if ($ewiki_links !== true) {
2251 foreach ($ewiki_plugins["page"] as $page=>$uu) {
2252 $ewiki_links[$page] = 1;
2254 #### BEGIN MOODLE CHANGES
2255 foreach($ewiki_links as $page => $uu) {
2256 if($uu) {
2257 $ewiki_link_case[strtolower($page)]=$page;
2260 #### END MOODLE CHANGES
2261 $ewiki_links = ewiki_array($ewiki_links);
2268 /* link rendering (p)regex callback
2269 (ooutch, this is a complicated one)
2271 function ewiki_link_regex_callback($uu, $force_noimg=0) {
2272 #print "<pre>"; print_r($uu); print "</pre>";
2273 global $ewiki_links, $ewiki_plugins, $ewiki_config, $ewiki_id;
2275 $str = trim($uu[0]);
2276 $type = array();
2277 $states = array();
2279 #-- link bracket '[' escaped with '!' or '~'
2280 if (($str[0] == "!") || ($str[0] == "~")) {
2281 return(substr($str, 1));
2283 if ($str[0] == "#") {
2284 $states["define"] = 1;
2285 $str = substr($str, 1);
2287 if ($str[0] == "[") {
2288 $states["brackets"] = 1;
2289 $str = substr($str, 1, -1);
2292 #-- explicit title given via [ title | WikiLink ]
2293 $href = $title = strtok($str, "|");
2294 if ($uu = strtok("|")) {
2295 $href = $uu;
2296 $states["titled"] = 1;
2298 #-- title and href swapped: swap back
2299 if (strpos("://", $title) || strpos($title, ":") && !strpos($href, ":")) {
2300 $uu = $title; $title = $href; $href = $uu;
2303 #-- new entitling scheme [ url "title" ]
2304 if ((($l=strpos($str, '"')) < ($r=strrpos($str, '"'))) && ($l!==false) ) {
2305 $title = substr($str, $l + 1, $r - $l - 1);
2306 $href = substr($str, 0, $l) . substr($str, $r + 1);
2307 $states["titled"] = 1;
2310 #-- strip spaces
2311 $spaces_l = ($href[0]==" ") ?1:0;
2312 $spaces_r = ($href[strlen($href)-1]==" ") ?1:0;
2313 $title = ltrim(trim($title), "^");
2314 $href = ltrim(trim($href), "^");
2316 #-- strip_htmlentities()
2317 if (1&& (strpos($href, "&")!==false) && strpos($href, ";")) {
2318 foreach (array("&lt;"=>"<", "&gt;"=>">", "&amp;"=>"&") as $f=>$t) {
2319 $href = str_replace($f, $t, $href);
2323 #-- anchors
2324 $href2 = "";
2325 if (($p = strrpos($href, "#")) && ($p) && ($href[$p-1] != "&")) {
2326 $href2 = trim(substr($href, $p));
2327 $href = trim(substr($href, 0, $p));
2329 elseif ($p === 0) {
2330 $states["define"] = 1;
2332 if ($href == ".") {
2333 $href = $ewiki_id;
2336 #-- for case-insensitivines
2337 $href_i = EWIKI_CASE_INSENSITIVE ? strtolower($href) : ($href);
2339 #-- injected URLs
2340 if (strpos($inj_url = $ewiki_links[$href_i], "://")) {
2341 if ($href==$title) { $href = $inj_url; }
2344 #-- interwiki links
2345 if (strpos($href, ":") && ($uu = ewiki_interwiki($href, $type))) {
2346 $href = $uu;
2347 $str = "<a href=\"$href$href2\">$title</a>";
2349 #-- action:WikiLinks
2350 elseif ($ewiki_plugins["action"][$a=strtolower(strtok($href, ":"))]) {
2351 $type = array($a, "action", "wikipage");
2352 $str = '<a href="' . ewiki_script($a, strtok("\000")) . '">' . $title . '</a>';
2354 #-- page anchor definitions, if ($href[0]=="#")
2355 elseif (@$states["define"]) {
2356 $type = array("anchor");
2357 if ($title==$href) { $title="&nbsp;"; }
2358 $str = '<a name="' . s(ltrim($href, "#")) . '">' . ltrim($title, "#") . '</a>';
2360 #-- inner page anchor jumps
2361 elseif (strlen($href2) && ($href==$ewiki_id) || ($href[0]=="#") && ($href2=&$href)) {
2362 $type = array("jump");
2363 $str = '<a href="' . s($href2) . '">' . $title . '</a>';
2365 #-- ordinary internal WikiLinks
2366 elseif (($ewiki_links === true) || @$ewiki_links[$href_i]) {
2367 $type = array("wikipage");
2368 #### BEGIN MOODLE CHANGES
2369 global $ewiki_link_case;
2370 $href_realcase=array_key_exists($href_i,$ewiki_link_case) ? $ewiki_link_case[$href_i] : $href;
2371 $str = '<a href="' . ewiki_script("", $href_realcase) . s($href2)
2372 . '">' . $title . '</a>';
2373 #### END MOODLE CHANGES
2375 #-- guess for mail@addresses, convert to URI if
2376 elseif (strpos($href, "@") && !strpos($href, ":")) {
2377 $type = array("email");
2378 $href = "mailto:" . $href;
2380 #-- not found fallback
2381 else {
2382 $str = "";
2383 #-- a plugin may take care
2384 if ($pf_a = $ewiki_plugins["link_notfound"]) {
2385 foreach ($pf_a as $pf) {
2386 if ($str = $pf($title, $href, $href2, $type)) {
2387 break;
2391 #-- (QuestionMarkLink to edit/ action)
2392 if (!$str) {
2393 $type = array("notfound");
2394 $str = '<span class="NotFound"><b>' . $title . '</b><a href="' .
2395 ewiki_script("", $href) . '">?</a></span>';
2399 #-- convert standard URLs
2400 foreach ($ewiki_config["idf"]["url"] as $find)
2401 if (strpos($href, $find)===0) {
2402 $type[-2] = "url";
2403 $type[-1] = strtok($find, ":");
2405 #-- URL plugins
2406 if ($pf_a = $ewiki_plugins["link_url"]) foreach ($pf_a as $pf) {
2407 if ($str = $pf($href, $title)) { break 2; }
2409 $meta = @$ewiki_links[$href];
2411 #-- check for image files
2412 $ext = substr($href, strrpos($href,"."));
2413 $nocache = strpos($ext, "no");
2414 $ext = strtok($ext, "?&#");
2415 $obj = in_array($ext, $ewiki_config["idf"]["obj"]);
2416 $img = $obj || in_array($ext, $ewiki_config["idf"]["img"]);
2418 #-- internal:// references (binary files)
2419 if (EWIKI_SCRIPT_BINARY && ((strpos($href, EWIKI_IDF_INTERNAL)===0) ||
2420 EWIKI_IMAGE_MAXSIZE && EWIKI_CACHE_IMAGES && $img && !$nocache) )
2422 $type = array("binary");
2423 $href = ewiki_script_binary("", $href);
2426 #-- output html reference
2427 if (!$img || $force_noimg || !$states["brackets"] || (strpos($href, EWIKI_IDF_INTERNAL) === 0)) {
2428 $str = '<a href="' . $href . '">' . $title . '</a>';
2430 #-- img tag
2431 else {
2432 if (is_string($meta)) {
2433 $meta = unserialize($meta);
2435 $type = array("image");
2436 #-- uploaded images size
2437 $x = $meta["width"];
2438 $y = $meta["height"];
2439 if ($p = strpos('?', $href)) { #-- width/height given in url
2440 parse_str(str_replace("&amp;", "&", substr($href, $p)), $meta);
2441 ($uu = $meta["x"] . $meta["width"]) and ($x = $uu);
2442 ($uu = $meta["y"] . $meta["height"]) and ($y = $uu);
2443 if ($scale = $meta["r"] . $meta["scale"]) {
2444 ($p = strpos($scale, "%")) and ($scale = strpos($scale, 0, $p) / 100);
2445 $x *= $scale; $y *= $scale;
2448 $align = array('', ' align="right"', ' align="left"', ' align="center"');
2449 $align = $align[$spaces_l + 2*$spaces_r];
2450 $str = ($obj ? '<embed width="70%"' : '<img') . ' src="' . $href . '"' .
2451 ' alt="' . ($title) . '"' .
2452 (@$states["titled"] ? ' title="' . ($title) . '"' : '').
2453 ($x && $y ? " width=\"$x\" height=\"$y\"" : "") .
2454 $align . " />" . ($obj ? "</embed>" : "");
2455 # htmlentities($title)
2458 break;
2461 #-- icon/transform plugins
2462 ksort($type);
2463 if ($pf_a = @$ewiki_plugins["link_final"]) {
2464 foreach ($pf_a as $pf) { $pf($str, $type, $href, $title); }
2467 return($str);
2472 Returns URL if it encounters an InterWiki:Link or workalike.
2474 function ewiki_interwiki($href, &$type) {
2475 global $ewiki_config, $ewiki_plugins;
2477 if (strpos($href, ":") and !strpos($href, "//")
2478 and ($p1 = strtok($href, ":"))) {
2480 $page = strtok("\000");
2482 if (($p1 = ewiki_array($ewiki_config["interwiki"], $p1)) !== NULL) {
2483 $type = array("interwiki", $uu);
2484 while ($p1_alias = $ewiki_config["interwiki"][$p1]) {
2485 $type[] = $p1;
2486 $p1 = $p1_alias;
2488 if (!strpos($p1, "%s")) {
2489 $p1 .= "%s";
2491 $href = str_replace("%s", $page, $p1);
2492 return($href);
2494 elseif ($pf = $ewiki_plugins["intermap"][$p1]) {
2495 return($pf($p1, $page));
2502 implements FeatureWiki:InterMapWalking
2504 function ewiki_intermap_walking($id, &$data, $action) {
2505 if (empty($data["version"]) && ($href = ewiki_interwiki($id, $uu))) {
2506 header("Location: $href");
2507 return("<a href=\"$href\">$href</a>");
2513 # =========================================================================
2517 ##### ## ## ## ## ##### ## ##
2518 ###### ## ### ## #### ###### ## ##
2519 ## ## ## ### ## ###### ## ## ## ##
2520 ##### ## #### ## ## ## ###### ######
2521 ##### ## ####### ###### #### ####
2522 ## ### ## ## #### ###### ##### ##
2523 ## ### ## ## ### ## ## ## ### ##
2524 ###### ## ## ### ## ## ## ## ##
2525 ###### ## ## ## ## ## ## ## ##
2530 /* fetch & store
2532 function ewiki_binary($break=0) {
2533 global $ewiki_plugins;
2534 global $USER; // MOODLE
2536 #-- reject calls
2537 if (!strlen($id = @$_REQUEST[EWIKI_UP_BINARY]) || !EWIKI_IDF_INTERNAL) {
2538 return(false);
2540 if (headers_sent()) die("ewiki-binary configuration error");
2542 #-- upload requests
2543 $upload_file = @$_FILES[EWIKI_UP_UPLOAD];
2544 $add_meta = array();
2545 if ($orig_name = @$upload_file["name"]) {
2546 $add_meta["Content-Location"] = urlencode($orig_name);
2547 $add_meta["Content-Disposition"] = 'inline; filename="'.urlencode(basename("remote://$orig_name")).'"';
2550 #-- what are we doing here?
2551 if (($id == EWIKI_IDF_INTERNAL) && ($upload_file)) {
2552 $do = "upload";
2554 else {
2555 $data = ewiki_database("GET", array("id" => $id));
2556 $flags = @$data["flags"];
2557 if (EWIKI_DB_F_BINARY == ($flags & EWIKI_DB_F_TYPE)) {
2558 $do = "get";
2560 elseif (empty($data["version"]) and EWIKI_CACHE_IMAGES) {
2561 $do = "cache";
2563 else {
2564 $do = "nop";
2569 #-- auth only happens when enforced with _PROTECTED_MODE_XXL setting
2570 # (authentication for inline images in violation of the WWW spirit)
2571 if ((EWIKI_PROTECTED_MODE>=5) && !ewiki_auth($id, $data, "binary-{$do}")) {
2572 return($_REQUEST["id"]="view/BinaryPermissionError");
2575 #-- upload an image
2576 if ($do == "upload"){
2578 $id = ewiki_binary_save_image($upload_file["tmp_name"], "", $return=0, $add_meta);
2579 @unlink($upload_file["tmp_name"]);
2580 ($title = trim($orig_name, "/")) && ($title = preg_replace("/[^-._\w\d]+/", "_", substr(substr($orig_name, strrpos($title, "/")), 0, 20)))
2581 && ($title = '"'.$title.'"') || ($title="");
2583 if ($id) {
2584 echo<<<EOF
2585 <html><head><title>File/Picture Upload</title><script type="text/javascript"><!--
2586 opener.document.forms["ewiki"].elements["content"].value += "\\nUPLOADED PICTURE: [$id$title]\\n";
2587 window.setTimeout("self.close()", 5000);
2588 //--></script></head><body bgcolor="#440707" text="#FFFFFF">Your uploaded file was saved as<br /><big><b>
2589 [$id]
2590 </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>
2591 EOF;
2595 #-- request for contents from the db
2596 elseif ($do == "get") {
2597 #### CHANGED FOR MOODLE
2598 if (EWIKI_HIT_COUNTING) {
2599 $tmp["id"]=$id;
2600 ewiki_database("HIT", $tmp);
2602 #### CHANGED FOR MOODLE
2604 #-- send http_headers from meta
2605 if (is_array($data["meta"])) {
2606 foreach ($data["meta"] as $hdr=>$val) {
2607 if (($hdr[0] >= "A") && ($hdr[0] <= "Z")) {
2608 header("$hdr: $val");
2613 #-- fetch from binary store
2614 if ($pf_a = $ewiki_plugins["binary_get"]) {
2615 #### CHANGED FOR MOODLE
2616 foreach ($pf_a as $pf) { $pf($id, $data["meta"]); }
2618 #### END CHANGED FOR MOODLE
2621 #-- else fpassthru
2622 echo $data["content"];
2625 #-- fetch & cache requested URL,
2626 elseif ($do == "cache") {
2628 #-- check for standard protocol names, to prevent us from serving
2629 # evil requests for '/etc/passwd.jpeg' or '../.htaccess.gif'
2630 if (preg_match('@^\w?(http|ftp|https|ftps|sftp)\w?://@', $id)) {
2632 #-- generate local copy
2633 $filename = tempnam(EWIKI_TMP, "ewiki.local.temp.");
2634 if (($i = fopen($id, "rb")) && ($o = fopen($filename, "wb"))) {
2636 while (!feof($i)) {
2637 fwrite($o, fread($i, 65536));
2640 fclose($i);
2641 fclose($o);
2643 $add_meta = array(
2644 "Content-Location" => urlencode($id),
2645 "Content-Disposition" => 'inline; filename="'.urlencode(basename($id)).'"'
2648 $result = ewiki_binary_save_image($filename, $id, "RETURN", $add_meta);
2652 #-- deliver
2653 if ($result && !$break) {
2654 ewiki_binary($break=1);
2656 #-- mark URL as unavailable
2657 else {
2658 $data = array(
2659 "id" => $id,
2660 "version" => 1,
2661 "flags" => EWIKI_DB_F_DISABLED,
2662 "lastmodified" => time(),
2663 "created" => time(),
2664 "author" => ewiki_author("ewiki_binary_cache"),
2665 "userid" => $USER->id,
2666 "content" => "",
2667 "meta" => array("Status"=>"404 Absent"),
2669 ewiki_database("WRITE", $data);
2670 header("Location: $id");
2671 ewiki_log("imgcache: did not find '$id', and marked it now in database as DISABLED", 2);
2676 #-- "we don't sell this!"
2677 else {
2678 if (strpos($id, EWIKI_IDF_INTERNAL) === false) {
2679 header("Status: 301 Located SomeWhere Else");
2680 header("Location: $id");
2682 else {
2683 header("Status: 404 Absent");
2684 header("X-Broken-URI: $id");
2688 // you should not remove this one, it is really a good idea to use it!
2689 die();
2697 function ewiki_binary_save_image($filename, $id="", $return=0,
2698 $add_meta=array(), $accept_all=EWIKI_ACCEPT_BINARY, $care_for_images=1)
2700 global $ewiki_plugins;
2701 global $USER; // MOODLE
2703 #-- break on empty files
2704 if (!filesize($filename)) {
2705 return(false);
2708 #-- check for image type and size
2709 $mime_types = array(
2710 "application/octet-stream",
2711 "image/gif",
2712 "image/jpeg",
2713 "image/png",
2714 "application/x-shockwave-flash"
2716 $ext_types = array(
2717 "bin", "gif", "jpeg", "png", "swf"
2719 list($width, $height, $mime_i, $uu) = getimagesize($filename);
2720 (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
2722 #-- images expected
2723 if ($care_for_images) {
2725 #-- mime type
2726 if (!$mime_i && !$accept_all || !filesize($filename)) {
2727 ewiki_die(ewiki_t("BIN_NOIMG"), $return);
2728 return;
2731 #-- resize image
2732 if (strpos($mime,"image/")!==false) {
2733 if ($pf_a = $ewiki_plugins["image_resize"]) {
2734 foreach ($pf_a as $pf) {
2735 if (EWIKI_IMAGE_RESIZE && (filesize($filename) > EWIKI_IMAGE_MAXSIZE)) {
2736 $pf($filename, $mime, $return);
2737 clearstatcache();
2738 }}}}
2740 #-- reject image if too large
2741 if (strlen($content) > EWIKI_IMAGE_MAXSIZE) {
2742 ewiki_die(ewiki_t("BIN_IMGTOOLARGE"), $return);
2743 return;
2746 #-- again check mime type and image sizes
2747 list($width, $height, $mime_i, $uu) = getimagesize($filename);
2748 (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
2751 ($ext = $ext_types[$mime_i]) or ($ext = $ext_types[0]);
2753 #-- binary files
2754 if ((!$mime_i) && ($pf = $ewiki_plugins["mime_magic"][0])) {
2755 if ($tmp = $pf($content)) {
2756 $mime = $tmp;
2759 if (!strlen($mime)) {
2760 $mime = $mime_types[0];
2763 #-- store size of binary file
2764 $add_meta["size"] = filesize($filename);
2765 $content = "";
2767 #-- handler for (large/) binary content?
2768 if ($pf_a = $ewiki_plugins["binary_store"]) {
2769 foreach ($pf_a as $pf) {
2770 $pf($filename, $id, $add_meta, $ext);
2774 #-- read file into memory (2MB), to store it into the database
2775 if ($filename) {
2776 $f = fopen($filename, "rb");
2777 $content = fread($f, 1<<21);
2778 fclose($f);
2781 #-- generate db file name
2782 if (empty($id)) {
2783 $md5sum = md5($content);
2784 $id = EWIKI_IDF_INTERNAL . $md5sum . ".$ext";
2785 ewiki_log("generated md5sum '$md5sum' from file content");
2788 #-- prepare meta data
2789 $meta = @array_merge(array(
2790 "class" => $mime_i ? "image" : "file",
2791 "Content-Type" => $mime,
2792 "Pragma" => "cache",
2793 ), $add_meta);
2794 if ($mime_i) {
2795 $meta["width"] = $width;
2796 $meta["height"] = $height;
2799 #-- database entry
2800 $data = array(
2801 "id" => $id,
2802 "version" => "1",
2803 "author" => ewiki_author(),
2804 "userid" => $USER->id,
2805 "flags" => EWIKI_DB_F_BINARY | EWIKI_DB_F_READONLY,
2806 "created" => time(),
2807 "lastmodified" => time(),
2808 "meta" => &$meta,
2809 "content" => &$content,
2812 #-- write if not exist
2813 $exists = ewiki_database("FIND", array($id));
2814 if (! $exists[$id] ) {
2815 $result = ewiki_database("WRITE", $data);
2816 ewiki_log("saving of '$id': " . ($result ? "ok" : "error"));
2818 else {
2819 ewiki_log("binary_save_image: '$id' was already in the database", 2);
2822 return($id);
2828 # =========================================================================
2831 #### #### #### ######## ########
2832 ##### ##### #### ########## ##########
2833 ###### ###### #### #### ### #### ###
2834 ############# #### ####
2835 ############# #### ######## ####
2836 #### ### #### #### ######## ####
2837 #### # #### #### #### ####
2838 #### #### #### ### #### #### ###
2839 #### #### #### ######### ##########
2840 #### #### #### ####### ########
2844 /* yes! it is not neccessary to annoy users with country flags, if the
2845 http already provides means to determine preferred languages!
2847 function ewiki_localization() {
2849 global $ewiki_t, $ewiki_plugins;
2851 $deflangs = ','.@$_ENV["LANGUAGE"] . ','.@$_ENV["LANG"]
2852 . ",".EWIKI_DEFAULT_LANG . ",en,C";
2854 foreach (explode(",", @$_SERVER["HTTP_ACCEPT_LANGUAGE"].$deflangs) as $l) {
2856 $l = strtok($l, ";");
2857 $l = strtok($l, "-"); $l = strtok($l, "_"); $l = strtok($l, ".");
2858 $l = trim($l);
2860 $ewiki_t["languages"][] = strtolower($l);
2867 /* poor mans gettext, $repl is an array of string replacements to get
2868 applied to the fetched text chunk,
2869 "$const" is either an entry from $ewiki_t[] or a larger text block
2870 containing _{text} replacement braces of the form "_{...}"
2872 function ewiki_t($const, $repl=array(), $pref_langs=array()) {
2873 ##### BEGIN MOODLE ADDITION #####
2874 $replacechars=array("." => "",
2875 "," => "",
2876 "!" => "",
2877 ";" => "",
2878 ":" => "",
2879 "'" => "",
2880 '"' => "",
2881 "-" => "",
2882 "_" => "",
2883 " " => "",
2884 "+" => "");
2886 $translation=get_string(strtolower(strtr($const,$replacechars)),"wiki",$repl);
2887 return $translation;
2888 ##### END MOODLE ADDITION #####
2890 /* global $ewiki_t;
2892 #-- use default language wishes
2893 if (empty($pref_langs)) {
2894 $pref_langs = $ewiki_t["languages"];
2897 #-- large text snippet replaceing
2898 if (strpos($const, "_{") !== false) {
2899 while ( (($l=strpos($const,"_{")) || ($l===0)) && ($r=strpos($const,"}",$l)) ) {
2900 $const = substr($const, 0, $l)
2901 . ewiki_t(substr($const, $l+2, $r-$l-2))
2902 . substr($const,$r+1);
2906 #-- just one string
2907 else foreach ($pref_langs as $l) {
2909 if (is_string($r = @$ewiki_t[$l][$const]) || ($r = @$ewiki_t[$l][strtoupper($const)])) {
2911 foreach ($repl as $key=>$value) {
2912 if ($key[0] != '$') {
2913 $key = '$'.$key;
2915 $r = str_replace($key, $value, $r);
2917 return($r);
2922 return($const);*/
2930 function ewiki_log($msg, $error_type=3) {
2932 if ((EWIKI_LOGLEVEL >= 0) && ($error_type <= EWIKI_LOGLEVEL)) {
2934 $msg = time() . " - " .
2935 getremoteaddr() . ":" . $_SERVER["REMOTE_PORT"] . " - " .
2936 $_SERVER["REQUEST_METHOD"] . " " . $_SERVER["REQUEST_URI"] . " - " .
2937 strtr($msg, "\n\r\000\377\t\f", "\r\r\r\r\t\f") . "\n";
2938 error_log($msg, 3, EWIKI_LOGFILE);
2945 function ewiki_die($msg, $return=0) {
2946 ewiki_log($msg, 1);
2947 if ($return) {
2948 return($GLOBALS["ewiki_error"] = $msg);
2950 else {
2951 die($msg);
2957 function ewiki_array_hash(&$a) {
2958 return(count($a) . ":" . implode(":", array_keys(array_slice($a, 0, 3))));
2963 /* provides an case-insensitive in_array replacement to search a page name
2964 in a list of others;
2965 the supplied $array WILL be lowercased afterwards, unless $dn was set
2967 function ewiki_in_array($value, &$array, $dn=0, $ci=EWIKI_CASE_INSENSITIVE) {
2969 static $as = array();
2971 #-- work around pass-by-reference
2972 if ($dn && $ci) { $dest = array(); }
2973 else { $dest = &$array; }
2975 #-- make everything lowercase
2976 if ($ci) {
2977 $value = strtolower($value);
2978 if (empty($as[ewiki_array_hash($array)])) { // prevent working on the
2979 foreach ($array as $i=>$v) { // same array multiple times
2980 $dest[$i] = strtolower($v);
2982 $as[ewiki_array_hash($dest)] = 1;
2986 #-- search in values
2987 return(in_array($value, $dest));
2992 /* case-insensitively retrieves an entry from an $array,
2993 or returns the given $array lowercased if $key was obmitted
2995 function ewiki_array($array, $key=false, $am=1, $ci=EWIKI_CASE_INSENSITIVE) {
2997 #-- make everything lowercase
2998 if ($ci) {
2999 $key = strtolower($key);
3001 $r = array();
3002 foreach ($array as $i=>$v) {
3003 $i = strtolower($i);
3004 if (!$am || empty($r[$i])) {
3005 $r[$i] = $v;
3007 else {
3008 $r[$i] .= $v; //RET: doubling for images`meta won't happen
3009 } // but should be "+" here for integers
3011 $array = &$r;
3014 #-- search in values
3015 if ($key) {
3016 return(@$array[$key]);
3018 else {
3019 return($array);
3028 function ewiki_author($defstr="") {
3030 $author = @$GLOBALS["ewiki_author"];
3031 ($ip = getremoteaddr()) or ($ip = "127.0.0.0");
3032 ($port = $_SERVER["REMOTE_PORT"]) or ($port = "null");
3033 $hostname = $ip;
3034 $remote = (($ip != $hostname) ? $hostname . " " : "")
3035 . $ip . ":" . $port;
3037 (empty($author)) && (
3038 ($author = $defstr) ||
3039 ($author = $_SERVER["HTTP_FROM"]) || // RFC2068 sect 14.22
3040 ($author = $_SERVER["PHP_AUTH_USER"])
3043 (empty($author))
3044 && ($author = $remote)
3045 || ($author = addslashes($author) . " (" . $remote . ")" );
3047 return($author);
3054 /* Returns a value of (true) if the currently logged in user (this must
3055 be handled by one of the plugin backends) is authenticated to do the
3056 current $action, or to view the current $id page.
3057 - alternatively just checks current authentication $ring permission level
3058 - errors are returned via the global $ewiki_errmsg
3060 function ewiki_auth($id, &$data, $action, $ring=false, $request_auth=0) {
3062 global $ewiki_plugins, $ewiki_ring, $ewiki_author, $ewiki_errmsg;
3063 $ok = true;
3064 $ewiki_errmsg="";
3066 #echo "_a($id,dat,$action,$ring,$request_auth)<br />\n";
3068 if (EWIKI_PROTECTED_MODE) {
3070 #-- set required vars
3071 if (!isset($ewiki_ring)) {
3072 $ewiki_ring = (int)EWIKI_AUTH_DEFAULT_RING;
3074 if ($ring===false) {
3075 $ring = NULL;
3078 #-- plugins to call
3079 $pf_login = @$ewiki_plugins["auth_query"][0];
3080 $pf_perm = $ewiki_plugins["auth_perm"][0];
3082 #-- nobody is currently logged in, so try to fetch username,
3083 # the login <form> is not yet enforced
3084 if ($pf_login && empty($ewiki_auth_user)) {
3085 $pf_login($data, 0);
3088 #-- check permission for current request (page/action/ring)
3089 if ($pf_perm) {
3091 #-- via _auth handler
3092 $ok = $pf_perm($id, $data, $action, $ring, $request_auth);
3094 #-- if it failed, we really depend on the login <form>,
3095 # and then recall the _perm plugin
3096 if ($pf_login && (($request_auth >= 2) || !$ok && $request_auth && (empty($ewiki_auth_user) || EWIKI_AUTO_LOGIN) && empty($ewiki_errmsg))) {
3097 //@FIXME: complicated if() - strip empty(errmsg) ??
3098 $pf_login($data, $request_auth);
3099 $ok = $pf_perm($id, $data, $action, $ring, $request_auth=0);
3102 else {
3103 $ok = !isset($ring) || isset($ring) && ($ewiki_ring <= $ring);
3106 #-- return error string
3107 if (!$ok && empty($ewiki_errmsg)) {
3108 $ewiki_errmsg = ewiki_t("FORBIDDEN");
3112 return($ok);
3117 Queries all registered ["auth_userdb"] plugins for the given
3118 username, and compares password to against "db" value, sets
3119 $ewiki_ring and returns(true) if valid.
3121 function ewiki_auth_user($username, $password) {
3122 global $ewiki_ring, $ewiki_errmsg, $ewiki_auth_user, $ewiki_plugins, $ewiki_author;
3124 if (empty($username)) {
3125 return(false);
3127 if (($password[0] == "$") || (strlen($password) > 12)) {
3128 ewiki_log("_auth_userdb: password was transmitted in encoded form, or is just too long (login attemp for user '$username')", 2);
3129 return(false);
3132 if ($pf_u = $ewiki_plugins["auth_userdb"])
3133 foreach ($pf_u as $pf) {
3135 if (function_exists($pf) && ($entry = $pf($username, $password))) {
3137 #-- get and compare password
3138 if ($entry = (array) $entry) {
3139 $enc_pw = $entry[0];
3141 $success = false
3142 || ($enc_pw == substr($password, 0, 12))
3143 || ($enc_pw == md5($password))
3144 || ($enc_pw == crypt($password, substr($enc_pw, 0, 2)))
3145 || function_exists("sha1") && ($enc_pw == sha1($password));
3146 $success &= $enc_pw != "*";
3148 #-- return if it matches
3149 if ($success) {
3150 if (isset($entry[1])) {
3151 $ewiki_ring = (int)($entry[1]);
3152 } else {
3153 $ewiki_ring = 2; //(EWIKI_AUTH_DEFAULT_RING - 1);
3155 if (empty($ewiki_author)) {
3156 ($ewiki_author = $entry[2]) or
3157 ($ewiki_author = $username);
3159 return($success && ($ewiki_auth_user=$username));
3164 if ($username || $password) {
3165 ewiki_log("_auth_userdb: wrong password supplied for user '$username', not verified against any userdb", 3);
3166 $ewiki_errmsg = "wrong username and/or password";
3167 # ewiki_auth($uu, $uu, $uu, $uu, 2);
3169 return(false);
3176 /* reads all files from "./init-pages/" into the database,
3177 when ewiki is run for the very first time and the FrontPage
3178 does not yet exist in the database
3180 function ewiki_eventually_initialize(&$id, &$data, &$action) {
3182 global $USER;
3184 #-- initialize database only if frontpage missing
3185 if (($id==EWIKI_PAGE_INDEX) && ($action=="edit") && empty($data["version"])) {
3187 ewiki_database("INIT", array());
3188 #### BEGIN MOODLE CHANGE
3189 $path=EWIKI_INIT_PAGES;
3190 if (!empty($path)) {
3191 if ($dh = @opendir($path=EWIKI_INIT_PAGES)) {
3192 while ($filename = readdir($dh)) {
3193 #### MOODLE CHANGE TO SOLVE BUG #3830. Original doesn't support dots in names.
3194 //Orig->if (preg_match('/^(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+\w*)+/', $filename)) {
3195 if ($filename == clean_filename($filename) && !is_dir($path.'/'.$filename)) {
3196 #### END OF MOODLE CHANGE TO SOLVE BUG #3830. Original doesn't support dots in names.
3197 $found = ewiki_database("FIND", array($filename));
3198 if (! $found[$filename]) {
3199 $content = implode("", file("$path/$filename"));
3200 ewiki_scan_wikiwords($content, $ewiki_links, "_STRIP_EMAIL=1");
3201 $refs = "\n\n" . implode("\n", array_keys($ewiki_links)) . "\n\n";
3202 $save = array(
3203 "id" => "$filename",
3204 "version" => "1",
3205 "flags" => "1",
3206 "content" => $content,
3207 "author" => ewiki_author("ewiki_initialize"),
3208 "userid" => $USER->id,
3209 "refs" => $refs,
3210 "lastmodified" => filemtime("$path/$filename"),
3211 "created" => filectime("$path/$filename") // (not exact)
3213 ewiki_database("WRITE", $save);
3217 closedir($dh);
3219 else {
3220 echo "<b>ewiki error</b>: could not read from directory ". realpath($path) ."<br />\n";
3223 #### END MOODLE CHANGE
3225 #-- try to view/ that newly inserted page
3226 if ($data = ewiki_database("GET", array("id"=>$id))) {
3227 $action = "view";
3235 #---------------------------------------------------------------------------
3239 ######## ### ######## ### ######## ### ###### ########
3240 ######## ### ######## ### ######## ### ###### ########
3241 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3242 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3243 ## ## ## ## ## ## ## ## ## ## ## ## ##
3244 ## ## ## ## ## ## ## ## ## ## ## ## ##
3245 ## ## ## ## ## ## ## ######## ## ## ###### ######
3246 ## ## ## ## ## ## ## ######## ## ## ###### ######
3247 ## ## ######### ## ######### ## ## ######### ## ##
3248 ## ## ######### ## ######### ## ## ######### ## ##
3249 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3250 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3251 ######## ## ## ## ## ## ######## ## ## ###### ########
3252 ######## ## ## ## ## ## ######## ## ## ###### ########
3257 /* wrapper
3259 function ewiki_database($action, $args, $sw1=0, $sw2=0, $pf=false) {
3261 #-- normalize (fetch bad parameters)
3262 if (($action=="GET") && !is_array($args) && is_string($args)) {
3263 $args = array("id" => $args);
3266 #-- treat special
3267 switch ($action) {
3269 case "GETALL":
3270 $args = array_unique(@array_merge($args, array("flags", "version")));
3271 $args = array_diff($args, array("id"));
3272 break;
3274 case "SEARCH":
3275 # unset($args["version"]);
3276 # unset($args["flags"]);
3277 break;
3279 default:
3280 break;
3283 #-- handle {meta} sub array as needed
3284 if (is_array(@$args["meta"])) {
3285 $args["meta"] = serialize($args["meta"]);
3288 #-- database plugin
3289 if (($pf) || ($pf = @$GLOBALS["ewiki_plugins"]["database"][0])) {
3290 $r = $pf($action, $args, $sw1, $sw2);
3292 else {
3293 ewiki_log("DB layer: no backend!", 0);
3294 $r = false;
3297 #-- database layer generation 2 abstraction
3298 if (is_array($r) && (($action=="SEARCH") || ($action=="GETALL"))) {
3299 $z = new ewiki_dbquery_result(array_keys($args));
3300 foreach ($r as $id=>$row) {
3301 $z->add($row);
3303 $r = $z;
3306 #-- extract {meta} sub array
3307 if (is_array($r) && !is_array(@$r["meta"]) && strlen(@$r["meta"])) {
3308 $r["meta"] = unserialize($r["meta"]);
3311 return($r);
3316 /* returned for SEARCH and GETALL queries, as those operations are
3317 otherwise too memory exhaustive
3319 class ewiki_dbquery_result {
3321 var $keys = array();
3322 var $entries = array();
3323 var $buffer = EWIKI_DBQUERY_BUFFER;
3324 var $size = 0;
3326 function ewiki_dbquery_result($keys) {
3327 $keys = @array_merge($keys, array(-50=>"id", "version", "flags"));
3328 $this->keys = array_unique($keys);
3331 function add($row) {
3332 if (is_array($row)) {
3333 if ($this->buffer) {
3334 $this->size += strlen(serialize($row));
3335 $this->buffer = $this->size <= EWIKI_DBQUERY_BUFFER;
3337 else {
3338 $row = $row["id"];
3341 $this->entries[] = $row;
3344 function get($all=0, $flags=0x00) {
3345 $row = array();
3347 $prot_hide = ($flags&0x0020) && EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING;
3348 do {
3349 if (count($this->entries)) {
3351 #-- fetch very first entry from $entries list
3352 $r = array_shift($this->entries);
3354 #-- finish if buffered entry
3355 if (is_array($r) && !$all) {
3356 $row = $r;
3358 #-- else refetch complete entry from database
3359 else {
3360 if (is_array($r)) {
3361 $r = $r["id"];
3363 $r = ewiki_database("GET", array("id"=>$r));
3364 if (!$all) {
3365 foreach ($this->keys as $key) {
3366 $row[$key] = $r[$key];
3368 } else {
3369 $row = $r;
3372 unset($r);
3374 else {
3375 return(NULL); // no more entries
3378 #-- expand {meta} field
3379 if (is_array($row) && is_string(@$row["meta"])) {
3380 $row["meta"] = unserialize($row["meta"]);
3383 #-- drop unwanted results
3384 if ($prot_hide && !ewiki_auth($row["id"], $row, $ewiki_action)) {
3385 $row = array();
3387 } while ($prot_hide && empty($row));
3389 return($row);
3392 function count() {
3393 return(count($this->entries));
3399 /* MySQL database backend
3400 (default)
3401 Note: this is of course an abuse of the relational database scheme,
3402 but neccessary for real db independence and abstraction
3404 function ewiki_database_mysql($action, &$args, $sw1, $sw2) {
3406 #-- reconnect to the database (if multiple are used)
3407 #<off># mysql_ping($GLOBALS["db"]);
3409 #-- result array
3410 $r = array();
3412 switch($action) {
3414 /* Returns database entry as array for the page whose name was given
3415 with the "id" key in the $args array, usually fetches the latest
3416 version of a page, unless a specific "version" was requested in
3417 the $args array.
3419 case "GET":
3420 $id = "'" . mysql_escape_string($args["id"]) . "'";
3421 ($version = 0 + @$args["version"]) and ($version = "AND (version=$version)") or ($version="");
3422 $result = mysql_query("SELECT * FROM " . EWIKI_DB_TABLE_NAME
3423 . " WHERE (pagename=$id) $version ORDER BY version DESC LIMIT 1"
3425 if ($result && ($r = mysql_fetch_array($result, MYSQL_ASSOC))) {
3426 $r["id"] = $r["pagename"];
3427 unset($r["pagename"]);
3429 if (strlen($r["meta"])) {
3430 $r["meta"] = @unserialize($r["meta"]);
3432 break;
3436 /* Increases the hit counter for the page name given in $args array
3437 with "id" index key.
3439 case "HIT":
3440 mysql_query("UPDATE " . EWIKI_DB_TABLE_NAME . " SET hits=(hits+1) WHERE pagename='" . mysql_escape_string($args["id"]) . "'");
3441 break;
3445 /* Stores the $data array into the database, while not overwriting
3446 existing entries (using WRITE); returns 0 on failure and 1 if
3447 saved correctly.
3449 case "OVERWRITE": // fall-through
3450 $COMMAND = "REPLACE";
3452 case "WRITE":
3453 $args["pagename"] = $args["id"];
3454 unset($args["id"]);
3456 if (is_array($args["meta"])) {
3457 $args["meta"] = serialize($args["meta"]);
3460 $sql1 = $sql2 = "";
3461 foreach ($args as $index => $value) {
3462 if (is_int($index)) {
3463 continue;
3465 $a = ($sql1 ? ', ' : '');
3466 $sql1 .= $a . $index;
3467 $sql2 .= $a . "'" . mysql_escape_string($value) . "'";
3470 strlen(@$COMMAND) || ($COMMAND = "INSERT");
3472 $result = mysql_query("$COMMAND INTO " . EWIKI_DB_TABLE_NAME .
3473 " (" . $sql1 . ") VALUES (" . $sql2 . ")"
3476 return($result && mysql_affected_rows() ?1:0);
3477 break;
3481 /* Checks for existence of the WikiPages whose names are given in
3482 the $args array. Returns an array with the specified WikiPageNames
3483 associated with values of "0" or "1" (stating if the page exists
3484 in the database). For images/binary db entries returns the "meta"
3485 field instead of an "1".
3487 case "FIND":
3488 $sql = "";
3489 foreach (array_values($args) as $id) if (strlen($id)) {
3490 $r[$id] = 0;
3491 $sql .= ($sql ? " OR " : "") .
3492 "(pagename='" . mysql_escape_string($id) . "')";
3494 $result = mysql_query($sql = "SELECT pagename AS id, meta FROM " .
3495 EWIKI_DB_TABLE_NAME . " WHERE $sql "
3497 while ($result && ($row = mysql_fetch_row($result))) {
3498 $r[$row[0]] = strpos($row[1], 's:5:"image"') ? $row[1] : 1;
3500 break;
3504 /* Returns an array of __all__ pages, where each entry is made up
3505 of the fields from the database requested with the $args array,
3506 e.g. array("flags","meta","lastmodified");
3508 case "GETALL":
3509 $result = mysql_query("SELECT pagename AS id, ".
3510 implode(", ", $args) .
3511 " FROM ". EWIKI_DB_TABLE_NAME .
3512 " GROUP BY id, version DESC"
3514 $r = new ewiki_dbquery_result($args);
3515 $drop = "";
3516 while ($result && ($row = mysql_fetch_array($result, MYSQL_ASSOC))) {
3517 $i = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
3518 if ($i != $drop) {
3519 $drop = $i;
3520 $r->add($row);
3523 break;
3527 /* Returns array of database entries (also arrays), where the one
3528 specified column matches the specified content string, for example
3529 $args = array("content" => "text...piece")
3530 is not guaranteed to only search/return the latest version of a page
3532 case "SEARCH":
3533 $field = implode("", array_keys($args));
3534 $content = strtolower(implode("", $args));
3535 if ($field == "id") { $field = "pagename"; }
3537 $result = mysql_query("SELECT pagename AS id, version, flags" .
3538 (EWIKI_DBQUERY_BUFFER && ($field!="pagename") ? ", $field" : "") .
3539 " FROM " . EWIKI_DB_TABLE_NAME .
3540 " WHERE LOCATE('" . mysql_escape_string($content) . "', LCASE($field)) " .
3541 " GROUP BY id, version DESC"
3543 $r = new ewiki_dbquery_result(array("id","version",$field));
3544 $drop = "";
3545 while ($result && ($row = mysql_fetch_array($result, MYSQL_ASSOC))) {
3546 $i = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
3547 if ($i != $drop) {
3548 $drop = $i;
3549 $r->add($row);
3552 break;
3556 case "DELETE":
3557 $id = mysql_escape_string($args["id"]);
3558 $version = $args["version"];
3559 mysql_query("DELETE FROM " . EWIKI_DB_TABLE_NAME ."
3560 WHERE pagename='$id' AND version=$version");
3561 break;
3565 case "INIT":
3566 mysql_query("CREATE TABLE " . EWIKI_DB_TABLE_NAME ."
3567 (pagename VARCHAR(160) NOT NULL,
3568 version INTEGER UNSIGNED NOT NULL DEFAULT 0,
3569 flags INTEGER UNSIGNED DEFAULT 0,
3570 content MEDIUMTEXT,
3571 author VARCHAR(100) DEFAULT 'ewiki',
3572 userid INTEGER UNSIGNED DEFAULT 0,
3573 created INTEGER UNSIGNED DEFAULT ".time().",
3574 lastmodified INTEGER UNSIGNED DEFAULT 0,
3575 refs MEDIUMTEXT,
3576 meta MEDIUMTEXT,
3577 hits INTEGER UNSIGNED DEFAULT 0,
3578 PRIMARY KEY id (pagename, version) )
3580 echo mysql_error();
3581 break;
3583 default:
3586 return($r);
3591 </script>