| [ Index ] |
|
Code source de WikiNi 0.4.4 |
1 <?php 2 /* encoding: iso-8859-1 3 wakka.php 4 Copyright (c) 2002, Hendrik Mans <hendrik@mans.de> 5 Copyright 2003 Carlo Zottmann 6 Copyright 2002, 2003 David DELON 7 Copyright 2002, 2003, 2004 Charles NÉPOTE 8 Copyright 2002, 2003 Patrick PAUL 9 Copyright 2003 Éric DELORD 10 Copyright 2003 Éric FELDSTEIN 11 Copyright 2004 Jean-Christophe ANDRÉ 12 Copyrught 2005-2006 Didier LOISEAU 13 All rights reserved. 14 Redistribution and use in source and binary forms, with or without 15 modification, are permitted provided that the following conditions 16 are met: 17 1. Redistributions of source code must retain the above copyright 18 notice, this list of conditions and the following disclaimer. 19 2. Redistributions in binary form must reproduce the above copyright 20 notice, this list of conditions and the following disclaimer in the 21 documentation and/or other materials provided with the distribution. 22 3. The name of the author may not be used to endorse or promote products 23 derived from this software without specific prior written permission. 24 25 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 /* 38 Yes, most of the formatting used in this file is HORRIBLY BAD STYLE. However, 39 most of the action happens outside of this file, and I really wanted the code 40 to look as small as what it does. Basically. Oh, I just suck. :) 41 */ 42 43 44 45 // do not change this line, you fool. In fact, don't change anything! Ever! 46 define("WAKKA_VERSION", "0.1.1"); 47 define("WIKINI_VERSION", "0.4.4"); 48 // start the compute time 49 list($g_usec, $g_sec) = explode(" ",microtime()); 50 define ("t_start", (float)$g_usec + (float)$g_sec); 51 $t_SQL=0; 52 53 54 55 class Wiki 56 { 57 var $dblink; 58 var $page; 59 var $tag; 60 var $parameter = array(); 61 var $queryLog = array(); 62 var $interWiki = array(); 63 var $VERSION; 64 var $CookiePath = '/'; 65 66 67 // constructor 68 function Wiki($config) 69 { 70 $this->config = $config; 71 // some host do not allow mysql_pconnect 72 $this->dblink = @mysql_connect ( 73 $this->config["mysql_host"], 74 $this->config["mysql_user"], 75 $this->config["mysql_password"]); 76 if ($this->dblink) 77 { 78 if (!@mysql_select_db($this->config["mysql_database"], $this->dblink)) 79 { 80 @mysql_close($this->dblink); 81 $this->dblink = false; 82 } 83 } 84 $this->VERSION = WAKKA_VERSION; 85 86 //determine le chemin pour le cookie 87 $a = parse_url($this->GetConfigValue('base_url')); 88 $this->CookiePath = dirname($a['path']); 89 if ($this->CookiePath != '/') $this->CookiePath .= '/'; 90 } 91 92 93 94 // DATABASE 95 function Query($query) 96 { 97 if($this->GetConfigValue("debug")) $start = $this->GetMicroTime(); 98 if (!$result = mysql_query($query, $this->dblink)) 99 { 100 ob_end_clean(); 101 die("Query failed: ".$query." (".mysql_error().")"); 102 } 103 if($this->GetConfigValue("debug")) 104 { 105 $time = $this->GetMicroTime() - $start; 106 $this->queryLog[] = array( 107 "query" => $query, 108 "time" => $time); 109 } 110 return $result; 111 } 112 function LoadSingle($query) { if ($data = $this->LoadAll($query)) return $data[0]; } 113 function LoadAll($query) 114 { 115 $data=array(); 116 if ($r = $this->Query($query)) 117 { 118 while ($row = mysql_fetch_assoc($r)) $data[] = $row; 119 mysql_free_result($r); 120 } 121 return $data; 122 } 123 124 125 126 // MISC 127 function GetMicroTime() { list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec); } 128 function IncludeBuffered($filename, $notfoundText = "", $vars = "", $path = "") 129 { 130 if ($path) $dirs = explode(":", $path); 131 else $dirs = array(""); 132 133 foreach($dirs as $dir) 134 { 135 if ($dir) $dir .= "/"; 136 $fullfilename = $dir.$filename; 137 if (file_exists($fullfilename)) 138 { 139 if (is_array($vars)) extract($vars); 140 141 ob_start(); 142 include($fullfilename); 143 $output = ob_get_contents(); 144 ob_end_clean(); 145 return $output; 146 } 147 } 148 if ($notfoundText) return $notfoundText; 149 else return false; 150 } 151 152 153 154 // VARIABLES 155 function GetPageTag() { return $this->tag; } 156 function GetPageTime() { return $this->page["time"]; } 157 function GetMethod() { return $this->method; } 158 function GetConfigValue($name) { return $this->config[$name]; } 159 function GetWakkaName() { return $this->GetConfigValue("wakka_name"); } 160 function GetWakkaVersion() { return $this->VERSION; } 161 function GetWikiNiVersion() { return WIKINI_VERSION; } 162 163 164 165 // PAGES 166 function LoadPage($tag, $time = "", $cache = 1) { 167 // retrieve from cache 168 if (!$time && $cache && ($cachedPage = $this->GetCachedPage($tag))) { $page = $cachedPage;} 169 // load page 170 if (!isset($page)) $page = $this->LoadSingle("select * from ".$this->config["table_prefix"]."pages where tag = '".mysql_escape_string($tag)."' ".($time ? "and time = '".mysql_escape_string($time)."'" : "and latest = 'Y'")." limit 1"); 171 // cache result 172 if (!$time) $this->CachePage($page); 173 return $page; 174 } 175 function GetCachedPage($tag) {return (isset($this->pageCache[$tag]) ? $this->pageCache[$tag] : ''); } 176 function CachePage($page) { $this->pageCache[$page["tag"]] = $page; } 177 function SetPage($page) { $this->page = $page; if ($this->page["tag"]) $this->tag = $this->page["tag"]; } 178 function LoadPageById($id) { return $this->LoadSingle("select * from ".$this->config["table_prefix"]."pages where id = '".mysql_escape_string($id)."' limit 1"); } 179 function LoadRevisions($page) { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where tag = '".mysql_escape_string($page)."' order by time desc"); } 180 function LoadPagesLinkingTo($tag) { return $this->LoadAll("select from_tag as tag from ".$this->config["table_prefix"]."links where to_tag = '".mysql_escape_string($tag)."' order by tag"); } 181 function LoadRecentlyChanged($limit=50) { 182 $limit= (int) $limit; 183 if ($pages = $this->LoadAll("select tag, time, user, owner from ".$this->config["table_prefix"]."pages where latest = 'Y' and comment_on = '' order by time desc limit $limit")) 184 { 185 foreach ($pages as $page) 186 { 187 $this->CachePage($page); 188 } 189 return $pages; 190 } 191 } 192 function LoadAllPages() { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where latest = 'Y' order by tag"); } 193 function FullTextSearch($phrase) { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where latest = 'Y' and match(tag, body) against('".mysql_escape_string($phrase)."')"); } 194 function LoadWantedPages() { return $this->LoadAll("select distinct ".$this->config["table_prefix"]."links.to_tag as tag,count(".$this->config["table_prefix"]."links.from_tag) as count from ".$this->config["table_prefix"]."links left join ".$this->config["table_prefix"]."pages on ".$this->config["table_prefix"]."links.to_tag = ".$this->config["table_prefix"]."pages.tag where ".$this->config["table_prefix"]."pages.tag is NULL group by tag order by count desc"); } 195 function LoadOrphanedPages() { return $this->LoadAll("select distinct tag from ".$this->config["table_prefix"]."pages left join ".$this->config["table_prefix"]."links on ".$this->config["table_prefix"]."pages.tag = ".$this->config["table_prefix"]."links.to_tag where ".$this->config["table_prefix"]."links.to_tag is NULL and ".$this->config["table_prefix"]."pages.comment_on = '' order by tag"); } 196 function IsOrphanedPage($tag) { return $this->LoadAll("select distinct tag from ".$this->config["table_prefix"]."pages left join ".$this->config["table_prefix"]."links on ".$this->config["table_prefix"]."pages.tag = ".$this->config["table_prefix"]."links.to_tag where ".$this->config["table_prefix"]."links.to_tag is NULL and ".$this->config["table_prefix"]."pages.comment_on ='' and tag='".mysql_escape_string($tag)."'"); } 197 function DeleteOrphanedPage($tag) { 198 $this->Query("delete from ".$this->config["table_prefix"]."pages where tag='".mysql_escape_string($tag)."' "); 199 $this->Query("delete from ".$this->config["table_prefix"]."links where from_tag='".mysql_escape_string($tag)."' "); 200 $this->Query("delete from ".$this->config["table_prefix"]."acls where page_tag='".mysql_escape_string($tag)."' "); 201 $this->Query("delete from ".$this->config["table_prefix"]."referrers where page_tag='".mysql_escape_string($tag)."' "); 202 } 203 function SavePage($tag, $body, $comment_on = "") { 204 // get current user 205 $user = $this->GetUserName(); 206 207 //die($tag); 208 209 // TODO: check write privilege 210 if ($comment_on ? $this->HasAccess("comment", $comment_on) 211 : $this->HasAccess("write", $tag)) 212 { 213 // is page new? 214 if (!$oldPage = $this->LoadPage($tag)) 215 { 216 // create default write acl. store empty write ACL for comments. 217 $this->SaveAcl($tag, "write", ($comment_on ? "" : $this->GetConfigValue("default_write_acl"))); 218 219 // create default read acl 220 $this->SaveAcl($tag, "read", $this->GetConfigValue("default_read_acl")); 221 222 // create default comment acl. 223 $this->SaveAcl($tag, "comment", $this->GetConfigValue("default_comment_acl")); 224 225 // current user is owner; if user is logged in! otherwise, no owner. 226 if ($this->GetUser()) $owner = $user; 227 else $owner = ''; 228 } 229 else 230 { 231 // aha! page isn't new. keep owner! 232 $owner = $oldPage["owner"]; 233 } 234 235 236 // set all other revisions to old 237 $this->Query("update ".$this->config["table_prefix"]."pages set latest = 'N' where tag = '".mysql_Escape_string($tag)."'"); 238 239 // add new revision 240 $this->Query("insert into ".$this->config["table_prefix"]."pages set ". 241 "tag = '".mysql_escape_string($tag)."', ". 242 ($comment_on ? "comment_on = '".mysql_escape_string($comment_on)."', " : ""). 243 "time = now(), ". 244 "owner = '".mysql_escape_string($owner)."', ". 245 "user = '".mysql_escape_string($user)."', ". 246 "latest = 'Y', ". 247 "body = '".mysql_escape_string(chop($body))."'"); 248 } 249 } 250 function PurgePages() { 251 if ($days = $this->GetConfigValue("pages_purge_time")) { 252 // Selection of pages which can be deleted 253 $pages = $this->LoadAll("select distinct tag, time from ".$this->config["table_prefix"]."pages where time < date_sub(now(), interval '".mysql_escape_string($days)."' day) and latest = 'N' order by time asc"); 254 foreach ($pages as $page) { 255 // Deletion if there are more than 2 versions avalaible (TODO : parameter ?) 256 $tags=$this->LoadAll("select distinct tag from ".$this->config["table_prefix"]."pages where tag = '".mysql_escape_string($page['tag'])."' group by tag having count(*) > 2 order by tag"); 257 foreach ($tags as $tag) { 258 $this->Query("delete from ".$this->config["table_prefix"]."pages where time = '".mysql_escape_string($page['time'])."' and tag = '".mysql_escape_string($tag['tag'])."'"); 259 } 260 } 261 } 262 } 263 264 265 266 // COOKIES 267 function SetSessionCookie($name, $value) { SetCookie($name, $value, 0, $this->CookiePath); $_COOKIE[$name] = $value; } 268 function SetPersistentCookie($name, $value, $remember = 0) { SetCookie($name, $value, time() + ($remember ? 90*24*60*60 : 60 * 60), $this->CookiePath); $_COOKIE[$name] = $value; } 269 function DeleteCookie($name) { SetCookie($name, "", 1, $this->CookiePath); $_COOKIE[$name] = ""; } 270 function GetCookie($name) { return $_COOKIE[$name]; } 271 272 273 274 // HTTP/REQUEST/LINK RELATED 275 function SetMessage($message) { $_SESSION["message"] = $message; } 276 function GetMessage() 277 { 278 if (isset($_SESSION["message"])) $message = $_SESSION["message"]; 279 else $message = ""; 280 $_SESSION["message"] = ""; 281 return $message; 282 } 283 function Redirect($url) 284 { 285 header("Location: $url"); 286 exit; 287 } 288 // returns just PageName[/method]. 289 function MiniHref($method = "", $tag = "") 290 { 291 if (!$tag = trim($tag)) $tag = $this->tag; 292 return $tag.($method ? "/".$method : ""); 293 } 294 // returns the full url to a page/method. 295 function Href($method = "", $tag = "", $params = "") 296 { 297 $href = $this->config["base_url"].$this->MiniHref($method, $tag); 298 if ($params) 299 { 300 $href .= ($this->config["rewrite_mode"] ? "?" : "&").$params; 301 } 302 return $href; 303 } 304 function Link($tag, $method = "", $text = "", $track = 1) 305 { 306 $tag=htmlspecialchars($tag); //avoid xss 307 $text=htmlspecialchars($text); //paranoiac again 308 $text = preg_replace('/&(\\#[xX][a-fA-F0-9]+|\\#[0-9]+|[a-zA-Z0-9]+);/', '&$1;', $text); 309 if (!$text) $text = $tag; 310 311 // is this an interwiki link? 312 if (preg_match("/^([A-Z][A-Z,a-z]+)[:]([A-Z,a-z,0-9]*)$/s", $tag, $matches)) 313 { 314 $tag = $this->GetInterWikiUrl($matches[1], $matches[2]); 315 return "<a href=\"$tag\">$text (interwiki)</a>"; 316 } 317 // is this a full link? ie, does it contain non alpha-numeric characters? 318 // Note : [:alnum:] is equivalent [0-9A-Za-z] 319 // [^[:alnum:]] means : some caracters other than [0-9A-Za-z] 320 // For example : "www.adress.com", "mailto:adress@domain.com", "http://www.adress.com" 321 else if (preg_match("/[^[:alnum:]]/", $tag)) 322 { 323 // check for email addresses 324 if (preg_match("/^[\w.-]+\@[\w.-]+$/", $tag)) 325 { 326 $tag = "mailto:".$tag; 327 } 328 // check for protocol-less URLs 329 else if (!preg_match("/:\/\//", $tag)) 330 { 331 $tag = "http://".$tag; //Very important for xss (avoid javascript:() hacking) 332 } 333 // is this an inline image (text!=tag and url ends png,gif,jpeg) 334 if ($text!=$tag and preg_match("/.(gif|jpeg|png|jpg)$/i",$tag)) 335 { 336 return "<img src=\"$tag\" alt=\"$text\" />"; 337 } 338 else 339 { 340 return "<a href=\"$tag\">$text</a>"; 341 } 342 } 343 else 344 { 345 // it's a Wiki link! 346 if (isset($_SESSION["linktracking"]) && $track) $this->TrackLinkTo($tag); 347 return ($this->LoadPage($tag) ? "<a href=\"".$this->href($method, $tag)."\">".$text."</a>" : "<span class=\"missingpage\">".$text."</span><a href=\"".$this->href("edit", $tag)."\">?</a>"); 348 } 349 } 350 function ComposeLinkToPage($tag, $method = "", $text = "", $track = 1) { 351 if (!$text) $text = $tag; 352 $text = htmlentities($text); 353 if (isset($_SESSION["linktracking"]) && $track) 354 $this->TrackLinkTo($tag); 355 return '<a href="'.$this->href($method, $tag).'">'.$text.'</a>'; 356 } 357 // function PregPageLink($matches) { return $this->Link($matches[1]); } 358 function IsWikiName($text) { return preg_match("/^[A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*$/", $text); } 359 function TrackLinkTo($tag) { $_SESSION["linktable"][] = $tag; } 360 function GetLinkTable() { return $_SESSION["linktable"]; } 361 function ClearLinkTable() { $_SESSION["linktable"] = array(); } 362 function StartLinkTracking() { $_SESSION["linktracking"] = 1; } 363 function StopLinkTracking() { $_SESSION["linktracking"] = 0; } 364 function WriteLinkTable() { 365 // delete old link table 366 $this->Query("delete from ".$this->config["table_prefix"]."links where from_tag = '".mysql_escape_string($this->GetPageTag())."'"); 367 if ($linktable = $this->GetLinkTable()) 368 { 369 $from_tag = mysql_escape_string($this->GetPageTag()); 370 foreach ($linktable as $to_tag) 371 { 372 $lower_to_tag = strtolower($to_tag); 373 if (!isset($written[$lower_to_tag])) 374 { 375 $this->Query("insert into ".$this->config["table_prefix"]."links set from_tag = '".$from_tag."', to_tag = '".mysql_escape_string($to_tag)."'"); 376 $written[$lower_to_tag] = 1; 377 } 378 } 379 } 380 } 381 function Header() { return $this->Action($this->GetConfigValue("header_action"), 1); } 382 function Footer() { return $this->Action($this->GetConfigValue("footer_action"), 1); } 383 384 385 386 // FORMS 387 function FormOpen($method = "", $tag = "", $formMethod = "post") { 388 $result = "<form action=\"".$this->href($method, $tag)."\" method=\"".$formMethod."\">\n"; 389 if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wiki\" value=\"".$this->MiniHref($method, $tag)."\" />\n"; 390 return $result; 391 } 392 function FormClose() { 393 return "</form>\n"; 394 } 395 396 397 398 // INTERWIKI STUFF 399 function ReadInterWikiConfig() { 400 if ($lines = file("interwiki.conf")) 401 { 402 foreach ($lines as $line) 403 { 404 if ($line = trim($line)) 405 { 406 list($wikiName, $wikiUrl) = explode(" ", trim($line)); 407 $this->AddInterWiki($wikiName, $wikiUrl); 408 } 409 } 410 } 411 } 412 function AddInterWiki($name, $url) { 413 $this->interWiki[$name] = $url; 414 } 415 function GetInterWikiUrl($name, $tag) { 416 if (isset($this->interWiki[$name])) 417 { 418 return $this->interWiki[$name].$tag; 419 } else { 420 return 'http://'.$tag; //avoid xss by putting http:// in front of JavaScript:() 421 } 422 } 423 424 425 426 // REFERRERS 427 function LogReferrer($tag = "", $referrer = "") { 428 // fill values 429 if (!$tag = trim($tag)) $tag = $this->GetPageTag(); 430 if (!$referrer = trim($referrer) AND isset($_SERVER["HTTP_REFERER"])) $referrer = $_SERVER["HTTP_REFERER"]; 431 432 // check if it's coming from another site 433 if ($referrer && !preg_match("/^".preg_quote($this->GetConfigValue("base_url"), "/")."/", $referrer)) 434 { 435 // avoid XSS (with urls like "javascript:alert()" and co) 436 // by forcing http/https prefix 437 // NB.: this does NOT exempt to htmlspecialchars() the collected URIs ! 438 if (!preg_match('`^https?://`', $referrer)) return; 439 440 $this->Query("insert into ".$this->config["table_prefix"]."referrers set ". 441 "page_tag = '".mysql_escape_string($tag)."', ". 442 "referrer = '".mysql_escape_string($referrer)."', ". 443 "time = now()"); 444 } 445 } 446 function LoadReferrers($tag = "") { 447 return $this->LoadAll("select referrer, count(referrer) as num from ".$this->config["table_prefix"]."referrers ".($tag = trim($tag) ? "where page_tag = '".mysql_escape_string($tag)."'" : "")." group by referrer order by num desc"); 448 } 449 function PurgeReferrers() { 450 if ($days = $this->GetConfigValue("referrers_purge_time")) { 451 $this->Query("delete from ".$this->config["table_prefix"]."referrers where time < date_sub(now(), interval '".mysql_escape_string($days)."' day)"); 452 } 453 } 454 455 456 457 // PLUGINS 458 function Action($action, $forceLinkTracking = 0) 459 { 460 $action = trim($action); $vars=array(); 461 // stupid attributes check 462 if ((stristr($action, "=\"")) || (stristr($action, "/"))) 463 { 464 // extract $action and $vars_temp ("raw" attributes) 465 preg_match("/^([A-Za-z0-9]*)\/?(.*)$/", $action, $matches); 466 list(, $action, $vars_temp) = $matches; 467 // match all attributes (key and value) 468 $this->parameter[$vars_temp]=$vars_temp; 469 preg_match_all("/([A-Za-z0-9]*)=\"(.*)\"/U", $vars_temp, $matches); 470 471 // prepare an array for extract() to work with (in $this->IncludeBuffered()) 472 if (is_array($matches)) 473 { 474 for ($a = 0; $a < count($matches[1]); $a++) 475 { 476 $vars[$matches[1][$a]] = $matches[2][$a]; 477 $this->parameter[$matches[1][$a]]=$matches[2][$a]; 478 } 479 } 480 } 481 if (!$forceLinkTracking) $this->StopLinkTracking(); 482 $result = $this->IncludeBuffered(strtolower($action).".php", "<i>Action inconnue \"$action\"</i>", $vars, $this->config["action_path"]); 483 $this->StartLinkTracking(); 484 if (isset($parameter)) unset($this->parameter[$parameter]); 485 unset($this->parameter); 486 return $result; 487 } 488 function Method($method) { 489 if (!$handler = $this->page["handler"]) $handler = "page"; 490 $methodLocation = $handler."/".$method.".php"; 491 return $this->IncludeBuffered($methodLocation, "<i>Méthode inconnue \"$methodLocation\"</i>", "", $this->config["handler_path"]); 492 } 493 function Format($text, $formatter = "wakka") { 494 return $this->IncludeBuffered("formatters/".$formatter.".php", "<i>Impossible de trouver le formateur \"$formatter\"</i>", compact("text")); 495 } 496 497 498 499 // USERS 500 function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config["table_prefix"]."users where name = '".mysql_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_escape_string($password)."'")." limit 1"); } 501 function LoadUsers() { return $this->LoadAll("select * from ".$this->config["table_prefix"]."users order by name"); } 502 function GetUserName() { if ($user = $this->GetUser()) $name = $user["name"]; else if (!$name = gethostbyaddr($_SERVER["REMOTE_ADDR"])) $name = $_SERVER["REMOTE_ADDR"]; return $name; } 503 function UserName() { /* deprecated! */ return $this->GetUserName(); } 504 function GetUser() { return (isset($_SESSION["user"]) ? $_SESSION["user"] : '');} 505 function SetUser($user, $remember=0) { $_SESSION["user"] = $user; $this->SetPersistentCookie("name", $user["name"], $remember); $this->SetPersistentCookie("password", $user["password"], $remember); $this->SetPersistentCookie("remember", $remember, $remember); } 506 function LogoutUser() { $_SESSION["user"] = ""; $this->DeleteCookie("name"); $this->DeleteCookie("password"); } 507 function UserWantsComments() { if (!$user = $this->GetUser()) return false; return ($user["show_comments"] == "Y"); } 508 function GetParameter($parameter, $default = '') { return (isset($this->parameter[$parameter]) ? $this->parameter[$parameter] : $default); } 509 510 511 512 // COMMENTS 513 function LoadComments($tag) { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where comment_on = '".mysql_escape_string($tag)."' and latest = 'Y' order by time"); } 514 function LoadRecentComments() { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where comment_on != '' and latest = 'Y' order by time desc"); } 515 function LoadRecentlyCommented($limit = 50) { 516 $pages = array(); 517 518 // NOTE: this is really stupid. Maybe my SQL-Fu is too weak, but apparently there is no easier way to simply select 519 // all comment pages sorted by their first revision's (!) time. ugh! 520 521 // load ids of the first revisions of latest comments. err, huh? 522 $pages=array(); 523 $comments=array(); 524 if ($ids = $this->LoadAll("select min(id) as id from ".$this->config["table_prefix"]."pages where comment_on != '' group by tag order by id desc")) 525 { 526 // load complete comments 527 $num=0; 528 foreach ($ids as $id) 529 { 530 $comment = $this->LoadSingle("select * from ".$this->config["table_prefix"]."pages where id = '".$id["id"]."' limit 1"); 531 if (!isset($comments[$comment["comment_on"]]) && $num < $limit) 532 { 533 $comments[$comment["comment_on"]] = $comment; 534 $num++; 535 } 536 } 537 538 // now load pages 539 if ($comments) 540 { 541 // now using these ids, load the actual pages 542 foreach ($comments as $comment) 543 { 544 $page = $this->LoadPage($comment["comment_on"]); 545 $page["comment_user"] = $comment["user"]; 546 $page["comment_time"] = $comment["time"]; 547 $page["comment_tag"] = $comment["tag"]; 548 $pages[] = $page; 549 } 550 } 551 } 552 // load tags of pages 553 //return $this->LoadAll("select comment_on as tag, max(time) as time, tag as comment_tag, user from ".$this->config["table_prefix"]."pages where comment_on != '' group by comment_on order by time desc"); 554 return $pages; 555 } 556 557 558 559 // ACCESS CONTROL 560 // returns true if logged in user is owner of current page, or page specified in $tag 561 function UserIsOwner($tag = "") { 562 // check if user is logged in 563 if (!$this->GetUser()) return false; 564 565 // set default tag 566 if (!$tag = trim($tag)) $tag = $this->GetPageTag(); 567 568 // check if user is owner 569 if ($this->GetPageOwner($tag) == $this->GetUserName()) return true; 570 } 571 function GetPageOwner($tag = "", $time = "") { if (!$tag = trim($tag)) $tag = $this->GetPageTag(); if ($page = $this->LoadPage($tag, $time)) return $page["owner"]; } 572 function SetPageOwner($tag, $user) { 573 // check if user exists 574 if (!$this->LoadUser($user)) return; 575 576 // updated latest revision with new owner 577 $this->Query("update ".$this->config["table_prefix"]."pages set owner = '".mysql_escape_string($user)."' where tag = '".mysql_escape_string($tag)."' and latest = 'Y' limit 1"); 578 } 579 function LoadAcl($tag, $privilege, $useDefaults = 1) { 580 if ((!$acl = $this->LoadSingle("select * from ".$this->config["table_prefix"]."acls where page_tag = '".mysql_escape_string($tag)."' and privilege = '".mysql_escape_string($privilege)."' limit 1")) && $useDefaults) 581 { 582 $acl = array("page_tag" => $tag, "privilege" => $privilege, "list" => $this->GetConfigValue("default_".$privilege."_acl")); 583 } 584 return $acl; 585 } 586 function SaveAcl($tag, $privilege, $list) { 587 if ($this->LoadAcl($tag, $privilege, 0)) $this->Query("update ".$this->config["table_prefix"]."acls set list = '".mysql_escape_string(trim(str_replace("\r", "", $list)))."' where page_tag = '".mysql_escape_string($tag)."' and privilege = '".mysql_escape_string($privilege)."' limit 1"); 588 else $this->Query("insert into ".$this->config["table_prefix"]."acls set list = '".mysql_escape_string(trim(str_replace("\r", "", $list)))."', page_tag = '".mysql_escape_string($tag)."', privilege = '".mysql_escape_string($privilege)."'"); 589 } 590 // returns true if $user (defaults to current user) has access to $privilege on $page_tag (defaults to current page) 591 function HasAccess($privilege, $tag = "", $user = "") { 592 // set defaults 593 if (!$tag = trim($tag)) $tag = $this->GetPageTag(); 594 if (!$user = $this->GetUserName()); 595 596 // load acl 597 $acl = $this->LoadAcl($tag, $privilege); 598 599 // if current user is owner, return true. owner can do anything! 600 if ($this->UserIsOwner($tag)) return true; 601 602 // fine fine... now go through acl 603 foreach (explode("\n", $acl["list"]) as $line) 604 { 605 $line = trim($line); 606 607 // check for inversion character "!" 608 if (preg_match("/^[!](.*)$/", $line, $matches)) 609 { 610 $negate = 1; 611 $line = $matches[1]; 612 } 613 else 614 { 615 $negate = 0; 616 } 617 618 // if there's still anything left... lines with just a "!" don't count! 619 if ($line) 620 { 621 switch ($line[0]) 622 { 623 // comments 624 case "#": 625 break; 626 // everyone 627 case "*": 628 return !$negate; 629 // aha! a user entry. 630 case "+": 631 if (!$this->LoadUser($user)) 632 { 633 return $negate; 634 } 635 else 636 { 637 return !$negate; 638 } 639 default: 640 if ($line == $user) 641 { 642 return !$negate; 643 } 644 } 645 } 646 } 647 648 // tough luck. 649 return false; 650 } 651 652 653 654 // MAINTENANCE 655 function Maintenance() { 656 // purge referrers 657 $this->PurgeReferrers(); 658 // purge old page revisions 659 $this->PurgePages(); 660 } 661 662 663 664 // THE BIG EVIL NASTY ONE! 665 function Run($tag, $method = "") { 666 if(!($this->GetMicroTime()%3)) $this->Maintenance(); 667 668 $this->ReadInterWikiConfig(); 669 670 // do our stuff! 671 if (!$this->method = trim($method)) $this->method = "show"; 672 if (!$this->tag = trim($tag)) $this->Redirect($this->href("", $this->config["root_page"])); 673 if ((!$this->GetUser() && isset($_COOKIE["name"])) && ($user = $this->LoadUser($_COOKIE["name"], $_COOKIE["password"]))) $this->SetUser($user, $_COOKIE["remember"]); 674 $this->SetPage($this->LoadPage($tag, (isset($_REQUEST["time"]) ? $_REQUEST["time"] :''))); 675 $this->LogReferrer(); 676 677 //correction pour un support plus facile de nouveaux handlers 678 print($this->Method($this->method)); 679 } 680 } 681 682 683 684 // stupid version check 685 if (!isset($_REQUEST)) die('$_REQUEST[] not found. Wakka requires PHP 4.1.0 or higher!'); 686 687 // workaround for the amazingly annoying magic quotes. 688 function magicQuotesSuck(&$a) 689 { 690 if (is_array($a)) 691 { 692 foreach ($a as $k => $v) 693 { 694 if (is_array($v)) 695 magicQuotesSuck($a[$k]); 696 else 697 $a[$k] = stripslashes($v); 698 } 699 } 700 } 701 set_magic_quotes_runtime(0); 702 if (get_magic_quotes_gpc()) 703 { 704 magicQuotesSuck($_POST); 705 magicQuotesSuck($_GET); 706 magicQuotesSuck($_COOKIE); 707 } 708 709 710 // default configuration values 711 $wakkaConfig= array(); 712 $wakkaDefaultConfig = array( 713 'wakka_version' => '', 714 'wikini_version' => '', 715 'debug' => 'no', 716 "mysql_host" => "localhost", 717 "mysql_database" => "wikini", 718 "mysql_user" => "wikini", 719 "mysql_password" => '', 720 "table_prefix" => "wikini_", 721 "root_page" => "PagePrincipale", 722 "wakka_name" => "MonSiteWikiNi", 723 "base_url" => "http://".$_SERVER["SERVER_NAME"].($_SERVER["SERVER_PORT"] != 80 ? ":".$_SERVER["SERVER_PORT"] : "").$_SERVER["REQUEST_URI"].(preg_match("/".preg_quote("wakka.php")."$/", $_SERVER["REQUEST_URI"]) ? "?wiki=" : ""), 724 "rewrite_mode" => (preg_match("/".preg_quote("wakka.php")."$/", $_SERVER["REQUEST_URI"]) ? "0" : "1"), 725 'meta_keywords' => '', 726 'meta_description' => '', 727 "action_path" => "actions", 728 "handler_path" => "handlers", 729 "header_action" => "header", 730 "footer_action" => "footer", 731 "navigation_links" => "DerniersChangements :: DerniersCommentaires :: ParametresUtilisateur", 732 "referrers_purge_time" => 24, 733 "pages_purge_time" => 90, 734 "default_write_acl" => "*", 735 "default_read_acl" => "*", 736 "default_comment_acl" => "*", 737 "preview_before_save" => "0", 738 'allow_raw_html' => false); 739 740 // load config 741 if (!$configfile = GetEnv("WAKKA_CONFIG")) $configfile = "wakka.config.php"; 742 if (file_exists($configfile)) include($configfile); 743 $wakkaConfigLocation = $configfile; 744 $wakkaConfig = array_merge($wakkaDefaultConfig, $wakkaConfig); 745 746 // check for locking 747 if (file_exists("locked")) { 748 // read password from lockfile 749 $lines = file("locked"); 750 $lockpw = trim($lines[0]); 751 752 // is authentification given? 753 if (isset($_SERVER["PHP_AUTH_USER"])) { 754 if (!(($_SERVER["PHP_AUTH_USER"] == "admin") && ($_SERVER["PHP_AUTH_PW"] == $lockpw))) { 755 $ask = 1; 756 } 757 } else { 758 $ask = 1; 759 } 760 761 if ($ask) { 762 header("WWW-Authenticate: Basic realm=\"".$wakkaConfig["wakka_name"]." Install/Upgrade Interface\""); 763 header("HTTP/1.0 401 Unauthorized"); 764 echo "Ce site est en cours de mise à jour. Veuillez essayer plus tard." ; 765 exit; 766 } 767 } 768 769 770 // compare versions, start installer if necessary 771 if ($wakkaConfig["wakka_version"] && (!$wakkaConfig["wikini_version"])) { $wakkaConfig["wikini_version"]=$wakkaConfig["wakka_version"]; } 772 if (($wakkaConfig["wakka_version"] != WAKKA_VERSION) || ($wakkaConfig["wikini_version"] != WIKINI_VERSION)) { 773 // start installer 774 if (!isset($_REQUEST["installAction"]) OR !$installAction = trim($_REQUEST["installAction"])) $installAction = "default"; 775 include ("setup/header.php"); 776 if (file_exists("setup/".$installAction.".php")) include("setup/".$installAction.".php"); else echo "<i>Invalid action</i>" ; 777 include ("setup/footer.php"); 778 exit; 779 } 780 781 782 // configuration du cookie de session 783 //determine le chemin pour le cookie 784 $a = parse_url($wakkaConfig['base_url']); 785 $CookiePath = dirname($a['path']); 786 if ($CookiePath != '/') $CookiePath .= '/'; 787 $a = session_get_cookie_params(); 788 session_set_cookie_params($a['lifetime'],$CookiePath); 789 unset($a); 790 unset($CookiePath); 791 792 // start session 793 session_start(); 794 795 // fetch wakka location 796 if (!isset($_REQUEST["wiki"])) $_REQUEST["wiki"] = ''; 797 798 $wiki = $_REQUEST["wiki"]; 799 800 // remove leading slash 801 $wiki = preg_replace("/^\//", "", $wiki); 802 803 // split into page/method 804 if (preg_match("#^(.+?)/([A-Za-z0-9_]*)$#", $wiki, $matches)) list(, $page, $method) = $matches; 805 else if (preg_match("#^(.*)$#", $wiki, $matches)) list(, $page) = $matches; 806 807 // create wiki object 808 $wiki = new Wiki($wakkaConfig); 809 // check for database access 810 if (!$wiki->dblink) 811 { 812 echo "<p>Pour des raisons indépendantes de notre volonté, le contenu de ce Wiki est temporairement inaccessible. Veuillez réessayer ultérieurement, merci de votre compréhension.</p>"; 813 exit; 814 } 815 816 // Check if the server is configured to automatically compress the output 817 if (!ini_get('zlib.output_compression') && !ini_get('zlib.output_handler')) 818 { 819 // Check if we can use ob_gzhandler (requires the zlib extension) 820 if (function_exists('ob_gzhandler')) 821 { 822 // let ob_gzhandler do the dirty job 823 ob_start('ob_gzhandler'); 824 } 825 // else let do the dirty job ourselves... 826 elseif (!empty($_SERVER['HTTP_ACCEPT_ENCODING']) && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode')) 827 { 828 ob_start ('gzencode'); 829 // Tell the browser the content is compressed with gzip 830 header ("Content-Encoding: gzip"); 831 } 832 } 833 834 835 // go! 836 if (!isset($method)) $method=''; 837 838 // Security (quick hack) : Check method syntax 839 if (!(preg_match('#^[A-Za-z0-9_]*$#',$method))) { 840 $method=''; 841 } 842 843 $wiki->Run($page, $method); 844 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Mon Nov 26 12:05:46 2007 | par Balluche grâce à PHPXref 0.7 |
|