bd82f686362659d27fe2a79b491403713cef2c2d
[moodle.git] / mod / wiki / ewiki / ewiki.php
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();
19   ?>
21 */
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", current_charset());
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", "");
92     }
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   
100     }
101 #### END MOODLE CHANGES
102    
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"]
194         );
195     $ewiki_config["action_links"]["info"] = @array_merge(array(
196         "view" => "browse",
197         "edit" => "fetchback",
198     ), @$ewiki_config["action_links"]["info"]
199         );
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;",
236            ),
237            "wm_source" => array(
238         "%%%" => "<br />",
239         "\t" => "        ",
240         "\n;:" => "\n      ",   # workaround, replaces the old ;:
241            ),
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"),
248            ),
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>"),
262            ),
263            "wm_start_end" => array(
264            ),
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),
273            ),
274            "format_params" => array(
275         "scan_links" => 1,
276         "html" => EWIKI_ALLOW_HTML,
277         "mpi" => 1,
278            ),
279         );
280         foreach ($ewiki_config_DEFAULTSTMP as $set => $val) {
281            if (!isset($ewiki_config[$set])) {
282               $ewiki_config[$set] = $val;
283            }
284            elseif (is_array($val)) foreach ($val as $vali=>$valv) {
285               if (is_int($vali)) {
286                  $ewiki_config[$set][] = $valv;
287               }
288               elseif (!isset($ewiki_config[$set][$vali])) {
289                  $ewiki_config[$set][$vali] = $valv;
290               }
291            }
292         }
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.");
304            }
305            $pf($GLOBALS);
306         }
307     unset($ewiki_plugins["init"]);
309     #-- text  (never remove the "C" or "en" sections!)
310         #
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>',
314         ));
315         #
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.",
352     ));
353         #
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.",
390         ));
391         #
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).",
430     ));
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/",
460     ));
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.
473 */
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);
483    }
484    if (!strlen($id)) {
485       $id = ewiki_id();
486    }
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);
493    }
494    elseif (EWIKI_USE_ACTION_PARAM && isset($_REQUEST["action"])) {
495       $action = $_REQUEST["action"];
496    }
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
504    );
505    if (!isset($_REQUEST["content"]) && ($dquery["version"] = @$_REQUEST["version"])) {
506       $dquery["forced_version"] = $dquery["version"];
507    }
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
515       }
516       elseif (!EWIKI_PROTECTED_MODE || !ewiki_auth($id, $data, $action, 0, 1) && ($ewiki_ring!=0)) {
517          return(ewiki_t("DISABLEDPAGE"));
518       }
519    }
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";
528       }
529       else {
530          $data["content"] = ewiki_t("DOESNOTEXIST");
531       }
532    }
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);
538       }
539       unset($ewiki_plugins["page_init"]);
540    }
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);
547       }
548    }
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; }
556    }  }
558    #-- finished by handler
559    if ($handler_o) {
560       $o .= $handler_o;
561    }
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);
565    }
566    #-- internal pages
567    elseif ($pf_page && function_exists($pf_page)) {
568       $o .= $pf_page($id, $data, $action);
569    }
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
580       }
582       $o .= $pf($id, $data, $action);
583    }
585    #-- error instead of page?
586    if (empty($o) && $ewiki_errmsg) {
587       $o = $ewiki_errmsg;
588    }
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);
595       }
596    }
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));
613       }
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
620       }
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\"");
625       }
626    }
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);
650    }
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));
668    }
669    #-- disabled
670    elseif (!$ewiki_config["print_title"]) {
671       return("");
672    }
674    #-- get id
675    if (empty($id)) {
676       $id = $ewiki_id;
677    }
679    #-- get title
680    if (!strlen($title)) {
681       $title = $ewiki_title;  // already in &html; format
682    }
683    elseif ($ewiki_config["split_title"] && $may_split) {
684       $title = ewiki_split_title($title, $ewiki_config["split_title"], 0&($title!=$ewiki_title));
685    }
686    else {
687       $title = s($title);
688    }
690    #-- title mangling
691    if ($pf_a = @$ewiki_plugins["title_transform"]) {
692       foreach ($pf_a as $pf) { $pf($id, $title, $go_action); }
693    }
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;
699       }
700       if ($uu = @$ewiki_config["link_title_url"]) {
701          $href = $uu;
702          unset($ewiki_config["link_title_url"]);
703       }
704       else {
705          $href = ewiki_script($go_action, $id);
706       }
707       $o = '<a href="' . $href . '">' . ($title) . '</a>';
708    }
709    else {
710       $o = $title;
711    }
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)),
728    );
729    $o .= $ewiki_plugins["render"][0] ($data["content"], $render_args);
730    if (!$all) {
731       return($o);
732    }
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); }
743    }
744    if ($pf_a = $ewiki_plugins["view_final"]) {
745       ksort($pf_a);
746       foreach ($pf_a as $n => $pf) { $pf($o, $id, $data, $action); }
747    }
749    if (!empty($_REQUEST["thankyou"]) && $ewiki_config["edit_thank_you"]) {
750       $o = ewiki_t("THANKSFORCONTRIBUTION") . $o;
751    }
753    
754    if (EWIKI_HIT_COUNTING) {
755       ewiki_database("HIT", $data);
756    }
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
770 */
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;
780    }
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
795 */
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;
799       
800    #-- get base script url from config vars
801    if (empty($script)) {
802       $script = &$ewiki_config[!$bin?"script":"script_binary"];
803    }
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");
811       }
812       else {
813          $id = $asid;
814          $asid = "";
815       }
816    }
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);
824       }
825    }
826    #-- action= parameter
827    if (EWIKI_USE_ACTION_PARAM >= 2) {
828       $params = "action=$asid" . (strlen($params)?"&":"") . $params;
829       $asid = "";
830    }
832    #-- workaround slashes in $id
833    if (empty($asid) && (strpos($id, EWIKI_ACTION_SEP_CHAR) !== false) && !$bin) {
834       $asid = "view";
835    }
836    /*paranoia*/ $asid = trim($asid, EWIKI_ACTION_SEP_CHAR);
838    #-- make url
839    if (EWIKI_URLENCODE) {
840       $id = urlencode($id);
841       $asid = urlencode($asid);
842    }
843    else {
844       # only urlencode &, %, ? for example
845    }
846    $url = $script;
847    if ($asid) {
848       $id = $asid . EWIKI_ACTION_SEP_CHAR . $id;  #= "action/PageName"
849    }
850    if (strpos($url, "%s") !== false) {
851       $url = str_replace("%s", $id, $url);
852    }
853    else {
854       $url .= $id;
855    }
857    #-- add url params
858    if (strlen($params)) {
859       $url .= (strpos($url,"?")!==false ? "&":"?") . $params;
860    }
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); 
869    }
870    return($url);
874 /*  this ewiki_script() wrapper is used to generate URLs to binary
875     content in the ewiki database
876 */
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);
886    }
888    #-- else get standard URL (thru ewiki.php) from ewiki_script()
889    else {
890       $url = ewiki_script($asid, $id, $params, "_BINARY=1");
891    }
893    return($url);
897 /*  this function returns the absolute ewiki_script url, if EWIKI_SCRIPT_URL
898     is set, else it guesses the value
899 */
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);
910    }
911    elseif (strpos($req_uri, $scr_current) !== false) {
912       $url = str_replace($req_uri, $scr_current, $scr_template);
913    }
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, "?"));
917    }
918    elseif (strpos($req_uri, $sn = $_SERVER["SCRIPT_NAME"])) {
919       $url = $sn . "?id=";
920    }
921    else {
922       return(NULL);   #-- could not guess it
923    }
924  
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.");
942    }
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"];
952       }
953    }
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;
964          }
965       }
966       return($r);
967    }
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;
988       }
989       elseif ($is_num) {
990          $id = $title = $add_text;
991          $add_text = "";
992       }
993       elseif ($value_as_title) {
994          $title = $add_text;
995          $add_text = "";
996       }
998       $lines[] = '<a href="' . ewiki_script("", $id, $params) . '">' . s($title) . '</a> ' . $add_text;
1000       if (($limit > 0)  &&  ($n++ >= $limit)) {
1001          break;
1002       }
1003    }
1005    if ($pf_a = @$ewiki_plugins["list_transform"])
1006    foreach ($pf_a as $pf_transform) {
1007       $pf_transform($lines);
1008    }
1010    if (($pf_list) || ($pf_list = @$ewiki_plugins["list_pages"][0])) {
1011       $o = $pf_list($lines);
1012    }
1013    elseif($lines) {
1014       $o = "&middot; " . implode("<br />\n&middot; ", $lines) . "<br />\n";
1015    }
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}
1034       ));
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];
1040          }
1041       }
1042    }
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);
1053       }
1054       $sorted[$name] = get_string(strtolower($print),"wiki",$value);
1055    ##### BEGIN MOODLE ADDITION #####
1056    }
1057    $o .= ewiki_list_pages($sorted);
1058    
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>';
1102    }
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);
1110       }
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;
1122             }
1124             $found[] = $row["id"];
1125          }
1126       }
1128       $o .= ewiki_list_pages($found);
1129    }
1130  
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",
1151    );
1152    $show = array(
1153       "version", "author", "userid", "created",
1154       "lastmodified", "refs",
1155       "flags", "meta", "content"
1156    );
1158    #-- versions to show
1159    $v_start = $data["version"];
1160    if ( ($uu=@$_REQUEST[EWIKI_UP_PAGENUM]) && ($uu<=$v_start) ) {
1161       $v_start = $uu;
1162    }
1163    $v_end = $v_start - $ewiki_config["list_limit"] + 1;
1164    if ( ($uu=@$_REQUEST[EWIKI_UP_PAGEEND]) && ($uu<=$v_start) ) {
1165       $v_end = $uu;
1166    }
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;
1177       }
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;';
1188          }
1189          $commands .= '<a href="' .
1190            ewiki_script($thisaction, $id, array("version"=>$current["version"])) .
1191            '">' . get_string($title,"wiki") . '</a>';
1192    ##### END MOODLE ADDITION #####
1193       }
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";
1206             } }
1207             $value = $str;
1208          }
1209          elseif ($value >= UNIX_MILLENNIUM) {    #-- {lastmodified}, {created}
1210             #### BEGIN MOODLE CHANGE
1211             $value=userdate($value);
1212             #$value = strftime("%c", $value);
1213             #### END MOODLE CHANGE
1214          }
1215          elseif ($i == "content") {
1216             continue;  // MOODLE DOESN'T CARE
1217             $value = strlen(trim($value)) . " bytes";
1218             $i = "content size";
1219          }
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");
1226             }
1227             $value = trim(implode(", ", $a));
1228             if (!$value) {
1229                 continue;
1230             }
1231          }
1232          elseif (strpos($value, "\n") !== false) {       #-- also for {refs}
1233             $value = str_replace("\n", ", ", trim($value));
1234             if (!$value) {
1235                 continue;
1236             }
1237          }
1238          elseif ($i == "version") {
1239             $value = '<a href="' .
1240                ewiki_script("", $id, array("version"=>$value)) . '">' .
1241                $value . '</a> '."($commands)";
1242          }
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 . " ";
1250               }
1251             }
1252             $value = $fstr;
1253          }
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);
1258          }
1259          elseif ($i == "userid") {
1260              $i = 'author';
1261              if ($user = get_record('user', 'id', $value)) {
1262                  if (!isset($course->id)) {
1263                      $course->id = 1;
1264                  }
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'];
1270              }
1271          }
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 #####
1278       }
1280       $o .= "</table><br /><br />\n";
1282    }
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 />";
1287    }
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"];
1301    }
1302    if ($overlap < 1) {
1303       $overlap = (int) ($limit * $overlap);
1304    }
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;
1319          }
1320       }
1321       else {
1322          $e = min($end, $e);
1323          if ($e >= $collapse_last * $limit) {
1324             $e = $end;
1325          }
1326       }
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;
1334       }
1335    }
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"]);
1360    }
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);
1366       }
1367    }
1369    #-- permission checks
1370    if (isset($ewiki_ring)) {
1371       $ring = $ewiki_ring;
1372    } else { 
1373       $ring = 3;
1374    }
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);
1382       }
1384       #-- flag checking
1385       if (($flags & EWIKI_DB_F_READONLY) and ($ring >= 2)) {
1386          return(ewiki_t("CANNOTCHANGEPAGE"));
1387       }
1388       if (($flags) and (($flags & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT) and ($ring >= 1)) {
1389          return(ewiki_t("CANNOTCHANGEPAGE"));
1390       }
1391    }
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);
1399    }
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 />";
1418             }
1420          }
1421          if (!$error) {
1423             #-- new pages` flags
1424             if (! ($set_flags = @$data["flags"] & EWIKI_DB_F_COPYMASK)) {
1425                $set_flags = 1;
1426             }
1427             if (EWIKI_ALLOW_HTML) {
1428                $set_flags |= EWIKI_DB_F_HTML;
1429             }
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",
1440             );
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);
1447                }
1448             }
1450             #-- save
1451             if (!$save || !ewiki_database("WRITE", $save)) {
1453                $o .= $ewiki_errmsg ? $ewiki_errmsg : ewiki_t("ERRORSAVING");
1455             }
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);
1465                  
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");
1471                   }
1472                   else {
1473                      $o .= '<meta http-equiv="Refresh" content="0; URL='.s($url).'">';
1474                   }
1475                }
1477             }
1479          }
1481          //@REWORK
1482          // header("Reload-Location: " . ewiki_script("", $id, "", 0, 0, ewiki_script_url()) );
1484    }
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);
1492       }
1493    }
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;
1509    }
1514 #-- edit <textarea>
1515 function ewiki_page_edit_form(&$id, &$data, &$hidden_postdata) {
1516    global $ewiki_plugins, $ewiki_config, $moodle_format;   
1518    $o='';
1519       
1520    #-- previously edited, or db fetched content
1521    if (@$_REQUEST["content"] || @$_REQUEST["version"]) {
1522       $data = array(
1523          "version" => &$_REQUEST["version"],
1524          "content" => &$_REQUEST["content"]
1525       );
1526    }
1527    else {
1528       if (empty($data["version"])) {
1529          $data["version"] = 1;
1530       }
1531       @$data["content"] .= "";
1532    }
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 .= '<fieldset class="invisiblefieldset">';
1548    #-- additional POST vars
1549    foreach ($hidden_postdata as $name => $value) {
1550        $o .= '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
1551    }
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"]);
1567      }
1568      print_textarea($usehtmleditor, $rows, $cols, 680, 400, "content", $oldtext);
1569      echo '</td></tr></table>';
1571      $o .= ob_get_contents();     
1572      //yu: this is causing problem and i don't know where to put it   
1573      if ($usehtmleditor) {
1574         use_html_editor("content");
1575      }
1576      ob_end_clean();     
1578    } else {
1579    ##### END MOODLE ADDITION #####
1581      $o .= '<textarea wrap="soft" id="ewiki_content" name="content" rows="'.$rows.'" cols="'.$cols.'">'
1582         . s($data["content"]) . "</textarea>"
1583         . $GLOBALS["ewiki_t"]["C"]["EDIT_TEXTAREA_RESIZE_JS"];
1585    ##### BEGIN MOODLE ADDITION #####
1586    }
1587    ##### END MOODLE ADDITION #####
1588    
1589    #-- more <input> elements before the submit button
1590    if ($pf_a = $ewiki_plugins["edit_form_insert"]) foreach ($pf_a as $pf) {
1591       $o .= $pf($id, $data, $action);
1592    }
1594    ##### BEGIN MOODLE ADDITION (Cancel Editing into Button) #####
1595    $o .= "\n<br />\n"
1596       . '<input type="submit" name="save" value="'. ewiki_t("SAVE") . '" />'."\n"
1597       . '<input type="submit" name="preview" value="'. ewiki_t("PREVIEW") . '" />' . "\n"
1598       . '<input type="submit" name="canceledit" value="'. ewiki_t("CANCEL_EDIT") . '" />' . "\n";
1599 #      . ' &nbsp; <a href="'. ewiki_script("", $id) . '">' . ewiki_t("CANCEL_EDIT") . '</a>';
1600    ##### END MOODLE ADDITION #####
1602    #-- additional form elements
1603    if ($pf_a = $ewiki_plugins["edit_form_append"]) foreach ($pf_a as $pf) {
1604       $o .= $pf($id, $data, $action);
1605    }
1607    $o .= "\n</fieldset></form>\n";
1608    //   . ewiki_t("EDIT_FORM_2");  // MOODLE DELETION
1610    return('<div class="edit-box">'. $o .'</div>');
1615 #-- pic upload form
1616 function ewiki_page_edit_form_final_imgupload(&$o, &$id, &$data, &$action) {
1617    if (EWIKI_SCRIPT_BINARY && EWIKI_UP_UPLOAD && EWIKI_IMAGE_MAXSIZE) {
1618       $o .= "\n<br />\n". '<div class="image-upload">'
1619       . '<form action='
1620       . '"'. ewiki_script_binary("", EWIKI_IDF_INTERNAL, "", "_UPLOAD=1") .'"'
1621       . ' method="post" enctype="multipart/form-data" target="_upload">'
1622       . '<fieldset class="invisiblefieldset">'
1623       . '<input type="hidden" name="MAX_FILE_SIZE" value="'.EWIKI_IMAGE_MAXSIZE.'" />'
1624       . '<input type="file" name="'.EWIKI_UP_UPLOAD.'"'
1625       . (defined("EWIKI_IMAGE_ACCEPT") ? ' accept="'.EWIKI_IMAGE_ACCEPT.'" />' : " />")
1626       . '<input type="hidden" name="'.EWIKI_UP_BINARY.'" value="'.EWIKI_IDF_INTERNAL.'" />'
1627       . '&nbsp;&nbsp;&nbsp;'
1628       . '<input type="submit" value="'.ewiki_t("UPLOAD_PICTURE_BUTTON").'" />'
1629       . '</fieldset></form></div>'. "\n";
1630   }
1634 function ewiki_page_edit_preview(&$data) {
1635 #### BEGIN MOODLE CHANGES   
1636    global $moodle_format;   
1637    $preview_text=$GLOBALS["ewiki_plugins"]["render"][0]($_REQUEST["content"], 1, EWIKI_ALLOW_HTML || (@$data["flags"]&EWIKI_DB_F_HTML));
1638    return( '<div class="preview">'
1639            . "<hr noshade>"
1640            . "<div align=\"right\">" . ewiki_t("PREVIEW") . "</div><hr noshade><br />\n"
1641            . format_text($preview_text, $moodle_format)
1642            . "<br /><br /><hr noshade><br />"
1643            . "</div>"
1644    );
1645 #### END MOODLE CHANGES   
1649 function ewiki_control_links($id, &$data, $action) {
1651    global $ewiki_plugins, $ewiki_ring, $ewiki_config;
1652    $action_links = & $ewiki_config["action_links"][$action];
1654    #-- disabled
1655    if (!$ewiki_config["control_line"]) {
1656       return("");
1657    }
1659    $o = "\n"
1660       . '<div align="right" class="action-links control-links">'
1661       . "\n<br />\n"
1662       . "<hr noshade>" . "\n";
1664    if (@$data["forced_version"]) {
1666       $o .= '<form action="' . ewiki_script("edit", $id) . '" method="post">' .
1667             '<fieldset class="invisiblefieldset">'.
1668             '<input type="hidden" name="edit" value="old" />' .
1669             '<input type="hidden" name="version" value="'.$data["forced_version"].'" />' .
1670             '<input type="submit" value="' . ewiki_t("OLDVERCOMEBACK") . '" /></form> ';
1671    }
1672    else {
1673       foreach ($action_links as $action => $title)
1674       if (!empty($ewiki_plugins["action"][$action]) || !empty($ewiki_plugins["action_always"][$action]) || strpos($action, ":/"))
1675       {
1676          if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($id, $data, $action))  { continue; }
1678          $o .= '<a href="'
1679             . (strpos($action, ":/") ? $action : ewiki_script($action, $id))
1680             . '">' . ewiki_t($title) . '</a> &middot; ';
1681       }
1682    }
1684    if ($data["lastmodified"] >= UNIX_MILLENNIUM) { 
1685       $o .= '<small>' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . '</small>';
1686    }
1688    $o .= "</div>\n";
1690    return($o);
1697 # ============================================================= rendering ===
1703 ########  ###   ###  #########  ###  ###   ###  #######
1704 ########  ####  ###  #########  ###  ####  ###  #######
1705 ###       ##### ###  ###             ##### ###  ###
1706 ######    #########  ###  ####  ###  #########  ######
1707 ######    #########  ###  ####  ###  #########  ######
1708 ###       ### #####  ###   ###  ###  ### #####  ###
1709 ########  ###  ####  #########  ###  ###  ####  #######
1710 ########  ###   ###  #########  ###  ###   ###  #######
1713 /*
1714    The _format() function transforms $wiki_source pages into <html> strings,
1715    also calls various markup and helper plugins during the transformation
1716    process. The $params array can activate various features and extensions.
1717    only accepts UNIX newlines!
1718 */
1719 function ewiki_format (
1720             $wiki_source,
1721             $params = array()
1722          )
1724    global $ewiki_links, $ewiki_plugins, $ewiki_config;
1726    #-- state vars
1727    $params = @array_merge($ewiki_config["format_params"], $params);
1728    $s = array(
1729       "in" => 0,         # current input $iii[] block array index
1730       "para" => "",
1731       "line" => "",
1732       "post" => "",      # string to append after current line/paragraph
1733       "line_i" => 0,
1734       "lines" => array(),
1735       "list" => "",      # lists
1736       "tbl" => 0,        # open table?
1737       "indent" => 0,     # indentation
1738       "close" => array(),
1739    );
1740    #-- aliases
1741    $in = &$s["in"]; 
1742    $line = &$s["line"];
1743    $lines = &$s["lines"];
1744    $para = &$s["para"];
1745    $post = &$s["post"];
1746    $list = &$s["list"];
1748    #-- input and output arrays
1749    if ($wiki_source[0] == "<") {            # also prepend an empty line 
1750       $wiki_source = "\n" . $wiki_source;    # for faster strpos() searchs
1751    }
1752    $iii = array(
1753       0 => array(
1754          0 => $wiki_source."\n",    # body + empty line
1755          1 => 0x0FFF,               # flags (0x1=WikiMarkup, 0x2=WikiLinks, 0x100=BlockPlugins)
1756          2 => "core",               # block plugin name
1757       )
1758    );
1759    $ooo = array(
1760    );
1761    unset($wiki_source);
1763    #-- plugins
1764    $pf_tbl = @$ewiki_plugins["format_table"][0];
1765    $pf_line = @$ewiki_plugins["format_line"];
1767    #-- wikimarkup (wm)
1768    $htmlentities = $ewiki_config["htmlentities"];
1769    $wm_indent = &$ewiki_config["wm_indent"];
1770    $wm_table_defaults = &$ewiki_config["wm_table_defaults"];
1771    $wm_source = &$ewiki_config["wm_source"];
1772    $wm_list = &$ewiki_config["wm_list"];
1773    $wm_list_chars = implode("", array_keys($wm_list));
1774    $wm_style = &$ewiki_config["wm_style"];
1775    $wm_start_end = &$ewiki_config["wm_start_end"];
1777    #-- eleminate html
1778    $iii[0][0] = strtr($iii[0][0], $htmlentities);
1779    unset($htmlentities["&"]);
1781    #-- pre-processing plugins (working on wiki source)
1782    if ($pf_source = $ewiki_plugins["format_source"]) {
1783       foreach ($pf_source as $pf) $pf(&$iii[0][0]);
1784    }
1786    #-- simple markup
1787    $iii[0][0] = strtr($iii[0][0], $wm_source);
1789    #-- separate input into blocks ------------------------------------------
1790    foreach ($ewiki_config["format_block"] as $btype => $binfo) {
1792       #-- disabled block plugin?
1793       if ($binfo[2] && !$params[$binfo[2]])  {
1794          continue;
1795       }
1797       #-- traverse $iii[]
1798       $in = -1;
1799       while ((++$in) < count($iii)) {
1801          #-- search fragment delimeters
1802          if ($iii[$in][1] & 0x0100)
1803          while (
1804             ($c = & $iii[$in][0]) &&
1805             (($l = strpos($c, $binfo[0])) !== false) &&
1806             ($r = strpos($c, $binfo[1], $l))   )
1807          {
1808             $l_len = strlen($binfo[0]);
1809             $r_len = strlen($binfo[1]);
1811             $repl = array();
1812             // pre-text
1813             if (($l > 0) && trim($text = substr($c, 0, $l))) {
1814                $repl[] = array($text, 0xFFFF, "core");
1815             }
1816             // the extracted part
1817             if (trim($text = substr($c, $l+$l_len, $r-$l-$r_len))) {
1818                $repl[] = array($text, $binfo[3], "$btype");
1819             }
1820             // rest
1821             if (($r+$r_len < strlen($c)) && trim($text = substr($c, $r+$r_len))) {
1822                $repl[] = array($text, 0xFFFF, "core");
1823             }
1824             array_splice($iii, $in, 1, $repl);
1826             $in += 1;
1827          }
1828       }
1829    }
1831    #-- run format_block plugins
1832    $in = -1;
1833    while ((++$in) < count($iii)) {
1834       if (($btype = $iii[$in][2]) && ($pf_a = $ewiki_plugins["format_block"][$btype])) {
1835          $c = &$iii[$in][0];
1836          foreach ($pf_a as $pf) {   
1837             # current buffer $c and pointer $in into $iii[] and state $s
1838             $pf($c, $in, $iii, $s, $btype);
1839          }
1840       }
1841    }
1843    #-- wiki markup ------------------------------------------------------
1844    $para = "";
1845    $in = -1;   
1846    while ((++$in) < count($iii)) {
1847       #-- wikimarkup
1848       if ($iii[$in][1] & 0x0001) {
1850          #-- input $lines buffer, and output buffer $ooo array
1851          $lines = explode("\n", $iii[$in][0]);
1852          $ooo[$in] = array(
1853             0 => "",
1854             1 => $iii[$in][1]
1855          );
1856          $out = &$ooo[$in][0];
1857          $s["block"] = ($iii[$in][2] != "core");  # disables indentation & paragraphs
1859          #-- walk through wiki source lines
1860          $line_max = count($lines);
1861          foreach ($lines as $s["line_i"]=>$line) {
1862 //echo "<pre>line={$s[line_i]}:".htmlspecialchars($line).":".htmlspecialchars($line[0])."</pre>";
1864             #-- empty lines separate paragraphs
1865             if (!strlen($line)) {
1866                ewiki_format_close_para($ooo, $s);
1867                ewiki_format_close_tags($ooo, $s);
1868                if (!$s["block"]) {
1869                   $out .= "\n";
1870                }
1871             }
1872             #-- horiz bar
1873             if (!strncmp($line, "----", 4)) {
1874                $out .= "<hr noshade>\n";
1875                continue;
1876             }
1877             #-- html comment
1878             #if (!strncmp($line, "&lt;!--", 7)) {
1879             #   $out .= "<!-- " . htmlentities(str_replace("--", "__", substr($line, 7))) . " -->\n";
1880             #   continue;
1881             #}
1883             ($c0 = $line[0])
1884             or ($c0 = "\000");
1886             #-- tables
1887             ### MOODLE CHANGE: TRIM
1888             if (($c0 == "|") && ($line[strlen(trim($line))-1] == "|")) {
1889                if (!$s["tbl"]) {
1890                   ewiki_format_close_para($ooo, $s);
1891                   ewiki_format_close_tags($ooo, $s);
1892                   $s["list"] = "";
1893                }
1894                $line = substr($line, 1, -1);
1895                if ($pf_tbl) { 
1896                   $pf_tbl($line, $ooo, $s);
1897                }
1898                else {
1899                   if (!$s["tbl"]) {  
1900                      $out .= "<table " . $wm_table_defaults . ">\n";
1901                      $s["close"][] = "\n</table>"; 
1902                   }
1903                   $line = "<tr>\n<td>" . str_replace("|", "</td>\n<td>", $line) . "</td>\n</tr>";
1904                }
1905                $s["tbl"] = 1;
1906                $para = false;
1907             }
1908             elseif ($s["tbl"]) {
1909                $s["tbl"] = 0;
1910             }
1913             #-- headlines
1914             if (($c0 == "!") && ($excl = strspn($line, "!"))) {
1915                if ($excl > 3) { 
1916                   $excl = 3;
1917                }
1918                $line = substr($line, $excl);
1919                $excl = 5 - $excl;
1920                $line = "<h$excl>" . $line . "</h$excl>";
1921                if ($para) {
1922                   ewiki_format_close_para($ooo, $s);
1923                }
1924                ewiki_format_close_tags($ooo, $s);
1925                $para = false;
1926             }
1928             #-- whole-line markup
1929             # ???
1932             #-- indentation (space/tab markup)
1933             $n_indent = 0;
1934             if (!$list && (!$s["block"]) && ($n_indent = strspn($line, " "))) {
1935                $n_indent = (int) ($n_indent / 2.65);
1936                while ($n_indent > $s["indent"]) { 
1937                   $out .= $wm_indent;
1938                   $s["indent"]++;
1939                }
1940             }
1941             while ($n_indent < $s["indent"]) { 
1942                $out .= "</div>\n";
1943                $s["indent"]--;
1944             }
1947             #-- text style triggers
1948             foreach ($wm_style as $find=>$replace) {
1949                $find_len = strlen($find);
1950                $loop = 20;
1951                while(($loop--) && (($l = strpos($line, $find)) !== false) && ($r = strpos($line, $find, $l + $find_len))) {
1952                   $line = substr($line, 0, $l) . $replace[0] .
1953                           substr($line, $l + strlen($find), $r - $l - $find_len) .
1954                           $replace[1] . substr($line, $r + $find_len);
1955                }
1956             }
1959             #-- list markup
1960             if (isset($wm_list[$c0])) {
1961                if (!$list) {
1962                   ewiki_format_close_para($ooo, $s);
1963                   ewiki_format_close_tags($ooo, $s);
1964                }
1965                $new_len = strspn($line, $wm_list_chars);
1966                $new_list = substr($line, 0, $new_len);
1967                $old_len = strlen($list);
1968                $lchar = $new_list[$new_len-1];
1969                list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
1971                #-- cut line
1972                $line = substr($line, $new_len);
1973                $lspace = "";
1974                $linsert = "";
1975                if ($ltag1) {
1976                   $linsert = "<$ltag1>" . strtok($line, $lchar) . "</$ltag1> ";
1977                   $line = strtok("\000");
1978                }
1980                #-- add another <li>st entry
1981                if ($new_len == $old_len) {
1982                   $lspace = str_repeat("  ", $new_len);
1983                   $out .=  "</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
1984                }
1985                #-- add list
1986                elseif ($new_len > $old_len) {
1987                   while ($new_len > ($old_len=strlen($list))) {
1988                      $lchar = $new_list[$old_len];
1989                      $list .= $lchar;
1990                      list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
1991                      $lclose = strtok($lopen, " ");
1992                      $lspace = str_repeat("  ", $new_len);
1993                      
1994                      $out .= "\n$lspace<$lopen>\n" . "$lspace". $linsert . "<$ltag2>";
1995                      $s["close"][] = "$lspace</$lclose>";
1996                      $s["close"][] = "$lspace</$ltag2>";
1997                   }
1998                }
1999                #-- close lists
2000                else {
2001                   while ($new_len < ($old_len=strlen($list))) {
2002                      $remove = $old_len-$new_len;
2003                      ewiki_format_close_tags($ooo, $s, 2*$remove);
2004                      $list = substr($list, 0, -$remove);
2005                   }
2006                   if ($new_len) {
2007                      $lspace = str_repeat("  ", $new_len);
2008                      $out .= "$lspace</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
2009                   }
2010                }
2012                $list = $new_list;
2013                $para = false;
2014             }
2015             elseif ($list) {
2016                if ($c0 == " ") {
2017                   $para = false;
2018                }
2019                else {
2020                   ewiki_format_close_tags($ooo, $s);
2021                   $list = "";
2022                }
2023             }
2026             #-- start-end markup
2027             foreach ($wm_start_end as $d) {
2028                $len0 = strlen($d[0]);
2029                $loop = 20;
2030                while(($loop--) && (($l = strpos($line, $d[0])) !== false) && ($r = strpos($line, $d[1], $l + $len0))) {
2031                   $len1 = strlen($d[1]);
2032                   $line = substr($line, 0, $l) . $d[2] .
2033                           substr($line, $l + $len0, $r - $l - $len0) .
2034                           $replace[1] . substr($line, $r + $len1);
2035                }
2036             }
2038             #-- call wiki source formatting plugins that work on current line
2039             if ($pf_line) {
2040                foreach ($pf_line as $pf) $pf($out, $line, $post);
2041             }
2045             #-- add formatted line to page-output
2046             $line .= $post;
2047             if ($para === false) {
2048                $out .= $line;
2049                $para = "";
2050             }
2051             else {
2052                $para .= $line . "\n";
2053             }
2055          }
2057          #-- last block, or next not WikiSource?
2058          if (!isset($iii[$in+1]) || !($iii[$in+1][1] & 0x0011)) {
2059             ewiki_format_close_para($ooo, $s);
2060             ewiki_format_close_tags($ooo, $s);
2061          }
2062       }
2063       #-- copy as is into output buffer
2064       else {
2065          $ooo[$in] = $iii[$in];
2066       }
2067       $iii[$in] = array();
2068    }
2070    #-- wiki linking ------------------------------------------------------
2071    $scan_src = "";
2072    for ($in=0; $in<count($ooo); $in++) {
2073       if (EWIKI_HTML_CHARS && ($ooo[$in][1] & 0x0004)) {  # html character entities
2074          $ooo[$in][0] = str_replace("&amp;#", "&#", $ooo[$in][0]);
2075       }
2076       if ($ooo[$in][1] & 0x0022) {
2077          #-- join together multiple WikiSource blocks
2078          while (isset($ooo[$in+1]) && ($ooo[$in][1] & 0x0002) && ($ooo[$in+1][1] & 0x0002)) {
2079             $ooo[$in] = array(
2080                0 => $ooo[$in][0] . "\n" . $ooo[$in+1][0],
2081                1 => $ooo[$in][1] | $ooo[$in+1][1],
2082             );
2083             array_splice($ooo, $in+1, 1);
2084          }
2085       }
2086       $scan_src .= $ooo[$in][0];
2087    }
2090    #-- pre-scan
2091    if (1+$params["scan_links"]) {
2092       ewiki_scan_wikiwords($scan_src, $ewiki_links);
2093    }
2094    if ($pf_linkprep = $ewiki_plugins["format_prepare_linking"]) {
2095       foreach ($pf_linkprep as $pf) $pf($scan_src);
2096    }
2097    $scan_src = NULL;
2099    #-- finally the link-detection-regex
2100    for ($in=0; $in<count($ooo); $in++) {
2101       if ($ooo[$in][1] & 0x0002) {
2102       ##### BEGIN MOODLE ADDITION #####
2103       # No WikiLinks in Editor
2104       #################################  
2105         global $ewiki_use_editor, $ewiki_editor_content;
2106         if(!($ewiki_use_editor && $ewiki_editor_content)) {
2107       ##### END MOODLE ADDITION #####
2108           ewiki_render_wiki_links($ooo[$in][0]);
2109       ##### BEGIN MOODLE ADDITION #####
2110          }
2111       ##### END MOODLE ADDITION #####
2112       }
2113    }
2115    #-- fin: combine all blocks into html string ----------------------------
2116    $html = "";
2117    for ($in=0; $in<count($ooo); $in++) {
2118       $html .= $ooo[$in][0] . "\n";
2119       $ooo[$in] = 0;
2120    }
2121    #-- call post processing plugins
2122    if ($pf_final = $ewiki_plugins["format_final"]) {
2123       foreach ($pf_final as $pf) $pf($html);
2124    }
2125    return($html);
2130 function ewiki_format_close_para(&$ooo, &$s) {
2131    $out = &$ooo[$s["in"]][0];
2132    #-- output text block
2133    if (trim($s["para"])) {
2134       if (!$s["block"]) {
2135          #### MOODLE CHANGES
2136          global $ewiki_use_editor;
2137          if(!$ewiki_use_editor) {
2138            $s["para"] = "\n<p>\n" . ltrim($s["para"], "\n") . "</p>\n";
2139          }
2140          #### MOODLE CHANGES
2141       }
2142       #-- paragraph formation plugins
2143       if ($pf_a = $GLOBALS["ewiki_plugins"]["format_para"]) {
2144          foreach ($pf_a as $pf) {
2145             $pf($s["para"], $ooo, $s);
2146          }
2147       }
2148       $out .= $s["para"];
2149       $s["para"] = "";
2150    }
2151    #-- indentation
2152    while ($s["indent"]) {
2153       $out .= "</div>";
2154       $s["indent"]--;
2155    }
2159 function ewiki_format_close_tags(&$ooo, &$s, $count=100) {
2160    $out = &$ooo[$s["in"]][0];
2161    if (!is_array($s) || !is_array($s["close"])) { 
2162       die("\$s is garbaged == $s!!");
2163    }
2164    while (($count--) && ($add = array_pop($s["close"]))) {
2165       $out .= $add . "\n";
2166    }
2170 function ewiki_format_pre(&$str, &$in, &$iii, &$s, $btype) {
2171    $str = "<pre class=\"markup $btype\">" . $str . "</pre>";
2175 function ewiki_format_html(&$str, &$in, &$iii, &$s) {
2176    $he = array_reverse($GLOBALS["ewiki_config"]["htmlentities"]);
2177    $str = strtr($str, array_flip($he));
2178    $str = "<span class=\"markup html\">" . $str . "\n</span>\n"; 
2182 function ewiki_format_comment(&$str, &$in, &$iii, &$s, $btype) {
2183    $str = "<!-- "  . str_replace("--", "¯¯", $str) . " -->";
2189 /* unclean pre-scanning for WikiWords in a page,
2190    pre-query to the db */
2191 function ewiki_scan_wikiwords(&$wiki_source, &$ewiki_links, $se=0) {
2193    global $ewiki_config;
2195    #-- find matches
2196    preg_match_all($ewiki_config["wiki_pre_scan_regex"], $wiki_source, $uu);
2197    $uu = @array_merge($uu[1], $uu[2], $uu[3], $uu[4], (array)@$uu[5]);
2199    #-- clean up list, trim() spaces (allows more unclean regex) - page id unification
2200    foreach ($uu as $i=>$id) {
2201       $uu[$i] = trim($id);
2202    }
2203    unset($uu[""]);
2204    $uu = array_unique($uu);
2206    #-- query db
2207    $ewiki_links = ewiki_database("FIND",  $uu);
2209    #-- strip email adresses
2210    if ($se) {
2211       foreach ($ewiki_links as $c=>$uu) {
2212          if (strpos($c, "@") && (strpos($c, ".") || strpos($c, ":"))) {
2213             unset($ewiki_links[$c]);
2214          }
2215       }
2216    }
2222 /* regex on page content,
2223    handled by callback (see below)
2224 */
2225 function ewiki_render_wiki_links(&$o) {
2227    global $ewiki_links, $ewiki_config, $ewiki_plugins;
2229    #-- merge with dynamic pages list
2230    ewiki_merge_links($ewiki_links);
2232    #-- replace WikiWords
2233    $link_regex = &$ewiki_config["wiki_link_regex"];
2234    $o = preg_replace_callback($link_regex, "ewiki_link_regex_callback", $o);
2236    #-- cleanup
2237    unset($ewiki_links);
2241 /*
2242    combines with page plugin list,
2243    and makes all case-insensitive
2244 */
2245 function ewiki_merge_links(&$ewiki_links) {
2246    global $ewiki_plugins;
2247 #### BEGIN MOODLE CHANGES   
2248      global $ewiki_link_case;
2249      $ewiki_link_case=array();
2250 #### END MOODLE CHANGES
2251      if ($ewiki_links !== true) {
2252       foreach ($ewiki_plugins["page"] as $page=>$uu) {
2253          $ewiki_links[$page] = 1;
2254       }
2255 #### BEGIN MOODLE CHANGES   
2256      foreach($ewiki_links as $page => $uu) {
2257        if($uu) {
2258          $ewiki_link_case[strtolower($page)]=$page;  
2259        }        
2260      }
2261 #### END MOODLE CHANGES
2262       $ewiki_links = ewiki_array($ewiki_links);
2263    }
2269 /* link rendering (p)regex callback
2270    (ooutch, this is a complicated one)
2271 */
2272 function ewiki_link_regex_callback($uu, $force_noimg=0) {
2273    #print "<pre>"; print_r($uu); print "</pre>";
2274    global $ewiki_links, $ewiki_plugins, $ewiki_config, $ewiki_id;
2276    $str = trim($uu[0]);
2277    $type = array();
2278    $states = array();
2280    #-- link bracket '[' escaped with '!' or '~'
2281    if (($str[0] == "!") || ($str[0] == "~")) {
2282       return(substr($str, 1));
2283    }
2284    if ($str[0] == "#") {
2285       $states["define"] = 1;
2286       $str = substr($str, 1);
2287    }
2288    if ($str[0] == "[") {
2289       $states["brackets"] = 1;
2290       $str = substr($str, 1, -1);
2291    }
2293    #-- explicit title given via [ title | WikiLink ]
2294    $href = $title = strtok($str, "|");
2295    if ($uu = strtok("|")) {
2296       $href = $uu;
2297       $states["titled"] = 1;
2298    }
2299    #-- title and href swapped: swap back
2300    if (strpos("://", $title) || strpos($title, ":") && !strpos($href, ":")) {
2301       $uu = $title; $title = $href; $href = $uu;
2302    }
2304    #-- new entitling scheme [ url "title" ]
2305    if ((($l=strpos($str, '"')) < ($r=strrpos($str, '"'))) && ($l!==false) ) {
2306       $title = substr($str, $l + 1, $r - $l - 1);
2307       $href = substr($str, 0, $l) . substr($str, $r + 1);
2308       $states["titled"] = 1;
2309     }
2311    #-- strip spaces
2312    $spaces_l = ($href[0]==" ") ?1:0;
2313    $spaces_r = ($href[strlen($href)-1]==" ") ?1:0;
2314    $title = ltrim(trim($title), "^");
2315    $href = ltrim(trim($href), "^");
2317    #-- strip_htmlentities()
2318    if (1&&    (strpos($href, "&")!==false) && strpos($href, ";")) {
2319       foreach (array("&lt;"=>"<", "&gt;"=>">", "&amp;"=>"&") as $f=>$t) {
2320          $href = str_replace($f, $t, $href);
2321       }
2322    }
2323  
2324    #-- anchors
2325    $href2 = "";
2326    if (($p = strrpos($href, "#")) && ($p) && ($href[$p-1] != "&")) {
2327       $href2 = trim(substr($href, $p));
2328       $href = trim(substr($href, 0, $p));
2329    }
2330    elseif ($p === 0) {
2331       $states["define"] = 1;
2332    }
2333    if ($href == ".") {
2334       $href = $ewiki_id;
2335    }
2337    #-- for case-insensitivines
2338    $href_i = EWIKI_CASE_INSENSITIVE ? strtolower($href) : ($href);
2340    #-- injected URLs
2341    if (strpos($inj_url = $ewiki_links[$href_i], "://")) {
2342       if ($href==$title) { $href = $inj_url; }
2343    }
2345    #-- interwiki links
2346    if (strpos($href, ":") && ($uu = ewiki_interwiki($href, $type))) {
2347       $href = $uu;
2348       $str = "<a href=\"$href$href2\">$title</a>";
2349    }
2350    #-- action:WikiLinks
2351    elseif ($ewiki_plugins["action"][$a=strtolower(strtok($href, ":"))]) {
2352       $type = array($a, "action", "wikipage");
2353       $str = '<a href="' . ewiki_script($a, strtok("\000")) . '">' . $title . '</a>';
2354    }
2355    #-- page anchor definitions, if ($href[0]=="#")
2356    elseif (@$states["define"]) {
2357       $type = array("anchor");
2358       if ($title==$href) { $title="&nbsp;"; }
2359       $str = '<a name="' . s(ltrim($href, "#")) . '">' . ltrim($title, "#") . '</a>';
2360    }
2361    #-- inner page anchor jumps
2362    elseif (strlen($href2) && ($href==$ewiki_id) || ($href[0]=="#") && ($href2=&$href)) {
2363       $type = array("jump");
2364       $str = '<a href="' . s($href2) . '">' . $title . '</a>';
2365    }
2366    #-- ordinary internal WikiLinks
2367    elseif (($ewiki_links === true) || @$ewiki_links[$href_i]) {
2368       $type = array("wikipage");
2369 #### BEGIN MOODLE CHANGES   
2370       global $ewiki_link_case;
2371       $href_realcase=array_key_exists($href_i,$ewiki_link_case) ? $ewiki_link_case[$href_i] : $href;  
2372       $str = '<a href="' . ewiki_script("", $href_realcase) . s($href2)
2373            . '">' . $title . '</a>';
2374 #### END MOODLE CHANGES
2375    }
2376    #-- guess for mail@addresses, convert to URI if
2377    elseif (strpos($href, "@") && !strpos($href, ":")) {
2378       $type = array("email");
2379       $href = "mailto:" . $href;
2380    }
2381    #-- not found fallback
2382    else {
2383       $str = "";
2384       #-- a plugin may take care
2385       if ($pf_a = $ewiki_plugins["link_notfound"]) {
2386          foreach ($pf_a as $pf) {
2387             if ($str = $pf($title, $href, $href2, $type)) {
2388                break;
2389          }  }
2390       }
2392       #-- (QuestionMarkLink to edit/ action)
2393       if (!$str) {
2394          $type = array("notfound");
2395          $str = '<span class="NotFound"><b>' . $title . '</b><a href="' .
2396              ewiki_script("", $href) . '">?</a></span>';
2397       }
2398    }
2400    #-- convert standard URLs
2401    foreach ($ewiki_config["idf"]["url"] as $find) 
2402     if (strpos($href, $find)===0) {
2403       $type[-2] = "url";
2404       $type[-1] = strtok($find, ":");
2406       #-- URL plugins
2407       if ($pf_a = $ewiki_plugins["link_url"]) foreach ($pf_a as $pf) {
2408          if ($str = $pf($href, $title)) { break 2; }
2409       }
2410       $meta = @$ewiki_links[$href];
2412       #-- check for image files
2413       $ext = substr($href, strrpos($href,"."));
2414       $nocache = strpos($ext, "no");
2415       $ext = strtok($ext, "?&#");
2416       $obj = in_array($ext, $ewiki_config["idf"]["obj"]);
2417       $img = $obj || in_array($ext, $ewiki_config["idf"]["img"]);
2419       #-- internal:// references (binary files)
2420       if (EWIKI_SCRIPT_BINARY && ((strpos($href, EWIKI_IDF_INTERNAL)===0)  ||
2421           EWIKI_IMAGE_MAXSIZE && EWIKI_CACHE_IMAGES && $img && !$nocache) )
2422       {
2423          $type = array("binary");
2424          $href = ewiki_script_binary("", $href);
2425       }
2427       #-- output html reference
2428       if (!$img || $force_noimg || !$states["brackets"] || (strpos($href, EWIKI_IDF_INTERNAL) === 0)) {
2429          $str = '<a href="' . $href . '">' . $title . '</a>';
2430       }
2431       #-- img tag
2432       else {
2433          if (is_string($meta)) {
2434             $meta = unserialize($meta);
2435          }
2436          $type = array("image");
2437          #-- uploaded images size
2438          $x = $meta["width"];
2439          $y = $meta["height"];
2440          if ($p = strpos('?', $href)) {      #-- width/height given in url
2441             parse_str(str_replace("&amp;", "&", substr($href, $p)), $meta);
2442             ($uu = $meta["x"] . $meta["width"]) and ($x = $uu);
2443             ($uu = $meta["y"] . $meta["height"]) and ($y = $uu);
2444             if ($scale = $meta["r"] . $meta["scale"]) {
2445                ($p = strpos($scale, "%")) and ($scale = strpos($scale, 0, $p) / 100);
2446                $x *= $scale; $y *= $scale;
2447             }
2448          }
2449          $align = array('', ' align="right"', ' align="left"', ' align="center"');
2450          $align = $align[$spaces_l + 2*$spaces_r];
2451          $str = ($obj ? '<embed width="70%"' : '<img') . ' src="' . $href . '"' .
2452                 ' alt="' . ($title) . '"' .
2453                 (@$states["titled"] ? ' title="' . ($title) . '"' : '').
2454         ($x && $y ? " width=\"$x\" height=\"$y\"" : "") .
2455                 $align . " />" . ($obj ? "</embed>" : "");
2456                                             # htmlentities($title)
2457       }
2459       break;
2460    }
2462    #-- icon/transform plugins
2463    ksort($type);
2464    if ($pf_a = @$ewiki_plugins["link_final"]) {
2465       foreach ($pf_a as $pf) { $pf($str, $type, $href, $title); }
2466    }
2468    return($str);
2472 /*
2473    Returns URL if it encounters an InterWiki:Link or workalike.
2474 */
2475 function ewiki_interwiki($href, &$type) {
2476    global $ewiki_config, $ewiki_plugins;
2478    if (strpos($href, ":") and !strpos($href, "//")
2479    and ($p1 = strtok($href, ":"))) {
2481       $page = strtok("\000");
2483       if (($p1 = ewiki_array($ewiki_config["interwiki"], $p1)) !== NULL) {
2484          $type = array("interwiki", $uu);
2485          while ($p1_alias = $ewiki_config["interwiki"][$p1]) {
2486              $type[] = $p1;
2487              $p1 = $p1_alias;
2488          }
2489          if (!strpos($p1, "%s")) {
2490              $p1 .= "%s";
2491          }
2492          $href = str_replace("%s", $page, $p1);
2493          return($href);
2494       }
2495       elseif ($pf = $ewiki_plugins["intermap"][$p1]) {
2496          return($pf($p1, $page));
2497       }
2498    }
2502 /* 
2503    implements FeatureWiki:InterMapWalking
2504 */
2505 function ewiki_intermap_walking($id, &$data, $action) {
2506    if (empty($data["version"]) && ($href = ewiki_interwiki($id, $uu))) {
2507       header("Location: $href");
2508       return("<a href=\"$href\">$href</a>");
2509    }
2514 # =========================================================================
2518 #####    ##  ##   ##    ##    #####   ##  ##
2519 ######   ##  ###  ##   ####   ######  ##  ##
2520 ##  ##   ##  ###  ##  ######  ##  ##  ##  ##
2521 #####    ##  #### ##  ##  ##  ######  ######
2522 #####    ##  #######  ######  ####     ####
2523 ##  ###  ##  ## ####  ######  #####     ##
2524 ##  ###  ##  ##  ###  ##  ##  ## ###    ##
2525 ######   ##  ##  ###  ##  ##  ##  ##    ##
2526 ######   ##  ##   ##  ##  ##  ##  ##    ##
2531 /*  fetch & store
2532 */
2533 function ewiki_binary($break=0) {
2534    global $ewiki_plugins;
2535    global $USER;   // MOODLE
2537    #-- reject calls
2538    if (!strlen($id = @$_REQUEST[EWIKI_UP_BINARY]) || !EWIKI_IDF_INTERNAL) {
2539       return(false);
2540    }
2541    if (headers_sent()) die("ewiki-binary configuration error");
2543    #-- upload requests
2544    $upload_file = @$_FILES[EWIKI_UP_UPLOAD];
2545    $add_meta = array();
2546    if ($orig_name = @$upload_file["name"]) {
2547       $add_meta["Content-Location"] = urlencode($orig_name);
2548       $add_meta["Content-Disposition"] = 'inline; filename="'.urlencode(basename("remote://$orig_name")).'"';
2549    }
2551    #-- what are we doing here?
2552    if (($id == EWIKI_IDF_INTERNAL) && ($upload_file)) { 
2553       $do = "upload";
2554    }
2555    else {
2556       $data = ewiki_database("GET", array("id" => $id));
2557       $flags = @$data["flags"];
2558       if (EWIKI_DB_F_BINARY == ($flags & EWIKI_DB_F_TYPE)) { 
2559          $do = "get";
2560       }
2561       elseif (empty($data["version"]) and EWIKI_CACHE_IMAGES) {
2562          $do = "cache";
2563       }
2564       else { 
2565          $do = "nop";
2566       }
2567    }
2569    
2570    #-- auth only happens when enforced with _PROTECTED_MODE_XXL setting
2571    #   (authentication for inline images in violation of the WWW spirit)
2572    if ((EWIKI_PROTECTED_MODE>=5) && !ewiki_auth($id, $data, "binary-{$do}")) {
2573       return($_REQUEST["id"]="view/BinaryPermissionError");
2574    }
2576    #-- upload an image
2577    if ($do == "upload"){
2579       $id = ewiki_binary_save_image($upload_file["tmp_name"], "", $return=0, $add_meta);
2580       @unlink($upload_file["tmp_name"]);
2581       ($title = trim($orig_name, "/")) && ($title = preg_replace("/[^-._\w\d]+/", "_", substr(substr($orig_name, strrpos($title, "/")), 0, 20)))
2582       && ($title = '"'.$title.'"') || ($title="");
2584       if ($id) {
2585          echo<<<EOF
2586 <html><head><title>File/Picture Upload</title><script type="text/javascript"><!--
2587  opener.document.forms["ewiki"].elements["content"].value += "\\nUPLOADED PICTURE: [$id$title]\\n";
2588  window.setTimeout("self.close()", 5000);
2589 //--></script></head><body bgcolor="#440707" text="#FFFFFF">Your uploaded file was saved as<br /><big><b>
2590 [$id]
2591 </b></big>.<br /><br /><noscript>Please copy this &uarr; into the text input box:<br />select/mark it with your mouse, press [Ctrl]+[Insert], go back<br />to the previous screen and paste it into the textbox by pressing<br />[Shift]+[Insert] inside there.</noscript></body></html>
2592 EOF;
2593       }
2594    }
2596    #-- request for contents from the db
2597    elseif ($do == "get") {
2598 #### CHANGED FOR MOODLE        
2599    if (EWIKI_HIT_COUNTING) {
2600       $tmp["id"]=$id;
2601       ewiki_database("HIT", $tmp);
2602    }
2603 #### CHANGED FOR MOODLE        
2605       #-- send http_headers from meta
2606       if (is_array($data["meta"])) {
2607          foreach ($data["meta"] as $hdr=>$val) {
2608             if (($hdr[0] >= "A") && ($hdr[0] <= "Z")) {
2609                header("$hdr: $val");
2610             }
2611          }
2612       }
2614       #-- fetch from binary store
2615       if ($pf_a = $ewiki_plugins["binary_get"]) {
2616 #### CHANGED FOR MOODLE        
2617         foreach ($pf_a as $pf) { $pf($id, $data["meta"]); }
2619 #### END CHANGED FOR MOODLE        
2620       }
2622       #-- else fpassthru
2623       echo $data["content"];
2624    }
2626    #-- fetch & cache requested URL,
2627    elseif ($do == "cache") {
2629       #-- check for standard protocol names, to prevent us from serving
2630       #   evil requests for '/etc/passwd.jpeg' or '../.htaccess.gif'
2631       if (preg_match('@^\w?(http|ftp|https|ftps|sftp)\w?://@', $id)) {
2633          #-- generate local copy
2634          $filename = tempnam(EWIKI_TMP, "ewiki.local.temp.");
2635          if (($i = fopen($id, "rb")) && ($o = fopen($filename, "wb"))) {
2637             while (!feof($i)) {
2638                fwrite($o, fread($i, 65536));
2639             }
2641             fclose($i);
2642             fclose($o);
2644             $add_meta = array(
2645                "Content-Location" => urlencode($id),
2646                "Content-Disposition" => 'inline; filename="'.urlencode(basename($id)).'"'
2647             );
2649             $result = ewiki_binary_save_image($filename, $id, "RETURN", $add_meta);
2650          }
2651       }      
2653       #-- deliver
2654       if ($result && !$break) {
2655          ewiki_binary($break=1);
2656       }
2657       #-- mark URL as unavailable
2658       else {
2659          $data = array(
2660             "id" => $id,
2661             "version" => 1, 
2662             "flags" => EWIKI_DB_F_DISABLED,
2663             "lastmodified" => time(),
2664             "created" => time(),
2665             "author" => ewiki_author("ewiki_binary_cache"),
2666             "userid" => $USER->id,
2667             "content" => "",
2668             "meta" => array("Status"=>"404 Absent"),
2669          );
2670          ewiki_database("WRITE", $data);
2671          header("Location: $id");
2672          ewiki_log("imgcache: did not find '$id', and marked it now in database as DISABLED", 2);
2673       }
2674       
2675    }
2677    #-- "we don't sell this!"
2678    else {
2679       if (strpos($id, EWIKI_IDF_INTERNAL) === false) {
2680          header("Status: 301 Located SomeWhere Else");
2681          header("Location: $id");
2682       }
2683       else {
2684          header("Status: 404 Absent");
2685          header("X-Broken-URI: $id");
2686       }
2687    }
2689    // you should not remove this one, it is really a good idea to use it!
2690    die();
2698 function ewiki_binary_save_image($filename, $id="", $return=0,
2699 $add_meta=array(), $accept_all=EWIKI_ACCEPT_BINARY, $care_for_images=1)
2701    global $ewiki_plugins;
2702    global $USER;   // MOODLE
2704    #-- break on empty files
2705    if (!filesize($filename)) {
2706       return(false);
2707    }
2709    #-- check for image type and size
2710    $mime_types = array(
2711       "application/octet-stream",
2712       "image/gif",
2713       "image/jpeg",
2714       "image/png",
2715       "application/x-shockwave-flash"
2716    );
2717    $ext_types = array(
2718       "bin", "gif", "jpeg", "png", "swf"
2719    );
2720    list($width, $height, $mime_i, $uu) = getimagesize($filename);
2721    (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
2723    #-- images expected
2724    if ($care_for_images) {
2726       #-- mime type
2727       if (!$mime_i && !$accept_all || !filesize($filename)) {
2728          ewiki_die(ewiki_t("BIN_NOIMG"), $return);
2729          return;
2730       }
2732       #-- resize image
2733       if (strpos($mime,"image/")!==false) {
2734       if ($pf_a = $ewiki_plugins["image_resize"]) {
2735       foreach ($pf_a as $pf) {
2736       if (EWIKI_IMAGE_RESIZE && (filesize($filename) > EWIKI_IMAGE_MAXSIZE)) {
2737          $pf($filename, $mime, $return);
2738          clearstatcache();
2739       }}}}
2741       #-- reject image if too large
2742       if (strlen($content) > EWIKI_IMAGE_MAXSIZE) {
2743          ewiki_die(ewiki_t("BIN_IMGTOOLARGE"), $return);
2744          return;
2745       }
2747       #-- again check mime type and image sizes
2748       list($width, $height, $mime_i, $uu) = getimagesize($filename);
2749       (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
2751    }
2752    ($ext = $ext_types[$mime_i]) or ($ext = $ext_types[0]);
2754    #-- binary files
2755    if ((!$mime_i) && ($pf = $ewiki_plugins["mime_magic"][0])) {
2756       if ($tmp = $pf($content)) {
2757          $mime = $tmp;
2758       }
2759    }
2760    if (!strlen($mime)) {
2761       $mime = $mime_types[0];
2762    }
2764    #-- store size of binary file
2765    $add_meta["size"] = filesize($filename);
2766    $content = "";
2768    #-- handler for (large/) binary content?
2769    if ($pf_a = $ewiki_plugins["binary_store"]) {
2770       foreach ($pf_a as $pf) {
2771          $pf($filename, $id, $add_meta, $ext);
2772       }
2773    }
2775    #-- read file into memory (2MB), to store it into the database
2776    if ($filename) {
2777       $f = fopen($filename, "rb");
2778       $content = fread($f, 1<<21);
2779       fclose($f);
2780    }
2782    #-- generate db file name
2783    if (empty($id)) {
2784       $md5sum = md5($content);
2785       $id = EWIKI_IDF_INTERNAL . $md5sum . ".$ext";
2786       ewiki_log("generated md5sum '$md5sum' from file content");
2787    }
2789    #-- prepare meta data
2790    $meta = @array_merge(array(
2791       "class" => $mime_i ? "image" : "file",
2792       "Content-Type" => $mime,
2793       "Pragma" => "cache",
2794    ), $add_meta);
2795    if ($mime_i) {
2796       $meta["width"] = $width;
2797       $meta["height"] = $height;
2798    }
2800    #-- database entry
2801    $data = array(
2802       "id" => $id,
2803       "version" => "1", 
2804       "author" => ewiki_author(),
2805       "userid" => $USER->id,
2806       "flags" => EWIKI_DB_F_BINARY | EWIKI_DB_F_READONLY,
2807       "created" => time(),
2808       "lastmodified" => time(),
2809       "meta" => &$meta,
2810       "content" => &$content,
2811    );
2812    
2813    #-- write if not exist
2814    $exists = ewiki_database("FIND", array($id));
2815    if (! $exists[$id] ) {
2816       $result = ewiki_database("WRITE", $data);
2817       ewiki_log("saving of '$id': " . ($result ? "ok" : "error"));
2818    }
2819    else {
2820       ewiki_log("binary_save_image: '$id' was already in the database", 2);
2821    }
2823    return($id);
2829 # =========================================================================
2832 ####     ####  ####   ########     ########
2833 #####   #####  ####  ##########   ##########
2834 ###### ######  ####  ####   ###   ####    ###
2835 #############        ####        ####
2836 #############  ####   ########   ####
2837 #### ### ####  ####    ########  ####
2838 ####  #  ####  ####        ####  ####
2839 ####     ####  ####  ###   ####  ####    ###
2840 ####     ####  ####  #########    ##########
2841 ####     ####  ####   #######      ########
2845 /* yes! it is not neccessary to annoy users with country flags, if the
2846    http already provides means to determine preferred languages!
2847 */
2848 function ewiki_localization() {
2850    global $ewiki_t, $ewiki_plugins;
2852    $deflangs = ','.@$_ENV["LANGUAGE"] . ','.@$_ENV["LANG"]
2853              . ",".EWIKI_DEFAULT_LANG . ",en,C";
2855    foreach (explode(",", @$_SERVER["HTTP_ACCEPT_LANGUAGE"].$deflangs) as $l) {
2857       $l = strtok($l, ";");
2858       $l = strtok($l, "-"); $l = strtok($l, "_"); $l = strtok($l, ".");
2859       $l = trim($l);
2861       $ewiki_t["languages"][] = strtolower($l);
2862    }
2868 /* poor mans gettext, $repl is an array of string replacements to get
2869    applied to the fetched text chunk,
2870    "$const" is either an entry from $ewiki_t[] or a larger text block
2871    containing _{text} replacement braces of the form "_{...}"
2872 */
2873 function ewiki_t($const, $repl=array(), $pref_langs=array()) {
2874    ##### BEGIN MOODLE ADDITION #####
2875    $replacechars=array("." => "",
2876                        "," => "",
2877                        "!" => "",
2878                        ";" => "",
2879                        ":" => "",
2880                        "'" => "",
2881                        '"' => "",
2882                        "-" => "",
2883                        "_" => "",
2884                        " " => "",
2885                        "+" => "");
2886    
2887    $translation=get_string(strtolower(strtr($const,$replacechars)),"wiki",$repl);
2888    return $translation;
2889    ##### END MOODLE ADDITION #####
2890    
2891 /*   global $ewiki_t;
2893    #-- use default language wishes
2894    if (empty($pref_langs)) {
2895       $pref_langs = $ewiki_t["languages"];
2896    }
2898    #-- large text snippet replaceing
2899    if (strpos($const, "_{") !== false) {
2900       while ( (($l=strpos($const,"_{")) || ($l===0)) && ($r=strpos($const,"}",$l)) ) {
2901          $const = substr($const, 0, $l)
2902                 . ewiki_t(substr($const, $l+2, $r-$l-2))
2903                 . substr($const,$r+1);
2904       }
2905    }
2907    #-- just one string
2908    else foreach ($pref_langs as $l) {
2910       if (is_string($r = @$ewiki_t[$l][$const]) || ($r = @$ewiki_t[$l][strtoupper($const)])) {
2912          foreach ($repl as $key=>$value) {
2913             if ($key[0] != '$') {
2914                $key = '$'.$key;
2915             }
2916             $r = str_replace($key, $value, $r);
2917          }
2918          return($r);
2920       }
2921    }
2923    return($const);*/
2931 function ewiki_log($msg, $error_type=3) {
2933    if ((EWIKI_LOGLEVEL >= 0) && ($error_type <= EWIKI_LOGLEVEL)) {
2935       $msg = time() . " - " .
2936              getremoteaddr() . ":" . $_SERVER["REMOTE_PORT"] . " - " .
2937              $_SERVER["REQUEST_METHOD"] . " " . $_SERVER["REQUEST_URI"] . " - " .
2938              strtr($msg, "\n\r\000\377\t\f", "\r\r\r\r\t\f") . "\n";
2939       error_log($msg, 3, EWIKI_LOGFILE);
2940    }
2946 function ewiki_die($msg, $return=0) {
2947    ewiki_log($msg, 1);
2948    if ($return) {
2949       return($GLOBALS["ewiki_error"] = $msg);
2950    }
2951    else {
2952       die($msg);
2953    }
2958 function ewiki_array_hash(&$a) {
2959    return(count($a) . ":" . implode(":", array_keys(array_slice($a, 0, 3))));
2964 /* provides an case-insensitive in_array replacement to search a page name
2965    in a list of others;
2966    the supplied $array WILL be lowercased afterwards, unless $dn was set
2967 */
2968 function ewiki_in_array($value, &$array, $dn=0, $ci=EWIKI_CASE_INSENSITIVE) {
2970    static $as = array();
2972    #-- work around pass-by-reference
2973    if ($dn && $ci) {   $dest = array();   }
2974               else {   $dest = &$array;   }
2976    #-- make everything lowercase
2977    if ($ci) {
2978       $value = strtolower($value);
2979       if (empty($as[ewiki_array_hash($array)])) {  // prevent working on the
2980          foreach ($array as $i=>$v) {              // same array multiple times
2981             $dest[$i] = strtolower($v);
2982          }
2983          $as[ewiki_array_hash($dest)] = 1;
2984       }
2985    }
2987    #-- search in values
2988    return(in_array($value, $dest));
2993 /* case-insensitively retrieves an entry from an $array,
2994    or returns the given $array lowercased if $key was obmitted
2995 */
2996 function ewiki_array($array, $key=false, $am=1, $ci=EWIKI_CASE_INSENSITIVE) {
2998    #-- make everything lowercase
2999    if ($ci) {
3000       $key = strtolower($key);
3002       $r = array();
3003       foreach ($array as $i=>$v) {
3004          $i = strtolower($i);
3005          if (!$am || empty($r[$i])) {
3006             $r[$i] = $v;
3007          }
3008          else {
3009             $r[$i] .= $v;   //RET: doubling for images`meta won't happen
3010          }          // but should be "+" here for integers
3011       }
3012       $array = &$r;
3013    }
3015    #-- search in values
3016    if ($key) {
3017       return(@$array[$key]);
3018    }
3019    else {
3020       return($array);
3021    }
3029 function ewiki_author($defstr="") {
3031    $author = @$GLOBALS["ewiki_author"];
3032    ($ip = getremoteaddr()) or ($ip = "127.0.0.0");
3033    ($port = $_SERVER["REMOTE_PORT"]) or ($port = "null");
3034    $hostname = $ip;
3035    $remote = (($ip != $hostname) ? $hostname . " " : "")
3036            . $ip . ":" . $port;
3038    (empty($author)) && (
3039       ($author = $defstr) ||
3040       ($author = $_SERVER["HTTP_FROM"]) ||  // RFC2068 sect 14.22
3041       ($author = $_SERVER["PHP_AUTH_USER"])
3042    );
3044    (empty($author))
3045       && ($author = $remote)
3046       || ($author = addslashes($author) . " (" . $remote . ")" );
3048    return($author);
3055 /*  Returns a value of (true) if the currently logged in user (this must
3056     be handled by one of the plugin backends) is authenticated to do the
3057     current $action, or to view the current $id page.
3058   - alternatively just checks current authentication $ring permission level
3059   - errors are returned via the global $ewiki_errmsg
3060 */
3061 function ewiki_auth($id, &$data, $action, $ring=false, $request_auth=0) {
3063    global $ewiki_plugins, $ewiki_ring, $ewiki_author, $ewiki_errmsg;
3064    $ok = true;
3065    $ewiki_errmsg="";
3067 #echo "_a($id,dat,$action,$ring,$request_auth)<br />\n";
3069    if (EWIKI_PROTECTED_MODE) {
3070  
3071       #-- set required vars
3072       if (!isset($ewiki_ring)) {
3073          $ewiki_ring = (int)EWIKI_AUTH_DEFAULT_RING;
3074       }
3075       if ($ring===false) {
3076          $ring = NULL;
3077       }
3079       #-- plugins to call
3080       $pf_login = @$ewiki_plugins["auth_query"][0];
3081       $pf_perm = $ewiki_plugins["auth_perm"][0];
3083       #-- nobody is currently logged in, so try to fetch username,
3084       #   the login <form> is not yet enforced
3085       if ($pf_login && empty($ewiki_auth_user)) {
3086          $pf_login($data, 0);
3087       }
3089       #-- check permission for current request (page/action/ring)
3090       if ($pf_perm) {
3092          #-- via _auth handler
3093          $ok = $pf_perm($id, $data, $action, $ring, $request_auth);
3095          #-- if it failed, we really depend on the login <form>,
3096          #   and then recall the _perm plugin
3097          if ($pf_login && (($request_auth >= 2) || !$ok && $request_auth && (empty($ewiki_auth_user) || EWIKI_AUTO_LOGIN) && empty($ewiki_errmsg))) {
3098 //@FIXME: complicated if()  - strip empty(errmsg) ??
3099             $pf_login($data, $request_auth);
3100             $ok = $pf_perm($id, $data, $action, $ring, $request_auth=0);
3101          }
3102       }
3103       else {
3104          $ok = !isset($ring) || isset($ring) && ($ewiki_ring <= $ring);
3105       }
3107       #-- return error string
3108       if (!$ok && empty($ewiki_errmsg)) {
3109          $ewiki_errmsg = ewiki_t("FORBIDDEN");
3110       }
3111    }
3113    return($ok);
3117 /*
3118    Queries all registered ["auth_userdb"] plugins for the given
3119    username, and compares password to against "db" value, sets
3120    $ewiki_ring and returns(true) if valid.
3121 */
3122 function ewiki_auth_user($username, $password) {
3123   global $ewiki_ring, $ewiki_errmsg, $ewiki_auth_user, $ewiki_plugins, $ewiki_author;
3125   if (empty($username)) {
3126      return(false);
3127   }
3128   if (($password[0] == "$") || (strlen($password) > 12)) {
3129      ewiki_log("_auth_userdb: password was transmitted in encoded form, or is just too long (login attemp for user '$username')", 2);
3130      return(false);
3131   }
3133   if ($pf_u = $ewiki_plugins["auth_userdb"])
3134   foreach ($pf_u as $pf) {
3136      if (function_exists($pf) && ($entry = $pf($username, $password))) {
3138         #-- get and compare password
3139         if ($entry = (array) $entry) {
3140            $enc_pw = $entry[0];
3141         }
3142         $success = false
3143                 || ($enc_pw == substr($password, 0, 12))
3144                 || ($enc_pw == md5($password))
3145                 || ($enc_pw == crypt($password, substr($enc_pw, 0, 2)))
3146                 || function_exists("sha1") && ($enc_pw == sha1($password));
3147         $success &= $enc_pw != "*";
3149         #-- return if it matches
3150         if ($success) {
3151            if (isset($entry[1])) { 
3152               $ewiki_ring = (int)($entry[1]);
3153            } else {
3154               $ewiki_ring = 2;  //(EWIKI_AUTH_DEFAULT_RING - 1);
3155            }
3156            if (empty($ewiki_author)) {
3157               ($ewiki_author = $entry[2]) or
3158               ($ewiki_author = $username);
3159            }
3160            return($success && ($ewiki_auth_user=$username));
3161         }
3162      }
3163   }
3165   if ($username || $password) {
3166      ewiki_log("_auth_userdb: wrong password supplied for user '$username', not verified against any userdb", 3);
3167      $ewiki_errmsg = "wrong username and/or password";
3168 #     ewiki_auth($uu, $uu, $uu, $uu, 2);
3169   }
3170   return(false);
3177 /*  reads all files from "./init-pages/" into the database,
3178     when ewiki is run for the very first time and the FrontPage
3179     does not yet exist in the database
3180 */
3181 function ewiki_eventually_initialize(&$id, &$data, &$action) {
3183    global $USER;
3185    #-- initialize database only if frontpage missing
3186    if (($id==EWIKI_PAGE_INDEX) && ($action=="edit") && empty($data["version"])) {
3188       ewiki_database("INIT", array());
3189 #### BEGIN MOODLE CHANGE
3190       $path=EWIKI_INIT_PAGES;
3191       if (!empty($path)) {
3192         if ($dh = @opendir($path=EWIKI_INIT_PAGES)) {
3193          while ($filename = readdir($dh)) {
3194 #### MOODLE CHANGE TO SOLVE BUG #3830. Original doesn't support dots in names.
3195     //Orig->if (preg_match('/^(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+\w*)+/', $filename)) {
3196             if ($filename == clean_filename($filename) && !is_dir($path.'/'.$filename)) {
3197 #### END OF MOODLE CHANGE TO SOLVE BUG #3830. Original doesn't support dots in names.
3198                $found = ewiki_database("FIND", array($filename));
3199                if (! $found[$filename]) {
3200                   $content = implode("", file("$path/$filename"));
3201                   ewiki_scan_wikiwords($content, $ewiki_links, "_STRIP_EMAIL=1");
3202                   $refs = "\n\n" . implode("\n", array_keys($ewiki_links)) . "\n\n";
3203                   $save = array(
3204                      "id" => "$filename",
3205                      "version" => "1",
3206                      "flags" => "1",
3207                      "content" => $content,
3208                      "author" => ewiki_author("ewiki_initialize"),
3209                      "userid" => $USER->id,
3210                      "refs" => $refs,
3211                      "lastmodified" => filemtime("$path/$filename"),
3212                      "created" => filectime("$path/$filename")   // (not exact)
3213                   );
3214                   ewiki_database("WRITE", $save);
3215                }
3216             }
3217          }
3218          closedir($dh);
3219         }
3220         else {
3221          echo "<b>ewiki error</b>: could not read from directory ". realpath($path) ."<br />\n";
3222         }
3223       }
3224 #### END MOODLE CHANGE
3226       #-- try to view/ that newly inserted page
3227       if ($data = ewiki_database("GET", array("id"=>$id))) {
3228          $action = "view";
3229       }
3230    }
3236 #---------------------------------------------------------------------------
3240 ########     ###    ########    ###    ########     ###     ######  ########
3241 ########     ###    ########    ###    ########     ###     ######  ########
3242 ##     ##   ## ##      ##      ## ##   ##     ##   ## ##   ##    ## ##
3243 ##     ##   ## ##      ##      ## ##   ##     ##   ## ##   ##    ## ##
3244 ##     ##  ##   ##     ##     ##   ##  ##     ##  ##   ##  ##       ##
3245 ##     ##  ##   ##     ##     ##   ##  ##     ##  ##   ##  ##       ##
3246 ##     ## ##     ##    ##    ##     ## ########  ##     ##  ######  ######
3247 ##     ## ##     ##    ##    ##     ## ########  ##     ##  ######  ######
3248 ##     ## #########    ##    ######### ##     ## #########       ## ##
3249 ##     ## #########    ##    ######### ##     ## #########       ## ##
3250 ##     ## ##     ##    ##    ##     ## ##     ## ##     ## ##    ## ##
3251 ##     ## ##     ##    ##    ##     ## ##     ## ##     ## ##    ## ##
3252 ########  ##     ##    ##    ##     ## ########  ##     ##  ######  ########
3253 ########  ##     ##    ##    ##     ## ########  ##     ##  ######  ########
3258 /*  wrapper
3259 */
3260 function ewiki_database($action, $args, $sw1=0, $sw2=0, $pf=false) {
3262    #-- normalize (fetch bad parameters)
3263    if (($action=="GET") && !is_array($args) && is_string($args)) {   
3264       $args = array("id" => $args);
3265    }
3267    #-- treat special
3268    switch ($action) {
3270       case "GETALL":
3271          $args = array_unique(@array_merge($args, array("flags", "version")));
3272          $args = array_diff($args, array("id"));
3273          break;
3275       case "SEARCH":
3276 #         unset($args["version"]);
3277 #         unset($args["flags"]);
3278          break;
3280       default:
3281          break;
3282    }
3284    #-- handle {meta} sub array as needed
3285    if (is_array(@$args["meta"])) {
3286       $args["meta"] = serialize($args["meta"]);
3287    }
3289    #-- database plugin
3290    if (($pf) || ($pf = @$GLOBALS["ewiki_plugins"]["database"][0])) {
3291       $r = $pf($action, $args, $sw1, $sw2);
3292    }
3293    else {
3294       ewiki_log("DB layer: no backend!", 0);
3295       $r = false;
3296    }
3298    #-- database layer generation 2 abstraction
3299    if (is_array($r) && (($action=="SEARCH") || ($action=="GETALL"))) {
3300       $z = new ewiki_dbquery_result(array_keys($args));
3301       foreach ($r as $id=>$row) {
3302          $z->add($row);
3303       }
3304       $r = $z;
3305    }
3307    #-- extract {meta} sub array
3308    if (is_array($r) && !is_array(@$r["meta"]) && strlen(@$r["meta"])) {
3309       $r["meta"] = unserialize($r["meta"]);
3310    }
3312    return($r);
3317 /*  returned for SEARCH and GETALL queries, as those operations are
3318     otherwise too memory exhaustive
3319 */
3320 class ewiki_dbquery_result {
3322    var $keys = array();
3323    var $entries = array();
3324    var $buffer = EWIKI_DBQUERY_BUFFER;
3325    var $size = 0;
3327    function ewiki_dbquery_result($keys) {
3328       $keys = @array_merge($keys, array(-50=>"id", "version", "flags"));
3329       $this->keys = array_unique($keys);
3330    }
3332    function add($row) {
3333       if (is_array($row)) {
3334          if ($this->buffer) {
3335             $this->size += strlen(serialize($row));
3336             $this->buffer = $this->size <= EWIKI_DBQUERY_BUFFER;
3337          }
3338          else {
3339             $row = $row["id"];
3340          }
3341       }
3342       $this->entries[] = $row;
3343    }
3345    function get($all=0, $flags=0x00) {
3346       $row = array();
3348       $prot_hide = ($flags&0x0020) && EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING;
3349       do {
3350          if (count($this->entries)) {
3352             #-- fetch very first entry from $entries list
3353             $r = array_shift($this->entries);
3355             #-- finish if buffered entry
3356             if (is_array($r) && !$all) {
3357                $row = $r;
3358             }
3359             #-- else refetch complete entry from database
3360             else {
3361                if (is_array($r)) {
3362                   $r = $r["id"];
3363                }
3364                $r = ewiki_database("GET", array("id"=>$r));
3365                if (!$all) {
3366                   foreach ($this->keys as $key) {
3367                      $row[$key] = $r[$key];
3368                   }
3369                } else { 
3370                   $row = $r;
3371                }
3372             }
3373             unset($r);
3374          }
3375          else { 
3376             return(NULL);  // no more entries
3377          }
3379          #-- expand {meta} field
3380          if (is_array($row) && is_string(@$row["meta"])) {
3381             $row["meta"] = unserialize($row["meta"]);
3382          }
3384          #-- drop unwanted results
3385          if ($prot_hide && !ewiki_auth($row["id"], $row, $ewiki_action)) {
3386             $row = array();
3387          }
3388       } while ($prot_hide && empty($row));
3390       return($row);
3391    }
3393    function count() {
3394       return(count($this->entries));
3395    }
3400 /*  MySQL database backend
3401     (default)
3402     Note: this is of course an abuse of the relational database scheme,
3403     but neccessary for real db independence and abstraction
3404 */
3405 function ewiki_database_mysql($action, &$args, $sw1, $sw2) {
3407    #-- reconnect to the database (if multiple are used)
3408    #<off>#  mysql_ping($GLOBALS["db"]);
3410    #-- result array
3411    $r = array();
3413    switch($action) {
3415       /*  Returns database entry as array for the page whose name was given
3416           with the "id" key in the $args array, usually fetches the latest
3417           version of a page, unless a specific "version" was requested in
3418           the $args array.
3419       */
3420       case "GET":
3421          $id = "'" . mysql_escape_string($args["id"]) . "'";
3422          ($version = 0 + @$args["version"]) and ($version = "AND (version=$version)") or ($version="");
3423          $result = mysql_query("SELECT * FROM " . EWIKI_DB_TABLE_NAME
3424             . " WHERE (pagename=$id) $version  ORDER BY version DESC  LIMIT 1"
3425          );
3426          if ($result && ($r = mysql_fetch_array($result, MYSQL_ASSOC))) {
3427             $r["id"] = $r["pagename"];
3428             unset($r["pagename"]);
3429          }
3430          if (strlen($r["meta"])) {
3431             $r["meta"] = @unserialize($r["meta"]);
3432          }
3433          break;
3437       /*  Increases the hit counter for the page name given in $args array
3438           with "id" index key.
3439       */
3440       case "HIT":
3441          mysql_query("UPDATE " . EWIKI_DB_TABLE_NAME . " SET hits=(hits+1) WHERE pagename='" . mysql_escape_string($args["id"]) . "'");
3442          break;
3446       /*  Stores the $data array into the database, while not overwriting
3447           existing entries (using WRITE); returns 0 on failure and 1 if
3448           saved correctly.
3449       */
3450       case "OVERWRITE":     // fall-through
3451          $COMMAND = "REPLACE";
3453       case "WRITE":
3454          $args["pagename"] = $args["id"];
3455          unset($args["id"]);
3457          if (is_array($args["meta"])) {
3458             $args["meta"] = serialize($args["meta"]);
3459          }
3461          $sql1 = $sql2 = "";
3462          foreach ($args as $index => $value) {
3463             if (is_int($index)) {
3464                continue;
3465             }
3466             $a = ($sql1 ? ', ' : '');
3467             $sql1 .= $a . $index;
3468             $sql2 .= $a . "'" . mysql_escape_string($value) . "'";
3469          }
3471          strlen(@$COMMAND) || ($COMMAND = "INSERT");
3473          $result = mysql_query("$COMMAND INTO " . EWIKI_DB_TABLE_NAME .
3474             " (" . $sql1 . ") VALUES (" . $sql2 . ")"
3475          );
3477          return($result && mysql_affected_rows() ?1:0);
3478          break;
3482       /*  Checks for existence of the WikiPages whose names are given in
3483           the $args array. Returns an array with the specified WikiPageNames
3484           associated with values of "0" or "1" (stating if the page exists
3485           in the database). For images/binary db entries returns the "meta"
3486           field instead of an "1".
3487       */
3488       case "FIND":
3489          $sql = "";
3490          foreach (array_values($args) as $id) if (strlen($id)) {
3491             $r[$id] = 0;
3492             $sql .= ($sql ? " OR " : "") .
3493                     "(pagename='" . mysql_escape_string($id) . "')";
3494          }
3495          $result = mysql_query($sql = "SELECT pagename AS id, meta FROM " .
3496             EWIKI_DB_TABLE_NAME . " WHERE $sql "
3497          );
3498          while ($result && ($row = mysql_fetch_row($result))) {
3499             $r[$row[0]] = strpos($row[1], 's:5:"image"') ? $row[1] : 1;
3500          }
3501          break;
3505       /*  Returns an array of __all__ pages, where each entry is made up
3506           of the fields from the database requested with the $args array,
3507           e.g. array("flags","meta","lastmodified");
3508       */
3509       case "GETALL":
3510          $result = mysql_query("SELECT pagename AS id, ".
3511             implode(", ", $args) .
3512             " FROM ". EWIKI_DB_TABLE_NAME .
3513             " GROUP BY id, version DESC"
3514          );
3515          $r = new ewiki_dbquery_result($args);
3516          $drop = "";
3517          while ($result && ($row = mysql_fetch_array($result, MYSQL_ASSOC))) {
3518             $i = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
3519             if ($i != $drop) {
3520                $drop = $i;
3521                $r->add($row);
3522             }
3523          }
3524          break;
3528       /*  Returns array of database entries (also arrays), where the one
3529           specified column matches the specified content string, for example
3530           $args = array("content" => "text...piece")
3531           is not guaranteed to only search/return the latest version of a page
3532       */
3533       case "SEARCH":
3534          $field = implode("", array_keys($args));
3535          $content = strtolower(implode("", $args));
3536          if ($field == "id") { $field = "pagename"; }
3538          $result = mysql_query("SELECT pagename AS id, version, flags" .
3539             (EWIKI_DBQUERY_BUFFER && ($field!="pagename") ? ", $field" : "") .
3540             " FROM " . EWIKI_DB_TABLE_NAME .
3541             " WHERE LOCATE('" . mysql_escape_string($content) . "', LCASE($field)) " .
3542             " GROUP BY id, version DESC"
3543          );
3544          $r = new ewiki_dbquery_result(array("id","version",$field));
3545          $drop = "";
3546          while ($result && ($row = mysql_fetch_array($result, MYSQL_ASSOC))) {
3547             $i = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
3548             if ($i != $drop) {
3549                $drop = $i;
3550                $r->add($row);
3551             }
3552          }
3553          break;
3557       case "DELETE":
3558          $id = mysql_escape_string($args["id"]);
3559          $version = $args["version"];
3560          mysql_query("DELETE FROM " . EWIKI_DB_TABLE_NAME ."
3561             WHERE pagename='$id' AND version=$version");
3562          break;
3566       case "INIT":
3567          mysql_query("CREATE TABLE " . EWIKI_DB_TABLE_NAME ."
3568             (pagename VARCHAR(160) NOT NULL,
3569             version INTEGER UNSIGNED NOT NULL DEFAULT 0,
3570             flags INTEGER UNSIGNED DEFAULT 0,
3571             content MEDIUMTEXT,
3572             author VARCHAR(100) DEFAULT 'ewiki',
3573             userid INTEGER UNSIGNED DEFAULT 0,
3574             created INTEGER UNSIGNED DEFAULT ".time().",
3575             lastmodified INTEGER UNSIGNED DEFAULT 0,
3576             refs MEDIUMTEXT,
3577             meta MEDIUMTEXT,
3578             hits INTEGER UNSIGNED DEFAULT 0,
3579             PRIMARY KEY id (pagename, version) )
3580             ");
3581          echo mysql_error();
3582          break;
3584       default:
3585    }
3587    return($r);
3592 </script>