1 <?php @define("EWIKI_VERSION", "R1.02b");
4 ErfurtWiki - a pretty flexible, fast and user-friendly wiki framework
6 Is PUBLIC DOMAIN (no license, no warranty); feel free to redistribute
7 under any other license, if you want. (c) 2003-2005 WhoEver wants to.
10 http://erfurtwiki.sourceforge.net/
11 http://ewiki.berlios.de/
13 Mario Salzer <mario*erphesfurt·de>
14 Andy Fundinger <andy*burgiss·com>
16 call it from within yoursite.php / layout script like this:
19 $CONTENT = ewiki_page();
28 #-- for future backwards compatibility to R1.02b (temporary file dependencies)
29 if (!function_exists("ewiki_page_edit")) { include_once("plugins/edit.php"); }
30 if (!function_exists("ewiki_format")) { include_once("plugins/format.php"); }
31 if (!function_exists("ewiki_binary")) { include_once("plugins/feature/binary.php"); }
32 if (!function_exists("ewiki_author")) { include_once("plugins/misc.php"); }
33 if (!class_exists("ewiki_database_mysql")) { include_once("plugins/db/mysql.php"); }
35 #-------------------------------------------------------- config ---
37 #-- this disables most PHPs debugging (_NOTICE) messages
38 error_reporting(0x0000377 & error_reporting());
39 # error_reporting(E_ALL^E_NOTICE); // development
41 #-- the location of your ewiki-wrapper script
42 define("EWIKI_SCRIPT", "?id="); # relative to docroot
43 # define("EWIKI_SCRIPT_URL", "http://../?id="); # absolute URL
45 #-- change to your needs (site lang)
46 define("EWIKI_NAME", "UnnamedWiki"); # Wiki title
47 define("EWIKI_PAGE_INDEX", "ATutorWiki"); # default page
48 define("EWIKI_PAGE_PRETTY_URL", 'mods\/wiki\/index.php'); #pretty URL format of this page
49 define("EWIKI_PAGE_LIST", "PageIndex");
50 define("EWIKI_PAGE_SEARCH", "SearchPages");
51 define("EWIKI_PAGE_NEWEST", "NewestPages");
52 define("EWIKI_PAGE_HITS", "MostVisitedPages");
53 define("EWIKI_PAGE_VERSIONS", "MostOftenChangedPages");
54 define("EWIKI_PAGE_UPDATES", "UpdatedPages"); # like RecentChanges
56 #-- default settings are good settings - most often ;)
58 define("EWIKI_PRINT_TITLE", 2); # <h2>WikiPageName</h2> on top
59 define("EWIKI_SPLIT_TITLE", 0); # <h2>Wiki Page Name</h2>
60 define("EWIKI_CONTROL_LINE", 1); # EditThisPage-link at bottom
61 define("EWIKI_LIST_LIMIT", 20); # listing limit
63 define("EWIKI_AUTO_EDIT", 1); # edit box for non-existent pages
64 define("EWIKI_EDIT_REDIRECT", 1); # redirect after edit save
65 define("EWIKI_DEFAULT_ACTION", "view"); # (keep!)
66 define("EWIKI_CASE_INSENSITIVE", 1); # wikilink case sensitivity
67 define("EWIKI_HIT_COUNTING", 1);
68 define("EWIKI_RESOLVE_DNS", 1); # gethostbyaddr() when editing
69 define("UNIX_MILLENNIUM", 1000000000);
71 define("EWIKI_ALLOW_HTML", 0); # often a very bad idea
72 define("EWIKI_HTML_CHARS", 1); # allows for È
73 define("EWIKI_ESCAPE_AT", 1); # "@" -> "@"
75 define("EWIKI_SUBPAGE_LONGTITLE", 0);
76 define("EWIKI_SUBPAGE_START", ".:/"); # set to "" to disable [.Sub] getting a link to [CurrentPage.Sub]
77 # define("EWIKI_SUBPAGE_CHARS", ".:/-!");
78 define("EWIKI_HTTP_HEADERS", 1); # most often a good thing
79 define("EWIKI_NO_CACHE", 1); # browser+proxy shall not cache
80 define("EWIKI_URLENCODE", 1); # disable when _USE_PATH_INFO
81 define("EWIKI_URLDECODE", 1);
82 #new! define("EWIKI_URL_UTF8", 1); # fix UTF-8 parameters
83 define("EWIKI_USE_PATH_INFO", 1);
84 define("EWIKI_USE_ACTION_PARAM", 1); # 2 for alternative link style
85 define("EWIKI_ACTION_SEP_CHAR", "/");
86 define("EWIKI_ACTION_TAKE_ASIS", 1);
87 define("EWIKI_UP_PAGENUM", "n"); # _UP_ means "url parameter"
88 define("EWIKI_UP_PAGEEND", "e");
89 define("EWIKI_UP_BINARY", "binary");
90 define("EWIKI_UP_UPLOAD", "upload");
91 define("EWIKI_UP_PARENTID", "parent_page");
92 define("EWIKI_UP_LISTLIM", "limit");
94 define("EWIKI_DEFAULT_LANG", "en");
95 define("EWIKI_CHARSET", "ISO-8859-1"); # nothing else supported
97 define("EWIKI_PROTECTED_MODE", 0); # disable funcs + require auth
98 define("EWIKI_PROTECTED_MODE_HIDING", 0); # hides disallowed actions
99 define("EWIKI_AUTH_DEFAULT_RING", 3); # 0=root 1=priv 2=user 3=view
100 define("EWIKI_AUTO_LOGIN", 1); # [auth_query] on startup
102 #-- allowed WikiPageNameCharacters
103 define("EWIKI_CHARS_L", "a-z_µ¤ß-ÿ$"); # \337-\377
104 define("EWIKI_CHARS_U", "A-Z0-9À-Þ"); # \300-\336
105 define("EWIKI_CHARS", EWIKI_CHARS_L.EWIKI_CHARS_U);
108 @define("EWIKI_DB_TABLE_NAME", "ewiki"); # MySQL / ADOdb
109 @define("EWIKI_DBFILES_DIRECTORY", "/tmp"); # see "db_flat_files.php"
110 define("EWIKI_DBA", "/tmp/ewiki.db3"); # see "db_dba.php"
111 define("EWIKI_DBQUERY_BUFFER", 512*1024); # 512K
112 define("EWIKI_INIT_PAGES", "./init-pages"); # for initialization
114 define("EWIKI_DB_F_TEXT", 1<<0);
115 define("EWIKI_DB_F_BINARY", 1<<1);
116 define("EWIKI_DB_F_DISABLED", 1<<2);
117 define("EWIKI_DB_F_HTML", 1<<3);
118 define("EWIKI_DB_F_READONLY", 1<<4);
119 define("EWIKI_DB_F_WRITEABLE", 1<<5);
120 define("EWIKI_DB_F_APPENDONLY", 1<<6);
121 define("EWIKI_DB_F_SYSTEM", 1<<7);
122 define("EWIKI_DB_F_PART", 1<<8);
123 define("EWIKI_DB_F_MINOR", 1<<9);
124 define("EWIKI_DB_F_HIDDEN", 1<<10);
125 define("EWIKI_DB_F_ARCHIVE", 1<<11);
126 define("EWIKI_DB_F_EXEC", 1<<17);
127 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);
128 define("EWIKI_DB_F_ACCESS", EWIKI_DB_F_READONLY | EWIKI_DB_F_WRITEABLE | EWIKI_DB_F_APPENDONLY);
129 define("EWIKI_DB_F_COPYMASK", EWIKI_DB_F_TYPE | EWIKI_DB_F_ACCESS | EWIKI_DB_F_HIDDEN | EWIKI_DB_F_HTML | EWIKI_DB_F_ARCHIVE);
131 define("EWIKI_DBFILES_NLR", '\\n');
132 define("EWIKI_DBFILES_ENCODE", 0 || (DIRECTORY_SEPARATOR != "/"));
133 define("EWIKI_DBFILES_GZLEVEL", "2");
135 #-- internal, auto-discovered
136 define("EWIKI_ADDPARAMDELIM", (strstr(EWIKI_SCRIPT,"?") ? "&" : "?"));
137 define("EWIKI_SERVER", ($_SERVER["HTTP_HOST"] ? $_SERVER["HTTP_HOST"] : $_SERVER["SERVER_NAME"]) . ( ($_SERVER["SERVER_PORT"] != "80") ? (":" . $_SERVER["SERVER_PORT"]) : ""));
138 define("EWIKI_BASE_URL", (@$_SERVER["HTTPS"] ? "https" : "http") . "://" . EWIKI_SERVER . substr(realpath(dirname(__FILE__)), strlen(realpath($_SERVER["DOCUMENT_ROOT"]))) . "/"); # URL to ewiki dir
139 define("EWIKI_BASE_DIR", dirname(__FILE__));
141 #-- binary content (images)
142 define("EWIKI_ENGAGE_BINARY", 1);
143 @define("EWIKI_SCRIPT_BINARY", /*"/binary.php?binary="*/ ltrim(strtok(" ".EWIKI_SCRIPT,"?"))."?".EWIKI_UP_BINARY."=" );
144 define("EWIKI_CACHE_IMAGES", 1 &&!headers_sent());
145 define("EWIKI_IMAGE_MAXSIZE", 64 *1024);
146 define("EWIKI_IMAGE_MAXWIDTH", 3072);
147 define("EWIKI_IMAGE_MAXHEIGHT", 2048);
148 define("EWIKI_IMAGE_MAXALLOC", 1<<19);
149 define("EWIKI_IMAGE_RESIZE", 1);
150 define("EWIKI_IMAGE_ACCEPT", "image/jpeg,image/png,image/gif,application/x-shockwave-flash");
151 define("EWIKI_IDF_INTERNAL", "internal://");
152 define("EWIKI_ACCEPT_BINARY", 0); # for arbitrary binary data files
155 define("EWIKI_TMP", isset($_SERVER["TEMP"]) ? $_SERVER["TEMP"] : "/tmp");
156 define("EWIKI_VAR", "./var"); # should be world-writable
157 define("EWIKI_LOGLEVEL", -1); # 0=error 1=warn 2=info 3=debug
158 define("EWIKI_LOGFILE", "/tmp/ewiki.log");
160 #-- plugins (tasks mapped to function names)
161 $ewiki_plugins["database"][] = "ewiki_database_mysql";
162 $ewiki_plugins["edit_preview"][] = "ewiki_page_edit_preview";
163 $ewiki_plugins["render"][] = "ewiki_format";
164 $ewiki_plugins["init"][-5] = "ewiki_localization";
165 if (EWIKI_ENGAGE_BINARY)
166 $ewiki_plugins["init"][-1] = "ewiki_binary";
167 $ewiki_plugins["handler"][-105] = "ewiki_eventually_initialize";
168 $ewiki_plugins["handler"][] = "ewiki_intermap_walking";
169 $ewiki_plugins["view_append"][-1] = "ewiki_control_links";
170 $ewiki_plugins["view_final"][-1] = "ewiki_add_title";
171 $ewiki_plugins["page_final"][] = "ewiki_http_headers";
172 $ewiki_plugins["page_final"][99115115] = "ewiki_page_css_container";
173 $ewiki_plugins["edit_form_final"][] = "ewiki_page_edit_form_final_imgupload";
174 $ewiki_plugins["format_block"]["pre"][] = "ewiki_format_pre";
175 $ewiki_plugins["format_block"]["code"][] = "ewiki_format_pre";
176 $ewiki_plugins["format_block"]["htm"][] = "ewiki_format_html";
177 $ewiki_plugins["format_block"]["html"][] = "ewiki_format_html";
178 $ewiki_plugins["format_block"]["comment"][] = "ewiki_format_comment";
181 $ewiki_plugins["page"][EWIKI_PAGE_LIST] = "ewiki_page_index";
182 $ewiki_plugins["page"][EWIKI_PAGE_NEWEST] = "ewiki_page_newest";
183 $ewiki_plugins["page"][EWIKI_PAGE_SEARCH] = "ewiki_page_search";
184 if (EWIKI_HIT_COUNTING) $ewiki_plugins["page"][EWIKI_PAGE_HITS] = "ewiki_page_hits";
185 $ewiki_plugins["page"][EWIKI_PAGE_VERSIONS] = "ewiki_page_versions";
186 $ewiki_plugins["page"][EWIKI_PAGE_UPDATES] = "ewiki_page_updates";
189 $ewiki_plugins["action"]["edit"] = "ewiki_page_edit";
190 $ewiki_plugins["action_always"]["links"] = "ewiki_page_links";
191 $ewiki_plugins["action"]["info"] = "ewiki_page_info";
192 $ewiki_plugins["action"]["view"] = "ewiki_page_view";
194 #-- helper vars ---------------------------------------------------
195 $ewiki_config["idf"]["url"] = array("http://", "mailto:", EWIKI_IDF_INTERNAL, "ftp://", "https://", "data:", "irc://", "telnet://", "news://", "chrome://", "file://", "gopher://", "httpz://");
196 $ewiki_config["idf"]["img"] = array(".jpeg", ".png", ".jpg", ".gif", ".j2k");
197 $ewiki_config["idf"]["obj"] = array(".swf", ".svg");
200 $ewiki_config["action_links"]["view"] = array(
201 "edit" => "EDITTHISPAGE", # ewiki_t() is called on these
202 "links" => "BACKLINKS",
203 "info" => "PAGEHISTORY",
204 "like" => "LIKEPAGES",
205 ) + (array)@$ewiki_config["action_links"]["view"];
206 $ewiki_config["action_links"]["info"] = array(
208 "edit" => "fetchback",
209 ) + (array)@$ewiki_config["action_links"]["info"];
211 #-- variable configuration settings (go into '$ewiki_config')
212 $ewiki_config_DEFAULTS_tmp = array(
213 "edit_thank_you" => 1,
214 "edit_box_size" => "77x17",
215 "print_title" => EWIKI_PRINT_TITLE,
216 "split_title" => EWIKI_SPLIT_TITLE,
217 "control_line" => EWIKI_CONTROL_LINE,
218 "list_limit" => EWIKI_LIST_LIMIT,
219 "script" => EWIKI_SCRIPT,
220 "script_url" => (defined("EWIKI_SCRIPT_URL")?EWIKI_SCRIPT_URL:NULL),
221 "script_binary" => EWIKI_SCRIPT_BINARY,
222 "qmark_links" => "0b?",
223 #-- heart of the wiki -- don't try to read this! ;)
224 "wiki_pre_scan_regex" => '/
226 ((?:(?:\w+:)*['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2,}[\w\d]*(?<!_))
227 |\^([-'.EWIKI_CHARS_L.EWIKI_CHARS_U.']{3,})
228 |\[ (?:"[^\]\"]+" | \s+ | [^:\]#]+\|)* ([^\|\"\[\]\#]+) (?:\s+ | "[^\]\"]+")* [\]\#]
229 |(\w{3,9}:\/\/[^\s\[\]\'\"()<>]+[^\s\[\]\'\"()<>!,.\-:;?])
231 "wiki_link_regex" => "\007 [!~\\\\]?(
232 \#?\[[^<>\[\]\n]+\] |
233 \w[-_.+\w]+@(\w[-_\w]+[.])+\w{2,} |
234 \^[-".EWIKI_CHARS_U.EWIKI_CHARS_L."]{3,} |
235 \b([\w]{3,}:)*([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}\#?[\w\d]* |
236 ([a-z]{2,9}://|mailto:|data:)[^\s\[\]\'\"()<>]+[^\s\[\]\'\"()<>,.!\-:;?]
238 #-- rendering ruleset
239 "wm_indent" => '<div style="margin-left:15px;" class="indent">',
240 "wm_table_defaults" => 'cellpadding="2" border="1" cellspacing="0"',
241 "wm_whole_line" => array(">>" => 'div align="right"'),
243 "wm_publishing_headers"=>0,
244 "htmlentities" => array(
249 "wm_source" => array(
251 "<br>" => "<br />",
253 "\n;:" => "\n ", # workaround, replaces the old ;:
256 "-" => array('ul type="square"', "", "li"),
257 "*" => array('ul type="circle"', "", "li"),
258 "#" => array("ol", "", "li"),
259 ":" => array("dl", "dt", "dd"),
260 #<out># ";" => array("dl", "dt", "dd"),
263 "'''''" => array("<b><i>", "</i></b>"),
264 "'''" => array("<b>", "</b>"),
265 "''" => array("<em>", "</em>"),
266 "__" => array("<strong>", "</strong>"),
267 "^^" => array("<sup>", "</sup>"),
268 "==" => array("<tt>", "</tt>"),
269 #<off># "___" => array("<i><b>", "</b></i>"),
270 #<off># "***" => array("<b><i>", "</i></b>"),
271 #<off># "###" => array("<big><b>", "</b></big>"),
272 #<broken+bug># "//" => array("<i>", "</i>"), # conflicts with URLs, could only be done with regex
273 "**" => array("<b>", "</b>"),
274 "##" => array("<big>", "</big>"),
275 "µµ" => array("<small>", "</small>"),
277 "wm_start_end" => array(
278 #<off># array("[-", "-]", "<s>", "</s>"),
279 #<off># array("(*", "*)", "<!--", "-->"),
281 #-- rendering plugins
282 "format_block" => array(
283 "html" => array("<html>", "</html>", "html", 0x0000),
284 "htm" => array("<htm>", "</htm>", "html", 0x0003),
285 "code" => array("<code>", "</code>", false, 0x0004),
286 "pre" => array("<pre>", "</pre>", false, 0x0027|4),
287 "comment" => array("\n<!--", "-->", false, 0x0030),
288 #<off># "verbatim" => array("<verbatim>", "</verbatim>", false, 0x0030),
290 "format_params" => array(
292 "html" => EWIKI_ALLOW_HTML,
296 #-- copy above settings into real _config[] array
297 foreach ($ewiki_config_DEFAULTS_tmp as $set => $val) {
298 if (!isset($ewiki_config[$set])) {
299 $ewiki_config[$set] = $val;
301 elseif (is_array($val)) foreach ($val as $vali=>$valv) {
303 $ewiki_config[$set][] = $valv;
305 elseif (!isset($ewiki_config[$set][$vali])) {
306 $ewiki_config[$set][$vali] = $valv;
310 $ewiki_config_DEFAULTS_tmp = $valv = $vali = $val = NULL;
313 $ewiki_config["ua"] = "ewiki/".EWIKI_VERSION
314 . " (".PHP_OS."; PHP/".PHP_VERSION.")" . @$ewiki_config["ua"];
317 #-- text (never remove the "C" or "en" sections!)
319 $ewiki_t["C"] = (array)@$ewiki_t["C"] + array(
320 "DATE" => "%a, %d %b %G %T %Z",
321 "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>',
324 $ewiki_t["en"] = (array)@$ewiki_t["en"] + array(
325 "EDITTHISPAGE" => "EditThisPage",
326 "APPENDTOPAGE" => "Add to",
327 "BACKLINKS" => "BackLinks",
328 "EDITCOMPLETE" => 'Your edit has been saved click <a href="$url">here</a> to see the edited page.',
329 "PAGESLINKINGTO" => "Pages linking to \$title",
330 "PAGEHISTORY" => "PageInfo",
331 "INFOABOUTPAGE" => "Information about page",
332 "LIKEPAGES" => "Pages like this",
333 "NEWESTPAGES" => "Newest Pages",
334 "LASTCHANGED" => "last changed on %c",
335 "DOESNOTEXIST" => "This page does not yet exist, please click on EditThisPage if you'd like to create it.",
336 "DISABLEDPAGE" => "This page is currently not available.",
337 "ERRVERSIONSAVE" => "Sorry, while you edited this page someone else
338 did already save a changed version. Please go back to the
339 previous screen and copy your changes to your computers
340 clipboard to insert it again after you reload the edit
342 "ERRORSAVING" => "An error occoured while saving your changes. Please try again.",
343 "THANKSFORCONTRIBUTION" => "Thank you for your contribution!",
344 "CANNOTCHANGEPAGE" => "This page cannot be changed.",
345 "OLDVERCOMEBACK" => "Make this old version come back to replace the current one",
346 "PREVIEW" => "Preview",
348 "CANCEL_EDIT" => "CancelEditing",
349 "UPLOAD_PICTURE_BUTTON" => "upload picture >>>",
350 "EDIT_FORM_1" => "It is <a href=\"".EWIKI_SCRIPT."GoodStyle\">GoodStyle</a>
351 to just start writing. With <a href=\"".EWIKI_SCRIPT."WikiMarkup\">WikiMarkup</a>
352 you can style your text later.<br />",
353 "EDIT_FORM_2" => "<br />Please do not write things, which may make other
354 people angry. And please keep in mind that you are not all that
355 anonymous in the internet (find out more about your computers
356 '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' at Google).",
357 "BIN_IMGTOOLARGE" => "Image file is too large!",
358 "BIN_NOIMG" => "This is no image file (inacceptable file format)!",
359 "FORBIDDEN" => "You are not authorized to access this page.",
362 $ewiki_t["es"] = (array)@$ewiki_t["es"] + array(
363 "EDITTHISPAGE" => "EditarEstaPágina",
364 "BACKLINKS" => "EnlacesInversos",
365 "PAGESLINKINGTO" => "Páginas enlazando \$title",
366 "PAGEHISTORY" => "InfoPágina",
367 "INFOABOUTPAGE" => "Información sobre la página",
368 "LIKEPAGES" => "Páginas como esta",
369 "NEWESTPAGES" => "Páginas más nuevas",
370 "LASTCHANGED" => "última modificación %d/%m/%Y a las %H:%M",
371 "DOESNOTEXIST" => "Esta página aún no existe, por favor eliga EditarEstaPágina si desea crearla.",
372 "DISABLEDPAGE" => "Esta página no está disponible en este momento.",
373 "ERRVERSIONSAVE" => "Disculpe, mientras editaba esta página alguién más
374 salvó una versión modificada. Por favor regrese a
375 a la pantalla anterior y copie sus cambios a su computador
376 para insertalos nuevamente después de que cargue
377 la pantalla de edición.",
378 "ERRORSAVING" => "Ocurrió un error mientras se salvavan sus cambios. Por favor intente de nuevo.",
379 "THANKSFORCONTRIBUTION" => "Gracias por su contribución!",
380 "CANNOTCHANGEPAGE" => "Esta página no puede ser modificada.",
381 "OLDVERCOMEBACK" => "Hacer que esta versión antigua regrese a remplazar la actual",
382 "PREVIEW" => "Previsualizar",
384 "CANCEL_EDIT" => "CancelarEdición",
385 "UPLOAD_PICTURE_BUTTON" => "subir gráfica >>>",
386 "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."BuenEstilo\">BuenEstilo</a> es
387 escribir lo que viene a su mente. No se preocupe mucho
388 por la apariencia. También puede agregar <a href=\"".EWIKI_SCRIPT."ReglasDeMarcadoWiki\">ReglasDeMarcadoWiki</a>
389 más adelante si piensa que es necesario.<br />",
390 "EDIT_FORM_2" => "<br />Por favor no escriba cosas, que puedan
391 enfadar a otras personas. Y por favor tenga en mente que
392 usted no es del todo anónimo en Internet
394 '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' de su computador con Google).",
395 "BIN_IMGTOOLARGE" => "¡La gráfica es demasiado grande!",
396 "BIN_NOIMG" => "¡No es un archivo con una gráfica (formato de archivo inaceptable)!",
397 "FORBIDDEN" => "No está autorizado para acceder a esta página.",
400 $ewiki_t["de"] = (array)@$ewiki_t["de"] + array(
401 "EDITTHISPAGE" => "DieseSeiteÄndern",
402 "APPENDTOPAGE" => "Ergänze",
403 "BACKLINKS" => "ZurückLinks",
404 "PAGESLINKINGTO" => "Verweise zur Seite \$title",
405 "PAGEHISTORY" => "SeitenInfo",
406 "INFOABOUTPAGE" => "Informationen über Seite",
407 "LIKEPAGES" => "Ähnliche Seiten",
408 "NEWESTPAGES" => "Neueste Seiten",
409 "LASTCHANGED" => "zuletzt geändert am %d.%m.%Y um %H:%M",
410 "DISABLEDPAGE" => "Diese Seite kann momentan nicht angezeigt werden.",
411 "ERRVERSIONSAVE" => "Entschuldige, aber während Du an der Seite
412 gearbeitet hast, hat bereits jemand anders eine geänderte
413 Fassung gespeichert. Damit nichts verloren geht, browse bitte
414 zurück und speichere Deine Änderungen in der Zwischenablage
415 (Bearbeiten->Kopieren) um sie dann wieder an der richtigen
416 Stelle einzufügen, nachdem du die EditBoxSeite nocheinmal
418 Vielen Dank für Deine Mühe.",
419 "ERRORSAVING" => "Beim Abspeichern ist ein Fehler aufgetreten. Bitte versuche es erneut.",
420 "THANKSFORCONTRIBUTION" => "Vielen Dank für Deinen Beitrag!",
421 "CANNOTCHANGEPAGE" => "Diese Seite kann nicht geändert werden.",
422 "OLDVERCOMEBACK" => "Diese alte Version der Seite wieder zur Aktuellen machen",
423 "PREVIEW" => "Vorschau",
424 "SAVE" => "Speichern",
425 "CANCEL_EDIT" => "ÄnderungenVerwerfen",
426 "UPLOAD_PICTURE_BUTTON" => "Bild hochladen >>>",
427 "EDIT_FORM_1" => "Es ist <a href=\"".EWIKI_SCRIPT."GuterStil\">GuterStil</a>,
428 einfach drauf los zu tippen. Mit den <a href=\"".EWIKI_SCRIPT."FormatierungsRegeln\">FormatierungsRegeln</a>
429 kannst du den Text später noch umgestalten.<br />",
430 "EDIT_FORM_2" => "<br />Bitte schreib keine Dinge, die andere Leute
431 verärgern könnten. Und bedenke auch, daß es schnell auf
432 dich zurückfallen kann wenn du verschiedene andere Dinge sagst (mehr Informationen zur
433 '<a href=\"http://google.de/search?q=computer+IP+adresse\">IP Adresse</a>'
434 deines Computers findest du bei Google).",
436 $ewiki_t["nl"] = (array)@$ewiki_t["nl"] + array(
437 "EDITTHISPAGE" => "BewerkPagina",
441 $ewiki_config["interwiki"] = (array)@$ewiki_config["interwiki"] +
443 "javascript" => "", # this actually protects from javascript: links
445 "jump" => "", # fallback; if jump plugin isn't loaded
447 "this" => defined("EWIKI_SCRIPT_URL")?EWIKI_SCRIPT_URL:EWIKI_SCRIPT,
449 "ErfurtWiki" => "http://erfurtwiki.sourceforge.net/",
450 "InterWiki" => "MetaWiki",
451 "MetaWiki" => "http://sunir.org/apps/meta.pl?",
452 "Wiki" => "WardsWiki",
453 "WardsWiki" => "http://www.c2.com/cgi/wiki?",
454 "WikiFind" => "http://c2.com/cgi/wiki?FindPage&value=",
455 "WikiPedia" => "http://www.wikipedia.com/wiki.cgi?",
456 "MeatBall" => "MeatballWiki",
457 "MeatballWiki" => "http://www.usemod.com/cgi-bin/mb.pl?",
458 "UseMod" => "http://www.usemod.com/cgi-bin/wiki.pl?",
459 "CommunityWiki" => "http://www.emacswiki.org/cgi-bin/community/",
460 "WikiFeatures" => "http://wikifeatures.wiki.taoriver.net/moin.cgi/",
461 "PhpWiki" => "http://phpwiki.sourceforge.net/phpwiki/index.php3?",
462 "LinuxWiki" => "http://linuxwiki.de/",
463 "OpenWiki" => "http://openwiki.com/?",
464 "Tavi" => "http://andstuff.org/tavi/",
465 "TWiki" => "http://twiki.sourceforge.net/cgi-bin/view/",
466 "MoinMoin" => "http://www.purl.net/wiki/moin/",
467 "Google" => "http://google.com/search?q=",
468 "ISBN" => "http://www.amazon.com/exec/obidos/ISBN=",
469 "icq" => "http://www.icq.com/",
477 #-------------------------------------------------------------------- init ---
480 #-- bring up database backend
481 if (!isset($ewiki_db) && ($pf = $ewiki_plugins["database"][0])) {
482 if (class_exists($pf)) {
485 elseif (function_exists($pf)) {
486 include("plugins/db/oldapi.php"); // eeeyk! temporary workaround!
490 #-- init stuff, autostarted parts (done a 2nd time inside ewiki_page)
491 if ($pf_a = $ewiki_plugins["init"]) {
493 foreach ($pf_a as $pf) {
496 unset($ewiki_plugins["init"]);
501 #-------------------------------------------------------------------- main ---
503 /* This is the main function, which you should preferrably call to
504 integrate the ewiki into your web site; it chains to most other
505 parts and plugins (including the edit box).
506 If you do not supply the requested pages "$id" we will fetch it
507 from the pre-defined possible URL parameters.
509 function ewiki_page($id=false) {
511 global $ewiki_links, $ewiki_plugins, $ewiki_ring, $ewiki_t,
512 $ewiki_errmsg, $ewiki_data, $ewiki_title, $ewiki_id,
513 $ewiki_action, $ewiki_config;
524 $action = EWIKI_DEFAULT_ACTION;
525 if ($delim = strpos($id, EWIKI_ACTION_SEP_CHAR)) {
526 $a = substr($id, 0, $delim);
527 if (EWIKI_ACTION_TAKE_ASIS || in_array($a, $ewiki_plugins["action"]) || in_array($a, $ewiki_plugins["action_always"])) {
528 $action = rawurlencode($a);
529 $id = substr($id, $delim + 1);
533 if (EWIKI_USE_ACTION_PARAM && isset($_REQUEST["action"])) {
534 $action = rawurlencode($_REQUEST["action"]);
536 $ewiki_data = array();
538 $ewiki_title = ewiki_split_title($id);
539 $ewiki_action = $action;
541 #-- more initialization
542 if ($pf_a = @$ewiki_plugins["init"]) {
544 foreach ($pf_a as $pf) {
547 unset($ewiki_plugins["init"]);
549 #-- micro-gettext stub (for upcoming/current transition off of ewiki_t)
550 if (!function_exists("_")) {
551 function _($text) { return($text); }
552 function gettext($text) { return($text); }
557 if (!isset($_REQUEST["content"]) && ($version = 0 + @$_REQUEST["version"])) {
558 $ewiki_config["forced_version"] = $version;
560 $ewiki_data = ewiki_db::GET($id, $version);
561 $data = &$ewiki_data;
563 #-- pre-check if actions exist
564 $pf_page = ewiki_array($ewiki_plugins["page"], $id);
566 #-- edit <form> or info/ page for non-existent and empty pages
567 if (($action==EWIKI_DEFAULT_ACTION) && empty($data["content"]) && empty($pf_page)) {
568 if ($data["version"] >= 2) {
571 elseif (EWIKI_AUTO_EDIT) {
575 $data["content"] = ewiki_t("DOESNOTEXIST");
579 #-- internal "create" action / used for authentication requests
580 if (($action == "edit")&&(($data["version"]==0) && !isset($pf_page))) {
581 $ewiki_config["create"] = $id;
585 if (EWIKI_PROTECTED_MODE) {
586 if (!ewiki_auth($id, $data, $action, $ring=false, $force=EWIKI_AUTO_LOGIN)) {
587 return($o.=$ewiki_errmsg);
593 if ($pf_a = @$ewiki_plugins["handler"]) {
595 foreach ($pf_a as $pf_i=>$pf) {
596 if ($handler_o = $pf($id, $data, $action, $pf_i)) { break; }
599 #-- stop here if page is not marked as _TEXT,
600 # perform authentication then, and let only administrators proceed
602 if (!empty($data["flags"]) && (($data["flags"] & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT)) {
603 if (($data["flags"] & EWIKI_DB_F_BINARY) && ($pf = $ewiki_plugins["handler_binary"][0])) {
604 return($pf($id, $data, $action)); //_BINARY entries handled separately
606 elseif ((!EWIKI_PROTECTED_MODE || !ewiki_auth($id, $data, $action, 0, 1)) && ($ewiki_ring!=0)) {
607 return(ewiki_t("DISABLEDPAGE"));
612 #-- finished by handler
616 #-- actions that also work for static and internal pages
617 elseif (($pf = @$ewiki_plugins["action_always"][$action]) && function_exists($pf)) {
618 $o .= $pf($id, $data, $action);
621 elseif ($pf_page && function_exists($pf_page)) {
622 $o .= $pf_page($id, $data, $action);
626 $pf = @$ewiki_plugins["action"][$action];
628 #-- fallback to "view" action
629 if (empty($pf) || !function_exists($pf)) {
631 $pf = "ewiki_page_view";
632 $action = "view"; // we could also allow different (this is a
633 // catch-all) view variants, but this would lead to some problems
636 $o .= $pf($id, $data, $action);
639 #-- error instead of page?
640 if (empty($o) && $ewiki_errmsg) {
644 #-- html post processing
645 if ($pf_a = $ewiki_plugins["page_final"]) {
647 foreach ($pf_a as $pf) {
648 $pf($o, $id, $data, $action);
652 if (EWIKI_ESCAPE_AT && !isset($ewiki_config["@"])) {
653 $o = str_replace("@", "@", $o);
656 $ewiki_data = &$data;
657 unset($ewiki_data["content"]);
663 #-- HTTP meta headers
664 function ewiki_http_headers(&$o, $id, &$data, $action, $saveasfilename=1) {
665 global $ewiki_t, $ewiki_config;
666 if (EWIKI_HTTP_HEADERS && !headers_sent()) {
668 if (($uu = @$data["id"]) && $saveasfilename) @header('Content-Disposition: inline; filename="' . urlencode($uu) . '.html"');
669 if ($uu = @$data["version"]) @header('Content-Version: ' . $uu);
670 if ($uu = @$data["lastmodified"]) @header('Last-Modified: ' . gmstrftime($ewiki_t["C"]["DATE"], $uu));
672 if (EWIKI_NO_CACHE) {
673 header('Expires: ' . gmstrftime($ewiki_t["C"]["DATE"], UNIX_MILLENNIUM));
674 header('Pragma: no-cache');
675 header('Cache-Control: no-cache, must-revalidate' . (($ewiki_author||EWIKI_PROTECTED_MODE)?", private":"") );
676 # ", private" flag only for authentified users / _PROT_MODE
679 if ($data["version"] && ($etag=ewiki_etag($data)) || ($etag=md5($o))) {
680 $weak = "W/" . urlencode($id) . "." . $data["version"];
681 header("ETag: \"$etag\""); ###, \"$weak\"");
682 header("X-Server: $ewiki_config[ua]");
686 function ewiki_etag(&$data) {
687 return( urlencode($data["id"]) . ":" . dechex($data["version"]) . ":ewiki:" .
688 dechex(crc32($data["content"]) & 0x7FFFBFFF) );
693 #-- encloses whole page output with a descriptive <div>
694 function ewiki_page_css_container(&$o, &$id, &$data, &$action) {
695 $sterilized_id = trim(preg_replace('/[^\w\d]+/', "-", $id), "-");
696 $sterilized_id = preg_replace('/^(\d)/', 'page$1', $sterilized_id);
697 $o = "<div class=\"wiki $action $sterilized_id\">\n" . $o . "\n</div>\n";
702 function ewiki_split_title ($id='', $split=-1, $entities=1) {
704 $split = $GLOBALS["ewiki_config"]["split_title"];
706 strlen($id) or ($id = $GLOBALS["ewiki_id"]);
708 $id = preg_replace("/([".EWIKI_CHARS_L."])([".EWIKI_CHARS_U."]+)/", "$1 $2", $id);
710 return($entities ? htmlentities($id) : $id);
715 function ewiki_add_title(&$html, $id, &$data, $action, $go_action="links") {
716 if (EWIKI_PRINT_TITLE)
717 $html = "<div class=\"text-head\">\n"
718 . ewiki_make_title($id, '', 1, $action, $go_action)
719 . "\n</div>\n" . $html;
723 function ewiki_make_title($id='', $title='', $class=3, $action="view", $go_action="links", $may_split=1) {
725 global $ewiki_config, $ewiki_plugins, $ewiki_title, $ewiki_id;
728 if ($pf = @$ewiki_plugins["make_title"][0]) {
729 return($pf($title, $class, $action, $go_action, $may_split));
732 elseif (!$ewiki_config["print_title"]) {
742 if (!strlen($title)) {
743 $title = $ewiki_title; // already in &html; format
745 elseif ($ewiki_config["split_title"] && $may_split) {
746 $title = ewiki_split_title($title, $ewiki_config["split_title"], 0&($title!=$ewiki_title));
749 $title = htmlentities($title);
753 if ($pf_a = @$ewiki_plugins["title_transform"]) {
754 foreach ($pf_a as $pf) { $pf($id, $title, $go_action); }
757 #-- clickable link or simple headline
758 if ($class <= $ewiki_config["print_title"]) {
759 if ($uu = @$ewiki_config["link_title_action"][$action]) {
762 if ($uu = @$ewiki_config["link_title_url"]) {
764 unset($ewiki_config["link_title_url"]);
767 $href = ewiki_script($go_action, $id);
769 $o = '<a href="' . $href . '">' . ($title) . '</a>';
775 // h2.page.title is obsolete; h2.text-title recommended
776 return('<h2 class="text-title page title">' . $o . '</h2>');
782 function ewiki_page_view($id, &$data, $action, $all=1) {
784 global $ewiki_plugins, $ewiki_config;
787 #-- render requested wiki page <-- goal !!!
788 $render_args = array(
790 "html" => (EWIKI_ALLOW_HTML||(@$data["flags"]&EWIKI_DB_F_HTML)),
792 $o .= '<div class="text-body">' . "\n"
793 . $ewiki_plugins["render"][0] ($data["content"], $render_args)
799 #-- control line + other per-page info stuff
800 if ($pf_a = $ewiki_plugins["view_append"]) {
802 $o .= "<div class=\"wiki-plugins\">\n";
803 foreach ($pf_a as $n => $pf) { $o .= $pf($id, $data, $action); }
806 if ($pf_a = $ewiki_plugins["view_final"]) {
808 foreach ($pf_a as $n => $pf) { $pf($o, $id, $data, $action); }
811 if (!empty($_REQUEST["thankyou"]) && $ewiki_config["edit_thank_you"]) {
812 $o = '<div class="text-prefix system-message">'
813 . ewiki_t("THANKSFORCONTRIBUTION") . "</div>\n" . $o;
816 if (EWIKI_HIT_COUNTING) {
826 #-------------------------------------------------------------------- util ---
829 /* retrieves "$id/$action" string from URL / QueryString / PathInfo,
830 change this in conjunction with ewiki_script() to customize your URLs
831 further whenever desired
833 function ewiki_id() {
834 ($id = @$_REQUEST["id"]) or
835 ($id = @$_REQUEST["name"]) or
836 ($id = @$_REQUEST["page"]) or
837 ($id = @$_REQUEST["file"]) or
838 (EWIKI_USE_PATH_INFO)
839 and isset($_SERVER["PATH_INFO"])
840 and ($_SERVER["PATH_INFO"] != $_SERVER["SCRIPT_NAME"]) // Apache+PHP workaround
841 and (preg_replace('/\/\d+\/'.EWIKI_PAGE_PRETTY_URL.'/', '', $_SERVER['PATH_INFO']) != '')
842 and ($id = ltrim($_SERVER["PATH_INFO"], "/")) or
843 (!isset($_REQUEST["id"])) and ($id = trim(strtok($_SERVER["QUERY_STRING"], "&?;")));
844 if (!strlen($id) || ($id=="id=")) {
845 $id = EWIKI_PAGE_INDEX;
847 (EWIKI_URLDECODE) && ($id = urldecode($id));
854 /* replaces EWIKI_SCRIPT, works more sophisticated, and
855 bypasses various design flaws
856 - if only the first parameter is used (old style), it can contain
857 a complete "action/WikiPage" - but this is ambigutious
858 - else $asid is the action, and $id contains the WikiPageName
859 - $ewiki_config["script"] will now be used in favour of the constant
860 - needs more work on _BINARY, should be a separate function
862 function ewiki_script($asid, $id=false, $params="", $bin=0, $html=1, $script=NULL) {
864 global $ewiki_config, $ewiki_plugins;
866 #-- get base script url from config vars
867 if (empty($script)) {
868 $script = &$ewiki_config[!$bin?"script":"script_binary"];
870 $alt_style = (EWIKI_USE_ACTION_PARAM >= 2);
871 $ins_prefix = (EWIKI_ACTION_TAKE_ASIS);
873 #-- separate $action and $id for old style requests
875 if (strpos($asid, EWIKI_ACTION_SEP_CHAR) !== false) {
876 $asid = strtok($asid, EWIKI_ACTION_SEP_CHAR);
877 $id = strtok("\000");
886 if (is_array($params)) {
889 if ($uu) foreach ($uu as $k=>$v) {
890 $params .= (strlen($params)? "&" : "") . rawurlencode($k) . "=" . rawurlencode($v);
893 #-- use action= parameter instead of prefix/
895 $params = "action=$asid" . (strlen($params)? "&": "") . $params;
901 #-- workaround slashes in $id
902 if (empty($asid) && (strpos($id, EWIKI_ACTION_SEP_CHAR) !== false) && !$bin && $ins_prefix) {
903 $asid = EWIKI_DEFAULT_ACTION;
905 /*paranoia*/ $asid = trim($asid, EWIKI_ACTION_SEP_CHAR);
908 if (EWIKI_URLENCODE) {
909 $id = urlencode($id);
910 $asid = urlencode($asid);
913 // only urlencode &, %, ? for example
917 $id = $asid . EWIKI_ACTION_SEP_CHAR . $id; #= "action/PageName"
919 if (strpos($url, "%s") !== false) {
920 $url = str_replace("%s", $id, $url);
927 if (strlen($params)) {
928 $url .= (strpos($url,"?")!==false ? "&":"?") . $params;
933 $url = str_replace("&", "&", $url);
939 /* this ewiki_script() wrapper is used to generate URLs to binary
940 content in the ewiki database
942 function ewiki_script_binary($asid, $id=false, $params=array(), $upload=0) {
944 $upload |= is_string($params) && strlen($params) || count($params);
946 #-- generate URL directly to the plainly saved data file,
947 # see also plugins/db/binary_store
948 if (defined("EWIKI_DB_STORE_URL") && !$upload) {
949 $url = EWIKI_DB_STORE_URL . urlencode(rawurlencode(strtok($id, "?")));
952 #-- else get standard URL (thru ewiki.php) from ewiki_script()
954 $url = ewiki_script($asid, $id, $params, "_BINARY=1");
961 /* this function returns the absolute ewiki_script url, if EWIKI_SCRIPT_URL
962 is set, else it guesses the value
964 function ewiki_script_url($asid="", $id="", $params="") {
966 global $ewiki_action, $ewiki_id, $ewiki_config;
969 return ewiki_script($asid, $id, $params, false, true, ewiki_script_url());
971 if ($url = $ewiki_config["script_url"]) {
975 $scr_template = $ewiki_config["script"];
976 $scr_current = ewiki_script($ewiki_action, $ewiki_id);
977 $req_uri = $_SERVER["REQUEST_URI"];
978 $qs = $_SERVER["QUERY_STRING"]?1:0;
979 $sn = $_SERVER["SCRIPT_NAME"];
981 if (($p = strpos($req_uri, $scr_current)) !== false) {
982 $url = substr($req_uri, 0, $p) . $scr_template;
984 elseif (($qs) && (strpos($scr_template, "?") !== false)) {
985 $url = substr($req_uri, 0, strpos($req_uri, "?"))
986 . substr($scr_template, strpos($scr_template, "?"));
988 elseif (($p = strrpos($sn, "/")) && (strncmp($req_uri, $sn, $p) == 0)) {
992 return(NULL); #-- could not guess it
995 $url = (@$_SERVER["HTTPS"] ? "https" : "http") . "://"
996 . EWIKI_SERVER . $url;
998 return($ewiki_config["script_url"] = $url);
1004 #------------------------------------------------------------ page plugins ---
1008 function ewiki_page_links($id, &$data, $action) {
1009 $o = ewiki_make_title($id, ewiki_t("PAGESLINKINGTO", array("title"=>$id)), 1, $action, "", "_MAY_SPLIT=1");
1010 if ($pages = ewiki_get_backlinks($id)) {
1011 $o .= ewiki_list_pages($pages);
1013 $o .= ewiki_t("This page isn't linked from anywhere else.");
1018 #-- get all pages, that are linking to $id
1019 function ewiki_get_backlinks($id) {
1020 $result = ewiki_db::SEARCH("refs", $id);
1022 $id_i = EWIKI_CASE_INSENSITIVE ? strtolower($id) : $id;
1023 while ($row = $result->get(0, 0x0077)) {
1024 if (strpos(EWIKI_CASE_INSENSITIVE ?strtolower($row["refs"]) :$row["refs"], "\n$id_i\n") !== false) {
1025 $pages[] = $row["id"];
1031 #-- get all existing pages (as array of pagenames), that are linked from $id
1032 function ewiki_get_links($id) {
1033 if ($data = ewiki_db::GET($id)) {
1034 $refs = explode("\n", trim($data["refs"]));
1036 foreach (ewiki_db::FIND($refs) as $id=>$exists) {
1047 #-- outputs listing from page name array
1048 function ewiki_list_pages($pages=array(), $limit=NULL,
1049 $value_as_title=0, $pf_list=false)
1051 global $ewiki_plugins;
1054 if (!isset($limit)) {
1055 ($limit = 0 + $_REQUEST[EWIKI_UP_LISTLIM])
1056 or ($limit = EWIKI_LIST_LIMIT);
1058 $is_num = !empty($pages[0]);
1062 if ($pages) foreach ($pages as $id=>$add_text) {
1067 if (is_array($add_text)) {
1068 list($id, $params, $title, $add_text) = $add_text;
1069 if (!$title) { $title = $id; }
1072 $id = $title = $add_text;
1075 elseif ($value_as_title) {
1080 $lines[] = '<a href="' . ewiki_script("", $id, $params) . '">' . ewiki_split_title($title) . '</a> ' . $add_text;
1082 if (($limit > 0) && ($n++ >= $limit)) {
1087 if ($pf_a = @$ewiki_plugins["list_transform"]) {
1088 foreach ($pf_a as $pf_transform) {
1089 $pf_transform($lines);
1093 if (($pf_list) || ($pf_list = @$ewiki_plugins["list_pages"][0])) {
1094 $o = $pf_list($lines);
1097 $o = "· " . implode("<br />\n· ", $lines) . "<br />\n";
1104 #---------------------------------------------------------- page plugins ---
1107 #-- list of all existing pages (without hidden + protected)
1108 function ewiki_page_index($id=0, $data=0, $action=0, $args=array()) {
1110 global $ewiki_plugins;
1112 $o = ewiki_make_title($id, $id, 2);
1114 $exclude = $args ? ("\n" . implode("\n", preg_split("/\s*[,;:\|]\s*/", $args["exclude"])) . "\n") : "";
1116 $sorted = array_keys($ewiki_plugins["page"]);
1118 $result = ewiki_db::GETALL(array("flags"), EWIKI_DB_F_TYPE, EWIKI_DB_F_TEXT);
1119 while ($row = $result->get(0, 0x0037, EWIKI_DB_F_TEXT)) {
1120 if (!stristr($exclude, "\n".$row["id"]."\n")) {
1121 $sorted[] = $row["id"];
1124 natcasesort($sorted);
1126 $o .= ewiki_list_pages($sorted, 0, 0, $ewiki_plugins["list_dict"][0]);
1132 #-- scans database for extremes (by given page meta data information),
1133 # generates page listing then from list
1134 //@TODO: split $asc parameter into $asc and $firstver
1135 function ewiki_page_ordered_list($orderby="created", $asc=0, $print="%n", $title="", $bad_flags=0) {
1137 $o = ewiki_make_title("", $title, 2, ".list", "links", 0);
1140 $result = ewiki_db::GETALL(array($orderby));
1142 while ($row = $result->get(0, 0x0037, EWIKI_DB_F_TEXT)) {
1144 // version 1 is most accurate for {hits}
1145 $row = ewiki_db::GET($row["id"], 1);
1147 if (! ($bad_flags & $row["flags"])) {
1148 $sorted[$row["id"]] = $row[$orderby];
1152 if ($asc != 0) { arsort($sorted); }
1153 else { asort($sorted); }
1155 if ($sorted) foreach ($sorted as $name => $value) {
1156 if (empty($value)) { $value = "0"; }
1157 $sorted[$name] = strftime(str_replace('%n', $value, $print), $value);
1159 $o .= ewiki_list_pages($sorted);
1166 function ewiki_page_newest($id, $data, $action) {
1167 return( ewiki_page_ordered_list("created", -1, ewiki_t("LASTCHANGED"), ewiki_t("NEWESTPAGES")) );
1170 function ewiki_page_updates($id, $data, $action) {
1171 return ewiki_page_ordered_list("lastmodified", -1, ewiki_t("LASTCHANGED"), EWIKI_PAGE_UPDATES, EWIKI_DB_F_MINOR);
1174 function ewiki_page_hits($id, $data, $action) {
1175 return( ewiki_page_ordered_list("hits", 1, "%n hits", EWIKI_PAGE_HITS) );
1178 function ewiki_page_versions($id, $data, $action) {
1179 return( ewiki_page_ordered_list("version", -1, "%n changes", EWIKI_PAGE_VERSIONS) );
1188 function ewiki_page_search($id, &$data, $action) {
1190 $o = ewiki_make_title($id, $id, 2, $action);
1192 if (! ($q = @$_REQUEST["q"])) {
1193 $o .= "None Found<br />";
1194 $o .= '<form action="' . ewiki_script("", $id) . '" method="POST">';
1195 $o .= ewiki_form("q::30", "") . '<br /><br />';
1196 $o .= ewiki_form(":submit", $id);
1202 $q = preg_replace('/\s*[^\041-\175\200-\377]\s*/', ' ', $q);
1203 if ($q) foreach (explode(" ", $q) as $search) {
1205 if (empty($search)) { continue; }
1207 $result = ewiki_db::SEARCH("content", $search);
1209 while ($row = $result->get()) {
1211 #-- show this entry in page listings?
1212 if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($row["id"], $row, "view")) {
1216 $found[] = $row["id"];
1219 $o .= ewiki_list_pages($found);
1228 function ewiki_page_info($id, &$data, $action) {
1230 global $ewiki_plugins, $ewiki_config, $ewiki_links;
1232 $o = ewiki_make_title($id, ewiki_t("INFOABOUTPAGE")." '{$id}'", 2, $action,"", "_MAY_SPLIT=1");
1235 "TEXT", "BIN", "DISABLED", "HTML", "READONLY", "WRITEABLE",
1236 "APPENDONLY", "SYSTEM", "PART", 10=>"HIDDEN", 17=>"EXEC",
1239 "version", "author",
1240 "lastmodified", "created", "hits", "refs",
1241 "flags", "meta", "content"
1243 $no_refs = (boolean)$ewiki_config["info_refs_once"];
1245 #-- versions to show
1246 $v_start = $data["version"];
1247 if ( ($uu=0+@$_REQUEST[EWIKI_UP_PAGENUM]) && ($uu<=$v_start) ) {
1250 $v_end = $v_start - $ewiki_config["list_limit"];
1251 if ( ($uu=0+@$_REQUEST[EWIKI_UP_PAGEEND]) && ($uu<=$v_start) ) {
1254 $v_end = max($v_end, 1);
1257 # the very ($first) entry is rendered more verbosely than the others
1258 for ($v=$v_start,$first=1; ($v>=$v_end); $v--,$first=0) {
1260 $current = ewiki_db::GET($id, $v);
1262 if (!strlen(trim($current["id"])) || !$current["version"]) {
1266 $o .= '<table class="version-info" border="0" cellpadding="2" cellspacing="1">' . "\n";
1268 #-- additional info-actions
1269 $o .= '<tr><td></td><td class="action-links">';
1270 $o .= ewiki_control_links_list($id, $data, $ewiki_config["action_links"]["info"], $current["version"]);
1271 $o .= "</td></tr>\n";
1273 #-- print page database entry
1274 foreach($show as $i) {
1276 $value = @$current[$i];
1278 #-- show database {fields} differently
1281 if ($value) foreach ($value as $n2=>$d2) {
1282 foreach ((array)$d2 as $n=>$d) {
1283 if (is_int($n)) { $n = $n2; } else { $n = "_$n"; }
1284 $str .= htmlentities("$n: $d") . "<br />\n";
1289 elseif (($i =="lastmodified")||($i =="created")) { #-- {lastmodified}, {created}
1290 $value = strftime("%c", $value);
1292 elseif ($i == "content") {
1293 $value = strlen(trim($value)) . " bytes";
1294 $i = "content size";
1296 elseif ($first && ($i == "refs") && !(EWIKI_PROTECTED_MODE && (EWIKI_PROTECTED_MODE_HIDING>=2))) {
1297 $a = explode("\n", trim($value));
1298 $ewiki_links = ewiki_db::FIND($a);
1299 ewiki_merge_links($ewiki_links);
1300 foreach ($a as $n=>$link) {
1301 $a[$n] = ewiki_link_regex_callback(array("$link"), "force_noimg");
1303 $value = implode(", ", $a);
1305 elseif (strpos($value, "\n") !== false) { #-- also for {refs}
1306 if ($no_refs && ($i == "refs")) { continue; }
1307 $value = str_replace("\n", ", ", trim($value));
1309 elseif ($i == "version") {
1310 $value = '<a href="' .
1311 ewiki_script("", $id, array("version"=>$value)) . '">' .
1314 elseif ($i == "flags") {
1316 for ($n = 0; $n < 32; $n++) {
1317 if ($value & (1 << $n)) {
1318 if (! ($s=$flagnames[$n])) { $s = "UU$n"; }
1324 elseif ($i == "author") {
1325 $value = ewiki_author_html($value);
1328 $o .= '<tr class="page-' . $i . '"><td valign="top"><b>' . $i . '</b></td>' .
1329 '<td>' . $value . "</td></tr>\n";
1333 $o .= "</table><br />\n";
1336 #-- page result split
1338 $o .= "<br /><div class=\"chunk-list\">\n" . ewiki_chunked_page($action, $id, -1, $v+1, 1) . "\n</div><br />";
1340 #-- ext info actions
1341 $o .= '<div class="summary control-links">' . ewiki_control_links_list($id, $data, $ewiki_config["action_links"]["summary"]) . "</div>\n";
1349 function ewiki_chunked_page($action, $id, $dir=-1, $start=10, $end=1, $limit=0, $overlap=0.25, $collapse_last=0.67) {
1351 global $ewiki_config;
1353 if (empty($limit)) {
1354 $limit = $ewiki_config["list_limit"];
1357 $overlap = (int) ($limit * $overlap);
1365 $n -= $dir * $overlap;
1367 $e = $n + $dir * ($limit + $overlap);
1371 if ($e <= $collapse_last * $limit) {
1377 if ($e >= $collapse_last * $limit) {
1382 $o .= ($o?" · ":"")
1383 . '<a href="xxx'.ewiki_script($action, $id, array(EWIKI_UP_PAGENUM=>$n, EWIKI_UP_PAGEEND=>$e))
1384 . '">'. "$n-$e" . '</a>';
1386 if (($n=$e) <= $end) {
1391 return('<div class="chunked-result">'. $o .'</div>');
1399 function ewiki_page_edit($id, $data, $action) {
1401 global $ewiki_links, $ewiki_author, $ewiki_plugins, $ewiki_ring,
1402 $ewiki_errmsg, $ewiki_config;
1404 $hidden_postdata = array();
1406 #-- previous version come back
1407 if ($ewiki_config["forced_version"]) {
1409 $current = ewiki_db::GET($id);
1410 $data["version"] = $current["version"];
1413 unset($_REQUEST["content"]);
1414 unset($_REQUEST["version"]);
1417 #-- edit interception
1418 if ($pf_a = @$ewiki_plugins["edit_hook"]) foreach ($pf_a as $pf) {
1419 if ($output = $pf($id, $data, $hidden_postdata)) {
1424 #-- permission checks //@TODO: move into above hook, split out flag checks
1425 if (isset($ewiki_ring)) {
1426 $ring = $ewiki_ring;
1430 $flags = @$data["flags"];
1431 if (!($flags & EWIKI_DB_F_WRITEABLE)) {
1434 $edit_ring = (EWIKI_PROTECTED_MODE>=2) ? (2) : (NULL);
1435 if (EWIKI_PROTECTED_MODE && !ewiki_auth($id, $data, $action, $edit_ring, "FORCE")) {
1436 return($ewiki_errmsg);
1440 if (($flags & EWIKI_DB_F_READONLY) and ($ring >= 2)) {
1441 return(ewiki_t("CANNOTCHANGEPAGE"));
1443 if (($flags) and (($flags & EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT) and ($ring >= 1)) {
1444 return(ewiki_t("CANNOTCHANGEPAGE"));
1449 $o = ewiki_make_title($id, ewiki_t("EDITTHISPAGE").(" '{$id}'"), 2, $action, "", "_MAY_SPLIT=1");
1451 #-- normalize to UNIX newlines
1452 $_REQUEST["content"] = str_replace("\015\012", "\012", $_REQUEST["content"]);
1453 $_REQUEST["content"] = str_replace("\015", "\012", $_REQUEST["content"]);
1456 if (isset($_REQUEST["preview"])) {
1457 $o .= $ewiki_plugins["edit_preview"][0]($data);
1461 if (isset($_REQUEST["save"])) {
1463 #-- check for concurrent version saving
1465 if ((@$data["version"] >= 1) && (($data["version"] != @$_REQUEST["version"]) || (@$_REQUEST["version"] < 1))) {
1467 $pf = $ewiki_plugins["edit_patch"][0];
1469 if (!$pf || !$pf($id, $data)) {
1471 $o .= ewiki_t("ERRVERSIONSAVE") . "<br /><br />";
1477 #-- new pages` flags
1478 $set_flags = (@$data["flags"] & EWIKI_DB_F_COPYMASK);
1479 if (($set_flags & EWIKI_DB_F_TYPE) == 0) {
1480 $set_flags = EWIKI_DB_F_TEXT;
1482 if (EWIKI_ALLOW_HTML) {
1483 $set_flags |= EWIKI_DB_F_HTML;
1489 "version" => @$data["version"] + 1,
1490 "flags" => $set_flags,
1491 "content" => $_REQUEST["content"],
1492 "created" => ($uu=@$data["created"]) ? $uu : time(),
1493 "meta" => ($uu=@$data["meta"]) ? $uu : "",
1494 "hits" => ($uu=@$data["hits"]) ? $uu : "0",
1496 ewiki_data_update($save);
1498 #-- edit storage hooks
1499 if ($pf_a = @$ewiki_plugins["edit_save"]) {
1500 foreach ($pf_a as $pf) {
1506 if (!$save || !ewiki_db::WRITE($save)) {
1508 $o .= $ewiki_errmsg ? $ewiki_errmsg : ewiki_t("ERRORSAVING");
1512 #-- prevent double saving, when ewiki_page() is re-called
1513 $_REQUEST = $_GET = $_POST = array();
1515 $o = ewiki_t("THANKSFORCONTRIBUTION") . "<br /><br />";
1517 if (EWIKI_EDIT_REDIRECT) {
1518 $url = ewiki_script("", $id, "thankyou=1", 0, 0, ewiki_script_url());
1519 $o .= ewiki_t("EDITCOMPLETE", array("url"=>htmlentities($url)));
1521 if (EWIKI_HTTP_HEADERS && !headers_sent()) {
1522 header("Status: 303 Redirect for GET");
1523 $sid = defined("SID") ? EWIKI_ADDPARAMDELIM.SID : "";
1524 header("Location: $url$sid");
1526 #header("URI: $url");
1527 #header("Refresh: 0; URL=$url");
1530 $o .= '<meta http-equiv="Location" content="'.htmlentities($url).'">';
1534 $o .= ewiki_page($id);
1542 // header("Reload-Location: " . ewiki_script("", $id, "", 0, 0, ewiki_script_url()) );
1547 $o .= ewiki_page_edit_form($id, $data, $hidden_postdata);
1549 #-- additional forms
1550 if ($pf_a = $ewiki_plugins["edit_form_final"]) foreach ($pf_a as $pf) {
1551 $pf($o, $id, $data, $action);
1559 function ewiki_data_update(&$data, $author="") {
1560 ewiki_db::UPDATE($data, $author);
1564 function ewiki_new_data($id, $flags=EWIKI_DB_F_TEXT, $author="") {
1565 return(ewiki_db::CREATE($id, $flags, $author));
1571 function ewiki_page_edit_form(&$id, &$data, &$hidden_postdata) {
1573 global $ewiki_plugins, $ewiki_config;
1575 #-- previously edited, or db fetched content
1576 if (@$_REQUEST["content"] || @$_REQUEST["version"]) {
1578 "version" => &$_REQUEST["version"],
1579 "content" => &$_REQUEST["content"]
1583 if (empty($data["version"])) {
1584 $data["version"] = 1;
1586 @$data["content"] .= "";
1589 #-- normalize to DOS newlines
1590 $data["content"] = str_replace("\015\012", "\012", $data["content"]);
1591 $data["content"] = str_replace("\015", "\012", $data["content"]);
1592 $data["content"] = str_replace("\012", "\015\012", $data["content"]);
1594 $hidden_postdata["version"] = &$data["version"];
1596 #-- edit textarea/form
1597 $o .= ewiki_t("EDIT_FORM_1")
1598 . '<form method="POST" enctype="multipart/form-data" action="'
1599 . ewiki_script("edit", $id) . '" name="ewiki"'
1600 . ' accept-charset="'.EWIKI_CHARSET.'">' . "\n";
1602 #-- additional POST vars
1603 if ($hidden_postdata) foreach ($hidden_postdata as $name => $value) {
1604 $o .= '<input type="hidden" name="' . $name . '" value="' . $value . '" />' ."\n";
1607 if (EWIKI_CHARSET=="UTF-8") {
1608 $data["content"] = utf8_encode($data["content"]);
1610 ($cols = strtok($ewiki_config["edit_box_size"], "x*/,;:")) && ($rows = strtok("x, ")) || ($cols=70) && ($rows=15);
1611 $o .= '<textarea wrap="soft" id="ewiki_content" name="content" rows="'.$rows . '" cols="' .$cols. '">'
1612 . htmlentities($data["content"]) . "</textarea>"
1613 . $GLOBALS["ewiki_t"]["C"]["EDIT_TEXTAREA_RESIZE_JS"];
1615 #-- more <input> elements before the submit button
1616 if ($pf_a = $ewiki_plugins["edit_form_insert"]) foreach ($pf_a as $pf) {
1617 $o .= $pf($id, $data, $action);
1621 . ewiki_form("save:submit", " ".ewiki_t("SAVE")." ")
1623 . ewiki_form("preview:submit", " ".ewiki_t("PREVIEW")." ")
1624 . ' <a class="cancel" href="'. ewiki_script("", $id) . '">' . ewiki_t("CANCEL_EDIT") . '</a><br />';
1626 #-- additional form elements
1627 if ($pf_a = $ewiki_plugins["edit_form_append"]) foreach ($pf_a as $pf) {
1628 $o .= $pf($id, $data, $action);
1632 . ewiki_t("EDIT_FORM_2");
1634 return('<div class="edit-box">'. $o .'</div>');
1640 function ewiki_page_edit_form_final_imgupload(&$o, &$id, &$data, &$action) {
1641 if (EWIKI_SCRIPT_BINARY && EWIKI_UP_UPLOAD && EWIKI_IMAGE_MAXSIZE) {
1642 $o .= "\n<br />\n". '<div class="image-upload">'
1644 . '"'. ewiki_script_binary("", EWIKI_IDF_INTERNAL, "", "_UPLOAD=1") .'"'
1645 . ' method="POST" enctype="multipart/form-data" target="_upload">'
1646 . '<input type="file" name="'.EWIKI_UP_UPLOAD.'"'
1647 . (defined("EWIKI_IMAGE_ACCEPT") ? ' accept="'.EWIKI_IMAGE_ACCEPT.'" />' : "")
1648 . '<input type="hidden" name="'.EWIKI_UP_BINARY.'" value="'.EWIKI_IDF_INTERNAL.'">'
1649 . '<input type="hidden" name="'.EWIKI_UP_PARENTID.'" value="'.htmlentities($id).'">'
1650 . ' '
1651 . '<input type="submit" value="'.ewiki_t("UPLOAD_PICTURE_BUTTON").'">'
1652 . '</form></div>'. "\n";
1657 function ewiki_page_edit_preview(&$data) {
1658 return( '<div class="preview">'
1659 . '<hr noshade="noshade" />'
1660 . "<div align=\"right\">" . ewiki_t("PREVIEW") . "</div><hr noshade=\"noshade\" /><br />\n"
1661 . $GLOBALS["ewiki_plugins"]["render"][0]($_REQUEST["content"], 1, EWIKI_ALLOW_HTML || (@$data["flags"]&EWIKI_DB_F_HTML))
1662 . '<hr noshade="noshade" /><br />'
1673 function ewiki_control_links($id, &$data, $action, $hide_hr=0, $hide_mtime=0) {
1675 global $ewiki_plugins, $ewiki_ring, $ewiki_config;
1676 $action_links = & $ewiki_config["action_links"][$action];
1679 if (!$ewiki_config["control_line"]) {
1684 . '<div align="right" class="action-links control-links"><br />';
1685 if (!$hide_hr && !@$ewiki_config["control_line.no_deco"]) {
1686 $o .= '<p><small>' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . '</small></p>';
1687 $o .= "\n\n" . '<hr noshade="noshade" />' . "\n";
1690 if (@$ewiki_config["forced_version"] && ewiki_auth($id, $data, "edit")) {
1692 $o .= '<form action="' . ewiki_script("edit", $id) . '" method="POST">' .
1693 '<input type="hidden" name="edit" value="old">' .
1694 '<input type="hidden" name="version" value="'.$ewiki_config["forced_version"].'">' .
1695 '<input type="submit" value="' . ewiki_t("OLDVERCOMEBACK") . '"></form> ';
1698 $o .= ewiki_control_links_list($id, $data, $action_links);
1701 if (!$hide_mtime && ($data["lastmodified"] >= UNIX_MILLENNIUM)) {
1702 // $o .= '<small>' . strftime(ewiki_t("LASTCHANGED"), @$data["lastmodified"]) . '</small>';
1710 #-- the core of ewiki_control_links, separated for use in info and plugins
1711 function ewiki_control_links_list($id, &$data, $action_links, $version=0) {
1712 global $ewiki_plugins, $ewiki_config, $o;
1714 ($ins = @$ewiki_config["control_links_enclose"]) or ($ins = " ");
1716 if ($action_links) foreach ($action_links as $action => $title)
1717 if (!empty($ewiki_plugins["action"][$action]) || !empty($ewiki_plugins["action_always"][$action]) || strpos($action, ":/"))
1719 if (EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING && !ewiki_auth($id, $data, $action)) {
1722 $o .= $ins[1] . '<a href="' .
1723 ( strpos($action, "://")
1724 ? $action # an injected "action" URL
1725 : ewiki_script($action, $id, $version?array("version"=>$version):NULL)
1726 ) . '">' . ewiki_t($title) .'</a> ' . $ins[2];
1732 $o = $ins[0] . $o . $ins[3];
1739 # ============================================================= rendering ===
1745 ######## ### ### ######### ### ### ### #######
1746 ######## #### ### ######### ### #### ### #######
1747 ### ##### ### ### ##### ### ###
1748 ###### ######### ### #### ### ######### ######
1749 ###### ######### ### #### ### ######### ######
1750 ### ### ##### ### ### ### ### ##### ###
1751 ######## ### #### ######### ### ### #### #######
1752 ######## ### ### ######### ### ### ### #######
1756 The _format() function transforms $wiki_source pages into <html> strings,
1757 also calls various markup and helper plugins during the transformation
1758 process. The $params array can activate various features and extensions.
1759 only accepts UNIX newlines!
1761 function ewiki_format (
1766 global $ewiki_links, $ewiki_plugins, $ewiki_config;
1769 $params = (array)$ewiki_config["format_params"] + (array)$params;
1771 "in" => 0, # current input $iii[] block array index
1774 "post" => "", # string to append after current line/paragraph
1777 "list" => "", # lists
1778 "tbl" => 0, # open table?
1779 "indent" => 0, # indentation
1784 $line = &$s["line"];
1785 $lines = &$s["lines"];
1786 $para = &$s["para"];
1787 $post = &$s["post"];
1788 $list = &$s["list"];
1790 #-- input and output arrays
1791 if ($wiki_source[0] == "<") { # also prepend an empty line
1792 $wiki_source = "\n" . $wiki_source; # for faster strpos() searchs
1794 $core_flags = 0x137F; # (0x0001=WikiMarkup, 0x0002=WikiLinks, 0x1000=MoreBlockPlugins)
1797 0 => $wiki_source."\n", # body + empty line
1798 1 => $core_flags, # rendering / behaviour options
1799 2 => "core", # block plugin name
1804 unset($wiki_source);
1807 $pf_tbl = @$ewiki_plugins["format_table"][0];
1808 $pf_line = @$ewiki_plugins["format_line"];
1811 $htmlentities = $ewiki_config["htmlentities"];
1812 $wm_indent = &$ewiki_config["wm_indent"];
1813 $s["wm_indent_close"] = "</" . strtok($wm_indent, "< />"). ">";
1814 $wm_table_defaults = &$ewiki_config["wm_table_defaults"];
1815 $wm_source = &$ewiki_config["wm_source"];
1816 $wm_list = &$ewiki_config["wm_list"];
1817 $wm_list_chars = implode("", array_keys($wm_list));
1818 $wm_style = &$ewiki_config["wm_style"];
1819 $wm_start_end = &$ewiki_config["wm_start_end"];
1820 $wm_max_header = &$ewiki_config["wm_max_header"];
1821 $wm_publishing_headers = &$ewiki_config["wm_publishing_headers"];
1822 $wm_whole_line = &$ewiki_config["wm_whole_line"];
1825 $iii[0][0] = strtr($iii[0][0], $htmlentities);
1826 unset($htmlentities["&"]);
1828 #-- pre-processing plugins (working on wiki source)
1829 if ($pf_source = $ewiki_plugins["format_source"]) {
1830 foreach ($pf_source as $pf) $pf($iii[0][0]);
1834 $iii[0][0] = strtr($iii[0][0], $wm_source);
1837 #-- separate input into blocks ------------------------------------------
1838 if ($ewiki_config["format_block"])
1839 foreach ($ewiki_config["format_block"] as $btype=>$binfo) {
1841 #-- disabled block plugin?
1842 if ($binfo[2] && !$params[$binfo[2]]) {
1848 while ((++$in) < count($iii)) {
1850 #-- search fragment delimeters
1851 if ($iii[$in][1] & 0x0100)
1853 ($c = & $iii[$in][0]) &&
1854 (($l = strpos($c, $binfo[0])) !== false) &&
1855 ($r = strpos($c, $binfo[1], $l)) )
1857 $l_len = strlen($binfo[0]);
1858 $r_len = strlen($binfo[1]);
1862 if (($l > 0) && trim($text = substr($c, 0, $l))) {
1863 $repl[] = array($text, $core_flags, "core");
1865 // the extracted part
1866 if (trim($text = substr($c, $l+$l_len, $r-$l-$l_len))) {
1867 $repl[] = array($text, $binfo[3], "$btype");
1870 if (($r+$r_len < strlen($c)) && trim($text = substr($c, $r+$r_len))) {
1871 $repl[] = array($text, $core_flags, "core");
1873 array_splice($iii, $in, 1, $repl);
1880 #-- run format_block plugins
1882 while ((++$in) < count($iii)) {
1883 if (($btype = $iii[$in][2]) && ($pf_a = @$ewiki_plugins["format_block"][$btype])) {
1885 if ($iii[$in][1] & 0x0400) {
1886 $c = strtr($c, array_flip($htmlentities));
1888 foreach ($pf_a as $pf) {
1889 # current buffer $c and pointer $in into $iii[] and state $s
1890 $pf($c, $in, $iii, $s, $btype);
1895 #-- wiki markup ------------------------------------------------------
1898 while ((++$in) < count($iii)) {
1900 if ($iii[$in][1] & 0x0001) {
1902 #-- input $lines buffer, and output buffer $ooo array
1903 $lines = explode("\n", $iii[$in][0]);
1908 $out = &$ooo[$in][0];
1909 $s["bmarkup"] = ($iii[$in][1] & 0x0008); # lists/tables/paras
1910 $s["nopara"] = !($s["bmarkup"]); # disables indentation & paragraphs
1911 # should this disable lists and tables and ...
1912 # shouldn't it rather be a bit flag?
1914 #-- walk through wiki source lines
1915 $line_max = count($lines);
1916 if ($lines) foreach ($lines as $s["line_i"]=>$line) {
1917 #echo "line={$s[line_i]}:$line\n";
1919 #-- empty lines separate paragraphs
1920 if (!ltrim($line)) {
1921 ewiki_format_close_para($ooo, $s);
1922 ewiki_format_close_tags($ooo, $s);
1923 if (!$s["nopara"]) {
1930 #-- list/table/headline "BlockMarkup" ---------------------------
1931 if ($s["bmarkup"]) {
1934 if (!$list && !strncmp($line, "----", 4)) {
1935 $s["para"] .= "<hr noshade=\"noshade\" />\n";
1939 if (!strncmp($line, "<!--", 7)) {
1940 $out .= "<!-- " . htmlentities(str_replace("--", "__", substr($line, 7))) . " -->\n";
1944 strlen($line) && ($c0 = $line[0])
1947 #-- tables ------------------------
1948 if (($c0 == "|") && ($s["tbl"] || ($line[strlen($line)-1] == "|"))) {
1950 ewiki_format_close_para($ooo, $s);
1951 ewiki_format_close_tags($ooo, $s);
1954 $line = substr($line, 1);
1955 if ($line[strlen($line)-1] == "|") {
1956 $line = substr($line, 0, -1);
1959 $pf_tbl($line, $ooo, $s);
1963 $out .= "<table " . $wm_table_defaults . ">\n";
1964 $s["close"][] = "\n</table>";
1966 $line = "<tr>\n<td>" . str_replace("|", "</td>\n<td>", $line) . "</td>\n</tr>";
1971 elseif ($s["tbl"]) {
1977 if (($c0 == "!") && ($excl = strspn($line, "!"))) {
1979 if ($excl > $wm_max_header) {
1980 $excl = $wm_max_header;
1982 $line = substr($line, $excl);
1983 //publishing headers go from h2 smaller "like word"
1984 $excl = $wm_publishing_headers? (1+$excl) :5 - $excl;
1985 $line = "<h$excl>" . $line . "</h$excl>";
1987 ewiki_format_close_para($ooo, $s);
1989 ewiki_format_close_tags($ooo, $s);
1994 #-- whole-line wikimarkup
1995 foreach ($wm_whole_line as $find=>$replace) {
1996 if (substr($line, 0, strlen($find)) == $find) {
1997 $line = "<$replace>" . ltrim(substr($line,strlen($find))) . "</".strtok($replace," ").">";
2001 #-- indentation (space/tab markup)
2003 if (!$list && (!$s["nopara"]) && ($n_indent = strspn($line, " "))) {
2004 $n_indent = (int) ($n_indent / 2.65);
2005 while ($n_indent > $s["indent"]) {
2006 $s["para"] .= $wm_indent;
2010 while ($n_indent < $s["indent"]) {
2011 $s["para"] .= $s["wm_indent_close"] . "\n";
2016 #-- list markup -------------------
2017 if (isset($wm_list[$c0])) {
2019 ewiki_format_close_para($ooo, $s);
2020 ewiki_format_close_tags($ooo, $s);
2022 $new_len = strspn($line, $wm_list_chars);
2023 $new_list = substr($line, 0, $new_len);
2024 $old_len = strlen($list);
2025 $lchar = $new_list[$new_len-1];
2026 list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
2028 #-- exception: "--" is treated as literal
2029 if (($old_len===0) && (($new_len>=2) && ($new_list=="--"))) {
2030 $list = ''; # change this ^^ to an OR (||)
2031 # to filter bad list markup
2035 $line = substr($line, $new_len);
2039 $linsert = "<$ltag1>" . strtok($line, $lchar) . "</$ltag1> ";
2040 $line = strtok("\000");
2044 if (($lchar == "#") && ($line[1] == " ") && ($ltype = $line[0])) {
2045 if (($ltype >= "0") || ($ltype <= "z")) {
2046 $line = substr($line, 2);
2052 #-- add another <li>st entry
2053 if ($new_len == $old_len) {
2054 $lspace = str_repeat(" ", $new_len);
2055 $out .= "</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
2058 elseif ($new_len > $old_len) {
2059 while ($new_len > ($old_len=strlen($list))) {
2060 $lchar = $new_list[$old_len];
2062 list($lopen, $ltag1, $ltag2) = $wm_list[$lchar];
2063 $lclose = strtok($lopen, " ");
2064 $lspace = str_repeat(" ", $new_len);
2066 if (isset($ltype) && $ltype) {
2067 $ltype = ($ltype<"A"?"1": ($ltype=="I"?"I": ($ltype=="i"?"i": ($ltype<"a"?"A": "a"))));
2068 $lopen .= " type=\"$rltype\"";
2069 if ($rltype!=$ltype) { $lopen .= " start=\"$ltype\""; }
2072 $out .= "\n$lspace<$lopen>\n" . "$lspace". $linsert . "<$ltag2>";
2073 $s["close"][] = "$lspace</$lclose>";
2074 $s["close"][] = "$lspace</$ltag2>";
2079 while ($new_len < ($old_len=strlen($list))) {
2080 $remove = $old_len-$new_len;
2081 ewiki_format_close_tags($ooo, $s, 2*$remove);
2082 $list = substr($list, 0, -$remove);
2085 $lspace = str_repeat(" ", $new_len);
2086 $out .= "$lspace</$ltag2>\n" . $lspace . $linsert . "<$ltag2>";
2099 ewiki_format_close_tags($ooo, $s);
2104 }#--if $s["bmarkup"] --------------------------------------------
2107 #-- text style triggers
2108 foreach ($wm_style as $find=>$replace) {
2109 $find_len = strlen($find);
2111 while(($loop--) && (($l = strpos($line, $find)) !== false) && ($r = strpos($line, $find, $l + $find_len))) {
2112 $line = substr($line, 0, $l) . $replace[0] .
2113 substr($line, $l + strlen($find), $r - $l - $find_len) .
2114 $replace[1] . substr($line, $r + $find_len);
2118 #-- start-end markup
2119 foreach ($wm_start_end as $d) {
2120 $len0 = strlen($d[0]);
2122 while(($loop--) && (($l = strpos($line, $d[0])) !== false) && ($r = strpos($line, $d[1], $l + $len0))) {
2123 $len1 = strlen($d[1]);
2124 $line = substr($line, 0, $l) . $d[2] .
2125 substr($line, $l + $len0, $r - $l - $len0) .
2126 $d[1] . substr($line, $r + $len1);
2130 #-- call wiki source formatting plugins that work on current line
2132 foreach ($pf_line as $pf) $pf($out, $line, $post);
2136 #-- add formatted line to page-output
2138 if ($para === false) {
2143 $para .= $line . "\n";
2148 #-- last block, or flags dictate a WikiSource blocks/para break?
2149 if (!isset($iii[$in+1]) || (($iii[$in+1][1] & 0x0010) ^ ($iii[$in][1] & 0x0010)) ) {
2150 ewiki_format_close_para($ooo, $s);
2151 ewiki_format_close_tags($ooo, $s);
2154 #-- copy as is into output buffer
2156 $ooo[$in] = $iii[$in];
2158 $iii[$in] = array();
2162 #-- wiki linking ------------------------------------------------------
2164 for ($in=0; $in<count($ooo); $in++) {
2165 // BUG: does not respect the (absence of) flags of individual blocks
2166 #-- join together multiple WikiSource blocks
2167 if ($ooo[$in][1] & 0x0022) {
2168 while (isset($ooo[$in+1]) && ($ooo[$in][1] & 0x0002) && ($ooo[$in+1][1] & 0x0002)) {
2170 0 => $ooo[$in][0] . "\n" . $ooo[$in+1][0],
2171 1 => $ooo[$in][1] | $ooo[$in+1][1],
2173 array_splice($ooo, $in+1, 1);
2176 #-- html character entities
2177 if (EWIKI_HTML_CHARS || ($ooo[$in][1] & 0x0004)) {
2178 $ooo[$in][0] = str_replace("&#", "&#", $ooo[$in][0]);
2180 $scan_src .= $ooo[$in][0];
2184 if ($params["scan_links"]) {
2185 ewiki_scan_wikiwords($scan_src, $ewiki_links);
2187 if ($pf_linkprep = @$ewiki_plugins["format_prepare_linking"]) {
2188 foreach ($pf_linkprep as $pf) $pf($scan_src);
2192 #-- finally the link-creation-regex
2193 for ($in=0; $in<count($ooo); $in++) {
2194 if ($ooo[$in][1] & 0x0002) {
2195 ewiki_render_wiki_links($ooo[$in][0]);
2200 #-- fin: combine all blocks into html string ----------------------------
2202 for ($in=0; $in<count($ooo); $in++) {
2203 $html .= $ooo[$in][0] . "\n";
2206 #-- call post processing plugins
2207 if ($pf_final = $ewiki_plugins["format_final"]) {
2208 foreach ($pf_final as $pf) $pf($html);
2215 function ewiki_format_close_para(&$ooo, &$s) {
2216 $out = &$ooo[$s["in"]][0];
2217 #-- output text block
2218 if (trim($s["para"])) {
2220 while ($s["indent"]) {
2221 $s["para"] .= $s["wm_indent_close"];
2224 #-- enclose in <p> tags
2225 if (!$s["nopara"]) {
2226 $s["para"] = "\n<p>" . ltrim($s["para"], "\n") . "</p>\n";
2228 #-- paragraph formation plugins
2229 if ($pf_a = @$GLOBALS["ewiki_plugins"]["format_para"]) {
2230 foreach ($pf_a as $pf) {
2231 $pf($s["para"], $ooo, $s);
2240 function ewiki_format_close_tags(&$ooo, &$s, $count=100) {
2241 $out = &$ooo[$s["in"]][0];
2242 if (!is_array($s) || !is_array($s["close"])) {
2243 die("\$s is garbaged == $s!!");
2245 while (($count--) && ($add = array_pop($s["close"]))) {
2246 $out .= $add . "\n";
2251 function ewiki_format_pre(&$str, &$in, &$iii, &$s, $btype) {
2252 $str = "<pre class=\"markup $btype\">" . $str . "</pre>";
2256 function ewiki_format_html(&$str, &$in, &$iii, &$s) {
2257 $he = array_reverse($GLOBALS["ewiki_config"]["htmlentities"]);
2258 $str = strtr($str, array_flip($he));
2259 $str = "<span class=\"markup html\">" . $str . "\n</span>\n";
2263 function ewiki_format_comment(&$str, &$in, &$iii, &$s, $btype) {
2264 $str = "<!-- " . str_replace("--", "¯¯", $str) . " -->";
2270 /* unclean pre-scanning for WikiWords in a page,
2271 pre-query to the db */
2272 function ewiki_scan_wikiwords(&$wiki_source, &$ewiki_links, $se=0) {
2274 global $ewiki_config, $ewiki_id;
2277 preg_match_all($ewiki_config["wiki_pre_scan_regex"], $wiki_source, $uu);
2278 $uu = array_merge((array)$uu[1], (array)$uu[2], (array)@$uu[3], (array)$uu[4]);
2280 #-- clean up list, trim() spaces (allows more unclean regex) - page id unification
2281 foreach ($uu as $i=>$id) {
2282 $uu[$i] = trim($id);
2285 $uu = array_unique($uu);
2287 #-- unfold SubPage names
2288 if (EWIKI_SUBPAGE_START) {
2289 foreach ($uu as $i=>$id) {
2290 if ($id && (strpos(EWIKI_SUBPAGE_START, $id[0]) !== false)) {
2291 if ($id[1] == "/") { $id = substr($id, 1); }
2292 $uu[$i] = $ewiki_id . $id;
2297 $ewiki_links = ewiki_db::FIND($uu);
2299 #-- strip email adresses
2301 foreach ($ewiki_links as $c=>$uu) {
2302 if (strpos($c, "@") && (strpos($c, ".") || strpos($c, ":"))) {
2303 unset($ewiki_links[$c]);
2310 /* regex on page content,
2311 handled by callback (see below)
2313 function ewiki_render_wiki_links(&$o) {
2314 global $ewiki_links, $ewiki_config, $ewiki_plugins;
2316 #-- merge with dynamic pages list
2317 ewiki_merge_links($ewiki_links);
2319 #-- replace WikiWords
2320 $link_regex = &$ewiki_config["wiki_link_regex"];
2321 $o = preg_replace_callback($link_regex, "ewiki_link_regex_callback", $o);
2324 /////////// unset($ewiki_links);
2328 /* combines with page plugin list,
2329 and makes all case-insensitive (=lowercased)
2330 in accord with EWIKI_CASE_INSENSITIVE
2331 (handled within ewiki_array)
2333 function ewiki_merge_links(&$ewiki_links) {
2334 global $ewiki_plugins;
2335 if ($ewiki_links !== true) {
2336 foreach ($ewiki_plugins["page"] as $page=>$uu) {
2337 $ewiki_links[$page] = 1;
2339 $ewiki_links = ewiki_array($ewiki_links);
2345 /* link rendering (p)regex callback
2346 (ooutch, this is a complicated one)
2348 function ewiki_link_regex_callback($ii, $force_noimg=0) {
2350 global $ewiki_links, $ewiki_plugins, $ewiki_config, $ewiki_id;
2352 $str = trim($ii[0]);
2356 #-- link bracket '[' escaped with '!' or '~'
2357 if (($str[0] == "!") || ($str[0] == "~") || ($str[0] == "\\")) {
2358 return(substr($str, 1));
2360 if ($str[0] == "#") {
2361 $states["define"] = 1;
2362 $str = substr($str, 1);
2364 if ($str[0] == "[") {
2365 $states["brackets"] = 1;
2366 $str = substr($str, 1, -1);
2367 if (!strlen($str)) { return("[]"); } //better: $ii[0]
2370 #-- explicit title given via [ title | WikiLink ]
2371 $href = $title = strtok($str, "|");
2372 if ($uu = strtok("|")) {
2374 $states["titled"] = 1;
2376 #-- title and href swapped: swap back
2377 if (strpos("://", $title) || strpos($title, ":") && !strpos($href, ":")) {
2378 $uu = $title; $title = $href; $href = $uu;
2380 #-- new entitling scheme [ url "title" ]
2381 if ((($l=strpos($str, '"')) < ($r=strrpos($str, '"'))) && ($l!==false) ) {
2382 $title = substr($str, $l + 1, $r - $l - 1);
2383 $href = substr($str, 0, $l) . substr($str, $r + 1);
2384 $states["titled"] = 1;
2385 if (!$href) { return($ii[0]); }
2389 $spaces_l = ($href[0]==" ") ?1:0;
2390 $spaces_r = ($href[strlen($href)-1]==" ") ?1:0;
2391 $title = ltrim(trim($title), "^");
2392 $href = ltrim(trim($href), "^");
2394 #-- strip_htmlentities()
2395 if (1&& (strpos($href, "&")!==false) && strpos($href, ";")) {
2396 ewiki_stripentities($href);
2401 if (($p = strrpos($href, "#")) && ($p) && ($href[$p-1] != "&")) {
2402 $href2 = trim(substr($href, $p));
2403 $href = trim(substr($href, 0, $p));
2406 $states["define"] = 1;
2416 if ($c0 && (strpos(EWIKI_SUBPAGE_START, $c0) !== false)) {
2417 $_set = EWIKI_SUBPAGE_LONGTITLE && ($href==$title);
2418 if (($href[1] == "/")) { ##($c0 == ".") &&
2419 $href = substr($href, 1);
2421 $href = $ewiki_id . $href;
2427 #-- for case-insensitivines
2428 $href_i = EWIKI_CASE_INSENSITIVE ? strtolower($href) : ($href);
2431 if (isset($ewiki_links[$href_i]) && strpos($inj_url = $ewiki_links[$href_i], "://")) {
2432 if ($href==$title) { $href = $inj_url; }
2434 $states["title"] = &$title;
2437 if (strpos($href, ":") && ($uu = ewiki_interwiki($href, $type, $states))) {
2439 $str = "<a href=\"$href$href2\">$title</a>";
2441 #-- action:WikiLinks
2442 elseif (isset($ewiki_plugins["action"][$a=strtolower(strtok($href, ":"))])) {
2443 $type = array($a, "action", "wikipage");
2444 $str = '<a href="' . ewiki_script($a, strtok("\000")) . '">' . $title . '</a>';
2446 #-- page anchor definitions, if ($href[0]=="#")
2447 elseif (@$states["define"]) {
2448 $type = array("anchor");
2449 if ($title==$href) {
2450 $title = ""; // was " " before, but that's not required
2452 $str = '<a name="' . htmlentities(ltrim($href, "#")) . '">' . ltrim($title, "#") . '</a>';
2454 #-- inner page anchor jumps
2455 elseif (strlen($href2) && ($href==$ewiki_id) || ($href[0]=="#") && ($href2=&$href)) {
2456 $type = array("jump");
2457 $str = '<a href="' . htmlentities($href2) . '">' . $title . '</a>';
2459 #-- ordinary internal WikiLinks
2460 elseif (($ewiki_links === true) || @$ewiki_links[$href_i]) {
2461 $type = array("wikipage");
2462 $str = '<a href="' . ewiki_script("", $href) . htmlentities($href2)
2463 . '">' . $title . '</a>';
2465 #-- guess for mail@addresses, convert to URI if
2466 elseif (strpos($href, "@") && !strpos($href, ":")) {
2467 $type = array("email");
2468 $href = "mailto:" . $href;
2470 #-- not found fallback
2473 #-- a plugin may take care
2474 if ($pf_a = @$ewiki_plugins["link_notfound"]) {
2475 foreach ($pf_a as $pf) {
2476 if ($str = $pf($title, $href, $href2, $type)) {
2480 #-- (QuestionMarkLink to edit/ action)
2482 $type = array("notfound");
2483 $t = $ewiki_config["qmark_links"];
2484 $str = ewiki_script(isset($t[4]) ? "edit" : "", $href);
2485 if (strlen($t) >= 3) {
2486 $str = ($t[0] ? "<a href=\"$str\">$t[0]</a>" :'')
2487 . ($t[1] ? "<$t[1]>$title</$t[1]>" : $title)
2488 . ($t[2] ? "<a href=\"$str\">$t[2]</a>" :'');
2490 $str = "<a href=\"$str\">" . $title . "</a>";
2491 if ($t<0) { $str .= "?"; }
2493 $str = '<span class="NotFound">' . $str . '</span>';
2497 #-- convert standard and internal:// URLs
2498 $is_url = preg_match('°^('.implode('|', $ewiki_config["idf"]["url"]).')°', $href);
2501 if (!$is_url && ($ewiki_links[$href_i]["flags"] & EWIKI_DB_F_BINARY)) {
2507 $type[-1] = strtok($href, ":");
2509 #-- [http://url titles]
2510 if (strpos($href, " ") && ($title == $href)) {
2511 $href = strtok($href, " ");
2512 $title = strtok("\377");
2516 if ($pf_a = $ewiki_plugins["link_url"]) foreach ($pf_a as $pf) {
2517 if ($str = $pf($href, $title, $status)) { break 2; }
2519 $meta = @$ewiki_links[$href];
2521 #-- check for image files
2522 $ext = substr($href, strrpos($href,"."));
2523 $nocache = strpos($ext, "no");
2524 $ext = strtok($ext, "?&#");
2525 $obj = in_array($ext, $ewiki_config["idf"]["obj"]);
2526 $img = (strncmp(strtolower($href), "data:image/", 11) == 0) && ($nocache=1)
2527 || $obj || in_array($ext, $ewiki_config["idf"]["img"]);
2529 #-- internal:// references (binary files)
2531 if (EWIKI_SCRIPT_BINARY && ((strpos($href, EWIKI_IDF_INTERNAL)===0) ||
2532 EWIKI_IMAGE_MAXSIZE && EWIKI_CACHE_IMAGES && $img && !$nocache) ||
2535 $type = array("binary");
2536 $href = ewiki_script_binary("", $href);
2539 #-- output html reference
2540 if (!$img || $force_noimg || !$states["brackets"] || (strpos($href, EWIKI_IDF_INTERNAL) === 0)) {
2541 //@FIX: #add1 || $href2 (breaks #.jpeg hack, but had a purpose?)
2542 $str = '<a href="' . $href /*#($href2)*/ . '">' . $title . '</a>';
2546 $type = array("image");
2547 if (is_string($meta)) {
2548 $meta = unserialize($meta);
2550 $str = ewiki_link_img($href, $id, $title, $meta, $spaces_l+2*$spaces_r, $obj, $states);
2554 #-- icon/transform plugins
2556 if ($pf_a = @$ewiki_plugins["link_final"]) {
2557 foreach ($pf_a as $pf) { $pf($str, $type, $href, $title, $states); }
2559 if (isset($states["xhtml"]) && $states["xhtml"]) {
2560 foreach ($states["xhtml"] as $attr=>$val) {
2561 $str = str_replace("<a ", "<a $attr=\"$val\" ", $str);
2570 assembles an <img> tag
2572 function ewiki_link_img($href, $id, $title, $meta, $spaces, $obj, $states) {
2574 #-- size of cached image
2575 $x = $meta["width"];
2576 $y = $meta["height"];
2578 #-- width/height given in url
2579 if ($p = strpos($id, '?')) {
2580 $id = str_replace("&", "&", substr($id, $p+1));
2581 parse_str($id, $meta);
2582 if ($uu = $meta["x"].$meta["width"]) {
2585 if ($uu = $meta["y"].$meta["height"]) {
2588 if ($scale = $meta["r"] . $meta["scale"]) {
2589 if ($p = strpos($scale, "%")) {
2590 $scale = strpos($scale, 0, $p) / 100;
2598 $align = array('', ' align="right"', ' align="left"', ' align="center"');
2599 $align = $align[$spaces];
2600 $size = ($x && $y ? " width=\"$x\" height=\"$y\"" : "");
2602 #-- remove annoyances
2603 if ($href==$title) {
2609 ($obj ? '<embed' : '<img')
2610 . ' src="' . $href . '"'
2611 . ' alt="' . htmlentities($title) . '"'
2612 . (@$states["titled"] ? ' title="' . htmlentities($title) . '"' : '')
2614 . ($obj ? "></embed>" : " />");
2615 # htmlentities($title)
2619 function ewiki_stripentities(&$str) {
2620 static $un = array("<"=>"<", ">"=>">", "&"=>"&");
2621 $str = strtr($str, $un);
2626 Returns URL if it encounters an InterWiki:Link or workalike.
2628 function ewiki_interwiki(&$href, &$type, &$s) {
2629 global $ewiki_config, $ewiki_plugins;
2631 $l = strpos($href, ":");
2632 if ($l and (strpos($href,"//") != $l+1) and ($p1 = strtok($href, ":"))) {
2633 $page = strtok("\000");
2635 if (($p2 = ewiki_array($ewiki_config["interwiki"], $p1)) !== NULL) {
2637 $type = array("interwiki", $uu);
2638 while ($p1_alias = $ewiki_config["interwiki"][$p1]) {
2642 if (!strpos($p1, "%s")) {
2645 $href = str_replace("%s", $page, $p1);
2648 elseif ($pf = $ewiki_plugins["intermap"][$p1]) {
2649 return($pf($p1, $page));
2651 elseif ($pf_a = $ewiki_plugins["interxhtml"]) {
2652 foreach($pf_a as $pf) {
2653 $pf($p1, $page, $s);
2662 implements FeatureWiki:InterMapWalking
2664 function ewiki_intermap_walking($id, &$data, $action) {
2665 if (empty($data["version"]) && ($href = ewiki_interwiki($id, $uu, $uu))) {
2666 header("Location: $href$sid");
2667 return("<a href=\"$href\">$href</a>");
2673 function ewiki_link($pagename, $title="") {
2674 if (!($url = ewiki_interwiki($pagename, $uu, $uu))) {
2675 $url = ewiki_script("", $pagename);
2677 if (!$title) { $title = $pagename; }
2678 return("<a href=\"$url\">".htmlentities($title)."</a>");
2683 # =========================================================================
2687 ##### ## ## ## ## ##### ## ##
2688 ###### ## ### ## #### ###### ## ##
2689 ## ## ## ### ## ###### ## ## ## ##
2690 ##### ## #### ## ## ## ###### ######
2691 ##### ## ####### ###### #### ####
2692 ## ### ## ## #### ###### ##### ##
2693 ## ### ## ## ### ## ## ## ### ##
2694 ###### ## ## ### ## ## ## ## ##
2695 ###### ## ## ## ## ## ## ## ##
2702 function ewiki_binary($break=0) {
2704 global $ewiki_plugins;
2707 if (!strlen($id = @$_REQUEST[EWIKI_UP_BINARY]) || !EWIKI_IDF_INTERNAL) {
2710 if (headers_sent()) die("ewiki-binary configuration error");
2713 $upload_file = @$_FILES[EWIKI_UP_UPLOAD];
2714 $add_meta = array();
2715 if ($orig_name = @$upload_file["name"]) {
2716 $add_meta["Content-Location"] = urlencode($orig_name);
2717 $add_meta["Content-Disposition"] = 'inline; filename="'.urlencode(basename("remote://$orig_name")).'"';
2720 #-- what are we doing here?
2721 if (($id == EWIKI_IDF_INTERNAL) && ($upload_file)) {
2725 $data = ewiki_db::GET($id);
2726 $flags = @$data["flags"];
2727 if (EWIKI_DB_F_BINARY == ($flags & EWIKI_DB_F_TYPE)) {
2730 elseif (empty($data["version"]) and EWIKI_CACHE_IMAGES) {
2738 #-- auth only happens when enforced with _PROTECTED_MODE_XXL setting
2739 # (authentication for inline images in violation of the WWW spirit)
2740 if ((EWIKI_PROTECTED_MODE>=5) && !ewiki_auth($id, $data, "binary-{$do}")) {
2741 return($_REQUEST["id"]="view/BinaryPermissionError");
2745 if ($do == "upload"){
2747 $id = ewiki_binary_save_image($upload_file["tmp_name"], "", $return=0, $add_meta);
2748 @unlink($upload_file["tmp_name"]);
2749 ($title = trim($orig_name, "/")) && ($title = preg_replace("/[^-._\w\d]+/", "_", substr(substr($orig_name, strrpos($title, "/")), 0, 20)))
2750 && ($title = ' \\"'.$title.'\\"') || ($title="");
2754 <html><head><title>File/Picture Upload</title><script language="JavaScript" type="text/javascript"><!--
2755 opener.document.forms["ewiki"].elements["content"].value += "\\nUPLOADED PICTURE: [$id$title]\\n";
2756 window.setTimeout("self.close()", 5000);
2757 //--></script></head><body bgcolor="#440707" text="#FFFFFF">Your uploaded file was saved as<br /><big><b>
2759 </b></big>.<br /><br /><noscript>Please copy this ↑ 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>
2764 #-- request for contents from the db
2765 elseif ($do == "get") {
2767 #-- send http_headers from meta
2768 if (is_array($data["meta"])) {
2769 foreach ($data["meta"] as $hdr=>$val) {
2770 if (($hdr[0] >= "A") && ($hdr[0] <= "Z")) {
2771 header("$hdr: $val");
2776 #-- fetch from binary store
2777 if ($pf_a = $ewiki_plugins["binary_get"]) {
2778 foreach ($pf_a as $pf) { $pf($id, $data["meta"]); }
2782 echo $data["content"];
2785 #-- fetch & cache requested URL,
2786 elseif ($do == "cache") {
2788 #-- check for standard protocol names, to prevent us from serving
2789 # evil requests for '/etc/passwd.jpeg' or '../.htaccess.gif'
2790 if (preg_match('@^\w?(http|ftp|https|ftps|sftp)\w?://@', $id)) {
2792 #-- generate local copy
2793 $filename = tempnam(EWIKI_TMP, "ewiki.local.temp.");
2794 if(!copy($id, $filename)){
2795 ewiki_log("ewiki_binary: error copying $id to $filename", 0);
2798 "Content-Location" => urlencode($id),
2799 "Content-Disposition" => 'inline; filename="'.urlencode(basename($id)).'"',
2800 'PageType' => 'CachedImage'
2803 $result = ewiki_binary_save_image($filename, $id, "RETURN", $add_meta);
2808 if ($result && !$break) {
2809 ewiki_binary($break=1);
2811 #-- mark URL as unavailable
2816 "flags" => EWIKI_DB_F_DISABLED,
2817 "lastmodified" => time(),
2818 "created" => time(),
2819 "author" => ewiki_author("ewiki_binary_cache"),
2821 "meta" => array("Status"=>"404 Absent"),
2823 ewiki_db::WRITE($data);
2824 header("Location: $id");
2825 ewiki_log("imgcache: did not find '$id', and marked it now in database as DISABLED", 2);
2830 #-- "we don't sell this!"
2832 if (strpos($id, EWIKI_IDF_INTERNAL) === false) {
2833 header("Status: 301 Located SomeWhere Else");
2834 header("Location: $id");
2837 header("Status: 404 Absent");
2838 header("X-Broken-URI: $id");
2842 // you should not remove this one, it is really a good idea to use it!
2851 function ewiki_binary_save_image($filename, $id="", $return=0,
2852 $add_meta=array(), $accept_all=EWIKI_ACCEPT_BINARY, $care_for_images=1)
2854 global $ewiki_plugins;
2856 #-- break on empty files
2857 if (!filesize($filename)) {
2861 #-- check for image type and size
2862 $mime_types = array(
2863 "application/octet-stream",
2867 "application/x-shockwave-flash"
2870 "bin", "gif", "jpeg", "png", "swf"
2872 list($width, $height, $mime_i, $uu) = getimagesize($filename);
2873 (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
2876 if ($care_for_images) {
2879 if (!$mime_i && !$accept_all || !filesize($filename)) {
2880 ewiki_die(ewiki_t("BIN_NOIMG"), $return);
2885 if ((strpos($mime,"image/")!==false)
2886 && (EWIKI_IMAGE_RESIZE)) { // filesize() check now in individual resize plugins
2887 if ($pf_a = $ewiki_plugins["image_resize"]) foreach ($pf_a as $pf) {
2888 $pf($filename, $mime, $return);
2893 #-- reject image if too large
2894 if(filesize($filename) > EWIKI_IMAGE_MAXSIZE) {
2895 ewiki_die(ewiki_t("BIN_IMGTOOLARGE"), $return);
2899 #-- again check mime type and image sizes
2900 list($width, $height, $mime_i, $uu) = getimagesize($filename);
2901 (!$mime_i) && ($mime_i=0) || ($mime = $mime_types[$mime_i]);
2904 ($ext = $ext_types[$mime_i]) or ($ext = $ext_types[0]);
2907 if ((!$mime_i) && ($pf = $ewiki_plugins["mime_magic"][0])) {
2908 if ($tmp = $pf($content)) {
2912 if (!strlen($mime)) {
2913 $mime = $mime_types[0];
2916 #-- store size of binary file
2917 $add_meta["size"] = filesize($filename);
2920 #-- handler for (large/) binary content?
2921 if ($pf_a = $ewiki_plugins["binary_store"]) {
2922 foreach ($pf_a as $pf) {
2923 $pf($filename, $id, $add_meta, $ext);
2927 #-- read file into memory (2MB), to store it into the database
2929 $f = fopen($filename, "rb");
2930 $content = fread($f, 1<<21);
2934 #-- generate db file name
2936 $md5sum = md5($content);
2937 $id = EWIKI_IDF_INTERNAL . $md5sum . ".$ext";
2938 ewiki_log("generated md5sum '$md5sum' from file content");
2941 #-- prepare meta data
2943 "class" => $mime_i ? "image" : "file",
2944 "Content-Type" => $mime,
2945 "Pragma" => "cache",
2946 ) + (array)$add_meta;
2948 $meta["width"] = $width;
2949 $meta["height"] = $height;
2956 "author" => ewiki_author(),
2957 "flags" => EWIKI_DB_F_BINARY | EWIKI_DB_F_READONLY,
2958 "created" => time(),
2959 "lastmodified" => time(),
2961 "content" => &$content,
2964 #-- write if not exist
2965 $exists = ewiki_db::FIND(array($id));
2966 if (! $exists[$id] ) {
2967 $result = ewiki_db::WRITE($data);
2968 ewiki_log("saving of '$id': " . ($result ? "ok" : "error"));
2971 ewiki_log("binary_save_image: '$id' was already in the database", 2);
2980 # =========================================================================
2983 #### #### #### ######## ########
2984 ##### ##### #### ########## ##########
2985 ###### ###### #### #### ### #### ###
2986 ############# #### ####
2987 ############# #### ######## ####
2988 #### ### #### #### ######## ####
2989 #### # #### #### #### ####
2990 #### #### #### ### #### #### ###
2991 #### #### #### ######### ##########
2992 #### #### #### ####### ########
2996 /* yes! it is not necessary to annoy people with country flags, if
2997 HTTP already provides means to determine the prefered language!
2999 function ewiki_localization() {
3003 $deflangs = ','.@$_ENV["LANGUAGE"] . ','.@$_ENV["LANG"]
3004 . ",".EWIKI_DEFAULT_LANG . ",en,C";
3006 foreach (explode(",", @$_SERVER["HTTP_ACCEPT_LANGUAGE"].$deflangs) as $l) {
3008 $l = strtok($l, ";");
3009 $l = strtok($l, "-"); $l = strtok($l, "_"); $l = strtok($l, ".");
3011 if ($l = trim($l)) {
3012 $ewiki_t["languages"][] = strtolower($l);
3016 $ewiki_t["languages"] = array_unique($ewiki_t["languages"]);
3022 /* poor mans gettext, $repl is an array of string replacements to get
3023 applied to the fetched text chunk,
3024 "$const" is either an entry from $ewiki_t[] or a larger text block
3025 containing _{text} replacement braces of the form "_{...}"
3027 function ewiki_t($const, $repl=array(), $pref_langs=array()) {
3031 #-- use default language wishes
3032 if (empty($pref_langs)) {
3033 $pref_langs = $ewiki_t["languages"];
3036 #-- large text snippet replacing
3037 if (strpos($const, "_{") !== false) {
3038 while ( (($l=strpos($const,"_{")) || ($l===0)) && ($r=strpos($const,"}",$l)) ) {
3039 $const = substr($const, 0, $l)
3040 . ewiki_t(substr($const, $l+2, $r-$l-2))
3041 . substr($const,$r+1);
3046 else foreach ($pref_langs as $l) {
3048 if (is_string($r = @$ewiki_t[$l][$const]) || ($r = @$ewiki_t[$l][strtoupper($const)])) {
3050 foreach ($repl as $key=>$value) {
3051 if ($key[0] != '$') {
3054 $r = str_replace($key, $value, $r);
3067 /* takes all ISO-8859-1 characters into account
3068 but won't work with all databases
3070 function ewiki_lowercase($s) {
3072 for ($i=0; $i<$len; $i++) {
3073 if (ord($s[$i]) >= 192) {
3074 $s[$i] = chr(ord($s[$i]) | 0x20);
3077 return(strtolower($s));
3083 function ewiki_log($msg, $error_type=3) {
3085 if ((EWIKI_LOGLEVEL >= 0) && ($error_type <= EWIKI_LOGLEVEL)) {
3087 $msg = time() . " - " .
3088 $_SERVER["REMOTE_ADDR"] . ":" . $_SERVER["REMOTE_PORT"] . " - " .
3089 $_SERVER["REQUEST_METHOD"] . " " . $_SERVER["REQUEST_URI"] . " - " .
3090 strtr($msg, "\n\r\000\377\t\f", "\r\r\r\r\t\f") . "\n";
3091 error_log($msg, 3, EWIKI_LOGFILE);
3098 function ewiki_die($msg, $return=0) {
3101 return($GLOBALS["ewiki_error"] = $msg);
3110 function ewiki_array_hash(&$a) {
3111 return(count($a) . ":" . implode(":", array_keys(array_slice($a, 0, 3))));
3116 /* provides an case-insensitive in_array replacement to search a page name
3117 in a list of others;
3118 the supplied $array WILL be lowercased afterwards, unless $dn was set
3120 function ewiki_in_array($value, &$array, $dn=0, $ci=EWIKI_CASE_INSENSITIVE) {
3122 static $as = array();
3124 #-- work around pass-by-reference
3125 if ($dn && $ci) { $dest = array(); }
3126 else { $dest = &$array; }
3128 #-- make everything lowercase
3130 $value = strtolower($value);
3131 if (empty($as[ewiki_array_hash($array)])) { // prevent working on the
3132 foreach ($array as $i=>$v) { // same array multiple times
3133 $dest[$i] = strtolower($v);
3135 $as[ewiki_array_hash($dest)] = 1;
3139 #-- search in values
3140 return(in_array($value, $dest));
3145 /* case-insensitively retrieves an entry from an $array,
3146 or returns the given $array lowercased if $key was obmitted
3148 function ewiki_array($array, $key=false, $am=1, $ci=EWIKI_CASE_INSENSITIVE) {
3150 #-- make everything lowercase
3152 $key = strtolower($key);
3155 foreach ($array as $i=>$v) {
3156 $i = strtolower($i);
3157 if (!$am || empty($r[$i])) {
3161 $r[$i] .= $v; //RET: doubling for images`meta won't happen
3162 } // but should be "+" here for integers
3167 #-- search in values
3169 return(@$array[$key]);
3181 generates {author} string field for page database entry updates
3183 function ewiki_author($defstr="") {
3185 $author = @$GLOBALS["ewiki_author"];
3186 ($ip = &$_SERVER["REMOTE_ADDR"]) or ($ip = "127.0.0.0");
3187 ($port = $_SERVER["REMOTE_PORT"]) or ($port = "null");
3189 #-- this call may be very slow (~20 sec)
3190 if (EWIKI_RESOLVE_DNS) {
3191 $hostname = gethostbyaddr($ip);
3193 $remote = (($ip != $hostname) ? $hostname . " " : "")
3194 . $ip . ":" . $port;
3196 (empty($author)) && (
3197 ($author = $defstr) ||
3198 ($author = $_SERVER["HTTP_FROM"]) || // RFC2068 sect 14.22
3199 ($author = $_SERVER["PHP_AUTH_USER"])
3203 && ($author = $remote)
3204 || ($author = addslashes($author) . " (" . $remote . ")" );
3210 decodes {author} field for display in pages
3212 function ewiki_author_html($orig, $tail=1) {
3213 $str = strtok($orig, " (|,;/[{<+");
3214 $tail = $tail ? " " . strtok("\000") : "";
3216 if (strpos($str, ":")) {
3217 return('<a href="'. strtok($str, ":") . "\">$orig</a>");
3220 elseif (strpos($str, "@")) {
3221 // email_protect_*() now takes care of plugin pages
3222 return("<a href=\"mailto:$str\">$str</a>$tail");
3225 elseif (strpos($str, ".") < strrpos($str, ".")) {
3226 return("<a href=\"http://$str/\">$str</a>$tail");
3228 #-- eventually an AuthorName
3230 return('<a href="' . ewiki_script("", $str) . '">' . $str . '</a>' . $tail);
3243 /* Returns a value of (true) if the currently logged in user (this must
3244 be handled by one of the plugin backends) is authenticated to do the
3245 current $action, or to view the current $id page.
3246 - alternatively just checks current authentication $ring permission level
3247 - errors are returned via the global $ewiki_errmsg
3249 function ewiki_auth($id, &$data, $action, $ring=false, $request_auth=0) {
3251 global $ewiki_plugins, $ewiki_ring, $ewiki_author,
3252 $ewiki_errmsg, $ewiki_config;
3256 #echo "_a($id,dat,$action,$ring,$request_auth)<br />\n";
3258 if (EWIKI_PROTECTED_MODE) {
3260 #-- set required vars
3261 if (!isset($ewiki_ring)) {
3262 $ewiki_ring = (int)EWIKI_AUTH_DEFAULT_RING;
3264 if ($ring===false) {
3267 if ($ewiki_config["create"] && ($action=="edit")) {
3268 $action = "create"; // used only/primarily in authentication plugins
3272 $pf_login = @$ewiki_plugins["auth_query"][0];
3273 $pf_perm = $ewiki_plugins["auth_perm"][0];
3275 #-- nobody is currently logged in, so try to fetch username,
3276 # the login <form> is not yet enforced
3277 if ($pf_login && empty($ewiki_auth_user)) {
3278 $pf_login($data, 0);
3281 #-- check permission for current request (page/action/ring)
3284 #-- via _auth handler
3285 $ok = $pf_perm($id, $data, $action, $ring, $request_auth);
3287 #-- if it failed, we really depend on the login <form>,
3288 # and then recall the _perm plugin
3289 if ($pf_login && (($request_auth >= 2) || !$ok && $request_auth && (empty($ewiki_auth_user) || EWIKI_AUTO_LOGIN) && empty($ewiki_errmsg))) {
3290 //@FIXME: complicated if() - strip empty(errmsg) ??
3291 $pf_login($data, $request_auth);
3292 $ok = $pf_perm($id, $data, $action, $ring, $request_auth=0);
3296 $ok = !isset($ring) || isset($ring) && ($ewiki_ring <= $ring);
3299 #-- return error string
3300 if (!$ok && empty($ewiki_errmsg)) {
3301 ewiki_log("ewiki_auth: Access Denied ($action/$id, $ring/$ewiki_ring, $request_auth)");
3302 $ewiki_errmsg = ewiki_t("FORBIDDEN");
3311 Queries all registered ["auth_userdb"] plugins for the given
3312 username, and compares password to against "db" value, sets
3313 $ewiki_ring and returns(true) if valid.
3315 function ewiki_auth_user($username, $password) {
3316 global $ewiki_ring, $ewiki_errmsg, $ewiki_auth_user, $ewiki_plugins, $ewiki_author;
3318 if (empty($username)) {
3321 if (($password[0] == "$") || (strlen($password) > 12)) {
3322 ewiki_log("_auth_userdb: password was transmitted in encoded form, or is just too long (login attemp for user '$username')", 2);
3326 if ($pf_u = $ewiki_plugins["auth_userdb"])
3327 foreach ($pf_u as $pf) {
3329 if (function_exists($pf) && ($entry = $pf($username, $password))) {
3331 #-- get and compare password
3332 if ($entry = (array) $entry) {
3333 $enc_pw = $entry[0];
3336 || ($enc_pw == substr($password, 0, 12))
3337 || ($enc_pw == md5($password))
3338 || ($enc_pw == crypt($password, substr($enc_pw, 0, 2)))
3339 || function_exists("sha1") && ($enc_pw == sha1($password));
3340 $success &= $enc_pw != "*";
3342 #-- return if it matches
3344 if (isset($entry[1])) {
3345 $ewiki_ring = (int)($entry[1]);
3347 $ewiki_ring = 2; //(EWIKI_AUTH_DEFAULT_RING - 1);
3349 if (empty($ewiki_author)) {
3350 ($ewiki_author = $entry[2]) or
3351 ($ewiki_author = $username);
3353 return($success && ($ewiki_auth_user=$username));
3358 if ($username || $password) {
3359 ewiki_log("_auth_userdb: wrong password supplied for user '$username', not verified against any userdb", 3);
3360 $ewiki_errmsg = "wrong username and/or password";
3361 # ewiki_auth($uu, $uu, $uu, $uu, 2);
3370 Returns <form> field html strings, looks up previously selected values.
3371 Don't use it for textareas, $value magically elects the input field type.
3373 function ewiki_form($name, $value, $label="", $_text="| |\n", $inj="") {
3374 global $_EWIKI, $ewiki_id;
3376 static $_sel = ' selected="selected"', $_chk = ' checked="checked"';
3380 $_text = explode("|", $_text);
3381 list($name, $type, $width, $height) = explode(":", $name);
3382 $type = $type ? (strpos($type, "a") ? "a" : (strpos($type, "b") ? "b" : $type[0])) : "t";
3383 if ($inj) { $inj = " $inj"; }
3384 $old_value = @$_EWIKI["form"][$ewiki_id][$name];
3387 if ((($type=="s") || strpos($value, "|")) && ($v = explode("|", $value))) {
3389 foreach ($v as $opt) {
3390 $opt = strtok($opt, "="); ($title = strtok("|")) or ($title = $opt);
3391 $value[$opt] = $title;
3395 #-- label, surrounding text
3397 if ($fid++ && $label) {
3398 $o .= "<label for=\"ff$fid\">$label</label>";
3402 #-- submit (as "button")
3403 if (!$name || ($type=="b")) {
3404 if ($name) { $name = " name=\"$name\""; }
3405 $o .= "<input type=\"submit\" id=\"ff$fid\"$name value=\"$value\"$inj />";
3408 elseif (is_array($value)) {
3409 $o .= "<select name=\"$name\" id=\"ff$fid\"$inj>";
3410 $no_val = isset($value[0]);
3411 foreach ($value as $val=>$title) {
3412 if ($no_val) { $val = $title; }
3413 $sel = (!$old_value && strpos($val, "!") || ($old_value==$val)) ? $_sel : "";
3414 $o .= '<option value="' . trim(rtrim($val, "!")) . '"' . $sel . '>'
3415 . trim(rtrim($title, "!")) . '</option>';
3420 elseif (($type=="c") || strpos($value, "]")) {
3421 if (isset($old_value)) { $value = $old_value ? "1x" : ""; }
3422 $sel = strpos($value, "x") ? $_chk : "";
3423 $o .= "<input type=\"checkbox\" id=\"ff$fid\" name=\"$name\" value=\"1\"$sel$inj />";
3426 elseif ($type=="a") {
3427 if ($width && $height) { $inj .= " cols=\"$width\" rows=\"$height\""; }
3428 $o .= "<textarea id=\"ff$fid\" name=\"$name\"$inj>"
3429 . htmlentities($value) . "</textarea>";
3431 #-- input field; text or hidden
3433 if ($width) { $inj .= " size=\"$width\""; }
3434 if (isset($old_value)) { $value = $old_value; }
3435 $type = ($type == "t") ? "text" : "hidden";
3436 $o .= "<input type=\"$type\" id=\"ff$fid\" name=\"$name\" value=\""
3437 . htmlentities($value) . "\"$inj />";
3448 /* reads all files from "./init-pages/" into the database,
3449 when ewiki is run for the very first time and the FrontPage
3450 does not yet exist in the database
3452 function ewiki_eventually_initialize(&$id, &$data, &$action) {
3454 #-- initialize database only if frontpage missing
3455 if (($id==EWIKI_PAGE_INDEX) && ($action=="edit") && empty($data["version"])) {
3458 if ($dh = @opendir($path=EWIKI_INIT_PAGES)) {
3459 while ($filename = readdir($dh)) {
3460 if (preg_match('/^(['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+\w*)+/', $filename)) {
3461 $found = ewiki_db::FIND(array($filename));
3462 if (! $found[$filename]) {
3463 $content = implode("", file("$path/$filename"));
3464 ewiki_scan_wikiwords($content, $ewiki_links, "_STRIP_EMAIL=1");
3465 $refs = "\n\n" . implode("\n", array_keys($ewiki_links)) . "\n\n";
3467 "id" => "$filename",
3469 "flags" => EWIKI_DB_F_TEXT,
3470 "content" => $content,
3471 "author" => ewiki_author("ewiki_initialize"),
3473 "lastmodified" => filemtime("$path/$filename"),
3474 "created" => filectime("$path/$filename") // (not exact)
3476 ewiki_db::WRITE($save);
3483 echo "<b>ewiki error</b>: could not read from directory ". realpath($path) ."<br />\n";
3486 #-- try to view/ that newly inserted page
3487 if ($data = ewiki_db::GET($id)) {
3496 #---------------------------------------------------------------------------
3500 ######## ### ######## ### ######## ### ###### ########
3501 ######## ### ######## ### ######## ### ###### ########
3502 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3503 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3504 ## ## ## ## ## ## ## ## ## ## ## ## ##
3505 ## ## ## ## ## ## ## ## ## ## ## ## ##
3506 ## ## ## ## ## ## ## ######## ## ## ###### ######
3507 ## ## ## ## ## ## ## ######## ## ## ###### ######
3508 ## ## ######### ## ######### ## ## ######### ## ##
3509 ## ## ######### ## ######### ## ## ######### ## ##
3510 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3511 ## ## ## ## ## ## ## ## ## ## ## ## ## ##
3512 ######## ## ## ## ## ## ######## ## ## ###### ########
3513 ######## ## ## ## ## ## ######## ## ## ###### ########
3518 #-- database API (static wrapper around backends)
3523 # returns database entry as array for the page whose name was given in
3524 # $id key, usually fetches the latest version of a page, unless a specific
3525 # $version was requested
3527 function GET($id, $version=false) {
3529 $r = $ewiki_db->GET($id, 0+$version);
3530 ewiki_db::expand($r);
3536 # stores the page $hash into the database, while not overwriting existing
3537 # entries unless $overwrite was set; returns 0 on failure, 1 if completed
3539 function WRITE($hash, $overwrite=0) {
3541 if (is_array($hash) && count($hash) && !defined("EWIKI_DB_LOCK")) {
3542 #-- settype (for flat-file databases)
3543 $hash["version"] += 0;
3545 $hash["lastmodified"] += 0;
3546 $hash["created"] += 0;
3547 ewiki_db::shrink($hash);
3548 return $ewiki_db->WRITE($hash, $overwrite);
3553 # returns dbquery_result object of database entries (also arrays), where
3554 # the one specified column matches the specified content string;
3555 # it is not guaranteed to only search/return the latest version of a page;
3556 # $field may be an array, in which case an OR-search is emulated
3558 function SEARCH($field, $content, $ci=1, $regex=0, $mask=0x0000, $filter=0x0000) {
3560 $ci = ($ci ? "i" : false);
3561 #-- multisearch (or connected)
3562 if (is_array($field)) {
3563 if (isset($field[0])) { // multiple $field names, just one $content string
3564 $uu = $field; $field = array();
3565 foreach ($uu as $f) {
3566 $field[$f] = $content;
3569 $r = new ewiki_dbquery_result(array($field));
3570 foreach ($field as $f=>$c) {
3571 $add = $ewiki_db->SEARCH($f, $c, $ci, $regex, $mask, $filter);
3572 $r->entries = array_merge($r->entries, $add->entries);
3573 unset($add); // dispose, hopefully
3578 $r = $ewiki_db->SEARCH($field, $content, $ci, $regex, $mask, $filter);
3579 ewiki_db::dbquery_result($r);
3586 # returns an dbquery_result object with __all__ pages, where each entry
3587 # is made up of at least the fields from the database requested with the
3588 # $fields array, e.g. array("flags","meta","lastmodified");
3590 function GETALL($fields, $mask=0x0000, $filter=0x0000) {
3592 $fields[] = "flags";
3593 $fields[] = "version";
3594 $fields = array_flip($fields);
3595 unset($fields["id"]);
3596 $fields = array_flip($fields);
3597 $r = $ewiki_db->GETALL($fields);
3598 ewiki_db::dbquery_result($r);
3603 #-- check page existence
3604 # searches for all given page names (in $list) in the database and returns
3605 # an associative array with page names as keys and booleans as values;
3606 # (int)0 for missing pages, and for existing ones the associated value is
3607 # the page {flags} value or the {meta} data array (for binary entries)
3609 function FIND($list) {
3611 if (!count($list)) {
3614 return $ewiki_db->FIND($list);
3619 # increases the {hit} counter for the page given by $id
3623 return $ewiki_db->HIT($id);
3628 function DELETE($id, $version=false) {
3630 if (!defined("EWIKI_DB_LOCK"))
3631 return $ewiki_db->DELETE($id, $version);
3635 return $ewiki_db->INIT();
3639 #-- virtual features
3640 # ::CREATE() creates a new page hash (template)
3641 # ::UPDATE() renews meta data (except version) to allow ::WRITE()
3642 # ::APPEND() adds content to an existing text page
3644 function CREATE($id, $flags=EWIKI_DB_F_TEXT, $author="") {
3646 "id"=>$id, "version"=>1, "flags"=>$flags,
3647 "content"=>"", "meta"=>array(),
3648 "hits"=>0, "created"=>time(),
3649 "lastmodified"=>time(),
3650 "author"=>ewiki_author($author),
3654 function UPDATE(&$data, $author="") {
3655 global $ewiki_links;
3656 #-- regenerate backlinks entry
3657 ewiki_scan_wikiwords($data["content"], $ewiki_links, "_STRIP_EMAIL=1");
3658 $data["refs"] = "\n\n".implode("\n", array_keys($ewiki_links))."\n\n";
3659 #-- update meta info
3660 $data["lastmodified"] = time();
3661 $data["author"] = ewiki_author($author);
3662 $data["meta"]["user-agent"] = trim($_SERVER["HTTP_USER_AGENT"]);
3664 function APPEND($id, $text, $textonly=1) {
3665 ($data = ewiki_db::GET($id))
3666 or ($data = ewiki_db::CREATE($id));
3667 if (!strlen(trim($text)) or $textonly && (($data["flags"]&EWIKI_DB_F_TYPE) != EWIKI_DB_F_TEXT)) {
3670 $data["content"] .= $text;
3671 ewiki_db::UPDATE($data);
3673 return ewiki_db::WRITE($data);
3678 function expand(&$r) {
3679 if (isset($r["meta"]) && is_string($r["meta"]) && strlen($r["meta"])) {
3680 $r["meta"] = unserialize($r["meta"]);
3683 function shrink(&$r) {
3684 if (isset($r["meta"]) && is_array($r["meta"])) {
3685 $r["meta"] = serialize($r["meta"]);
3688 function dbquery_result(&$r) {
3690 $z = new ewiki_dbquery_result(array_keys($args));
3691 foreach ($r as $id=>$row) {
3702 #-- returned for SEARCH and GETALL queries, as those operations are
3703 # otherwise too memory exhaustive
3704 class ewiki_dbquery_result {
3706 var $keys = array();
3707 var $entries = array();
3708 var $buffer = EWIKI_DBQUERY_BUFFER;
3711 function ewiki_dbquery_result($keys) {
3712 $keys = array_merge((array)$keys, array(-50=>"id", "version", "flags"));
3713 $this->keys = array_unique($keys);
3716 function add($row) {
3717 if (is_array($row)) {
3718 if ($this->buffer) {
3719 $this->size += strlen(serialize($row));
3720 $this->buffer = $this->size <= EWIKI_DBQUERY_BUFFER;
3721 ewiki_db::expand($row);
3727 $this->entries[] = $row;
3730 function get($all=0, $flags=0x0000, $type=0) {
3733 $prot_hide = ($flags&0x0020) && EWIKI_PROTECTED_MODE && EWIKI_PROTECTED_MODE_HIDING;
3734 $flag_hide = ($flags&0x0003);
3736 if (count($this->entries)) {
3738 #-- fetch very first entry from $entries list
3739 $r = array_shift($this->entries);
3741 #-- finish if buffered entry
3742 if (is_array($r) && !$all) {
3745 #-- else refetch complete entry from database
3750 $r = ewiki_db::GET($r);
3752 foreach ($this->keys as $key) {
3753 $row[$key] = $r[$key];
3762 return(NULL); // no more entries
3765 #-- expand {meta} field
3766 if (is_array($row) && is_string(@$row["meta"])) {
3767 $row["meta"] = unserialize($row["meta"]);
3770 #-- drop unwanted results
3771 if ($prot_hide && !ewiki_auth($row["id"], $row, 'view')
3772 || ($flag_hide && ($row["flags"] & (EWIKI_DB_F_HIDDEN|EWIKI_DB_F_DISABLED)))
3773 || ($type) && (($row["flags"] & EWIKI_DB_F_TYPE) != $type)) {
3776 } while (empty($row) && ($prot_hide || $flag_hide));
3782 return(count($this->entries));
3788 #-- obsolete compatibility wrapper
3789 function ewiki_database($action, $args, $sw1=0, $sw2=0, $pf=false) {
3792 return ewiki_db::GET($args["id"], @$args["version"]);
3794 return ewiki_db::WRITE($args, 0);
3796 return ewiki_db::WRITE($args, 1);
3798 return ewiki_db::FIND($args);
3800 return ewiki_db::GETALL($args);
3802 return ewiki_db::SEARCH(implode("",array_keys($args)), implode("",$args));
3804 return ewiki_db::HIT($args["id"]);
3806 return ewiki_db::DELETE($args["id"], $args["version"]);
3808 return ewiki_db::INIT();
3810 echo "error: unknown database call '$action'<br>\n";
3816 #-- MySQL database backend (default, but will be teared out soon)
3817 # Note: this is of course an abuse of the relational database scheme,
3818 # but necessary for real db independence and abstraction
3819 class ewiki_database_mysql {
3821 function ewiki_database_mysql() {
3822 $this->table = EWIKI_DB_TABLE_NAME;
3826 function GET($id, $version=false) {
3827 $id = mysql_escape_string($id);
3829 $version = "AND (version=$version)";
3833 $result = mysql_query("SELECT *, pagename as id FROM {$this->table}
3834 WHERE (pagename='$id') $version ORDER BY version DESC LIMIT 1"
3837 if ($result && ($r = mysql_fetch_array($result, MYSQL_ASSOC))) {
3838 unset($r["pagename"]);
3845 $id = mysql_escape_string($id);
3846 mysql_query("UPDATE {$this->table} SET hits=(hits+1) WHERE pagename='$id'");
3850 function WRITE($hash, $overwrite=0) {
3852 $COMMAND = $overwrite ? "REPLACE" : "INSERT";
3854 $hash["pagename"] = $hash["id"];
3856 foreach ($hash as $index=>$value) {
3857 if (is_int($index)) {
3860 $a = ($sql1 ? ', ' : '');
3861 $sql1 .= $a . $index;
3862 $sql2 .= $a . "'" . mysql_escape_string($value) . "'";
3865 $result = mysql_query("$COMMAND INTO {$this->table} ($sql1) VALUES ($sql2)");
3866 $result = ($result && mysql_affected_rows()) ?1:0;
3871 function FIND($list) {
3874 foreach (array_values($list) as $id) {
3877 $sql .= ($sql ? " OR " : "") .
3878 "(pagename='" . mysql_escape_string($id) . "')";
3881 $result = mysql_query("SELECT pagename AS id, meta, flags FROM {$this->table} WHERE $sql");
3883 while ($row = mysql_fetch_array($result)) {
3885 if (strlen($row["meta"])) {
3886 $r[$id] = unserialize($row["meta"]);
3887 $r[$id]["flags"] = $row["flags"];
3889 $r[$id] = $row["flags"];
3897 function GETALL($fields, $mask=0, $filter=0) {
3898 $fields = implode(", ", $fields);
3899 $f_sql = $mask ? "WHERE ((flags & $mask) = $filter)" : "";
3900 $result = mysql_query("SELECT pagename AS id, $fields FROM
3901 {$this->table} $f_sql GROUP BY id, version DESC"
3903 $r = new ewiki_dbquery_result($fields);
3905 if ($result) while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
3906 $drop = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
3907 if (($last != $drop) && ($last = $drop)) {
3915 function SEARCH($field, $content, $ci="i", $regex=0, $mask=0, $filter=0) {
3917 $sql_fields = ", $field";
3918 if ($field == "id") {
3919 $field = "pagename";
3922 $content = mysql_escape_string($content);
3924 $sql_flags = "AND ((flags & $mask) = $filter)";
3927 $sql_strsearch = "($field REGEXP '$content')";
3930 $sql_strsearch = "LOCATE('".strtolower($content)."', LCASE($field))";
3933 $sql_strsearch = "LOCATE('$content', $field)";
3936 $result = mysql_query(
3937 "SELECT pagename AS id, version, flags $sql_fields
3939 WHERE $sql_strsearch $sql_flags
3940 GROUP BY id, version DESC
3943 $r = new ewiki_dbquery_result(array("id","version",$field));
3945 if ($result) while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
3946 $drop = EWIKI_CASE_INSENSITIVE ? strtolower($row["id"]) : $row["id"];
3947 if (($last != $drop) && ($last = $drop)) {
3955 function DELETE($id, $version) {
3956 $id = mysql_escape_string($id);
3957 mysql_query("DELETE FROM {$this->table} WHERE pagename='$id' AND version=$version");
3962 mysql_query("CREATE TABLE {$this->table}
3963 (pagename VARCHAR(160) NOT NULL,
3964 version INTEGER UNSIGNED NOT NULL DEFAULT 0,
3965 flags INTEGER UNSIGNED DEFAULT 0,
3967 author VARCHAR(100) DEFAULT 'ewiki',
3968 created INTEGER UNSIGNED DEFAULT ".time().",
3969 lastmodified INTEGER UNSIGNED DEFAULT 0,
3972 hits INTEGER UNSIGNED DEFAULT 0,
3973 PRIMARY KEY id (pagename, version) )
3979 } // end of class ewiki_database_mysql