Subversion Repositories Applications.wikini

Rev

Rev 54 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 54 Rev 75
1
<?php
1
<?php
2
/*
2
/*
3
$Id: wakka.php 864 2007-11-28 12:44:52Z nepote $
3
$Id: wakka.php 864 2007-11-28 12:44:52Z nepote $
4
Copyright (c) 2002, Hendrik Mans <hendrik@mans.de>
4
Copyright (c) 2002, Hendrik Mans <hendrik@mans.de>
5
Copyright 2003 Carlo Zottmann
5
Copyright 2003 Carlo Zottmann
6
Copyright 2002, 2003, 2005 David DELON
6
Copyright 2002, 2003, 2005 David DELON
7
Copyright 2002, 2003, 2004, 2006 Charles N?POTE
7
Copyright 2002, 2003, 2004, 2006 Charles N?POTE
8
Copyright 2002, 2003 Patrick PAUL
8
Copyright 2002, 2003 Patrick PAUL
9
Copyright 2003 Eric DELORD
9
Copyright 2003 Eric DELORD
10
Copyright 2003 Eric FELDSTEIN
10
Copyright 2003 Eric FELDSTEIN
11
Copyright 2004-2006 Jean-Christophe ANDR?
11
Copyright 2004-2006 Jean-Christophe ANDR?
12
Copyright 2005-2006 Didier LOISEAU
12
Copyright 2005-2006 Didier LOISEAU
13
All rights reserved.
13
All rights reserved.
14
Redistribution and use in source and binary forms, with or without
14
Redistribution and use in source and binary forms, with or without
15
modification, are permitted provided that the following conditions
15
modification, are permitted provided that the following conditions
16
are met:
16
are met:
17
1. Redistributions of source code must retain the above copyright
17
1. Redistributions of source code must retain the above copyright
18
notice, this list of conditions and the following disclaimer.
18
notice, this list of conditions and the following disclaimer.
19
2. Redistributions in binary form must reproduce the above copyright
19
2. Redistributions in binary form must reproduce the above copyright
20
notice, this list of conditions and the following disclaimer in the
20
notice, this list of conditions and the following disclaimer in the
21
documentation and/or other materials provided with the distribution.
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
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.
23
derived from this software without specific prior written permission.
24
 
24
 
25
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
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
26
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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
31
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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
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.
34
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
 */
35
 */
36
 
36
 
37
/*
37
/*
38
	Yes, most of the formatting used in this file is HORRIBLY BAD STYLE. However,
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
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. :)
40
	to look as small as what it does. Basically. Oh, I just suck. :)
41
 */
41
 */
42
 
42
 
43
 
43
 
44
 
44
 
45
// do not change this line, you fool. In fact, don't change anything! Ever!
45
// do not change this line, you fool. In fact, don't change anything! Ever!
46
define("WAKKA_VERSION", "0.1.1");
46
define("WAKKA_VERSION", "0.1.1");
47
define("WIKINI_VERSION", "0.5.0");
47
define("WIKINI_VERSION", "0.5.0");
48
require 'includes/constants.php';
48
require 'includes/constants.php';
49
include 'includes/urlutils.inc.php';
49
include 'includes/urlutils.inc.php';
50
 
50
 
51
// start the compute time
51
// start the compute time
52
list($g_usec, $g_sec) = explode(" ",microtime());
52
list($g_usec, $g_sec) = explode(" ",microtime());
53
define ("t_start", (float)$g_usec + (float)$g_sec);
53
define ("t_start", (float)$g_usec + (float)$g_sec);
54
$t_SQL=0;
54
$t_SQL=0;
55
 
55
 
56
 
56
 
57
 
57
 
58
class Wiki
58
class Wiki
59
{
59
{
60
	var $dblink;
60
	var $dblink;
61
	var $page;
61
	var $page;
62
	var $tag;
62
	var $tag;
63
	var $parameter = array();
63
	var $parameter = array();
64
	var $queryLog = array();
64
	var $queryLog = array();
65
	var $interWiki = array();
65
	var $interWiki = array();
66
	var $VERSION;
66
	var $VERSION;
67
	var $CookiePath = '/';
67
	var $CookiePath = '/';
68
	var $inclusions = array();
68
	var $inclusions = array();
69
	/**
69
	/**
70
	 * an array containing all the actions that are implemented by an object
70
	 * an array containing all the actions that are implemented by an object
71
	 * @access private
71
	 * @access private
72
	 */
72
	 */
73
	var $actionObjects;
73
	var $actionObjects;
74
 
74
 
75
	// LinkTrackink
75
	// LinkTrackink
76
	var $isTrackingLinks = false;
76
	var $isTrackingLinks = false;
77
	var $linktable = array();
77
	var $linktable = array();
78
 
78
 
79
	var $pageCache = array();
79
	var $pageCache = array();
80
	var $_groupsCache = array();
80
	var $_groupsCache = array();
81
	var $_actionsAclsCache = array();
81
	var $_actionsAclsCache = array();
82
 
82
 
83
	// constructor
83
	// constructor
84
	function Wiki($config)
84
	function Wiki($config)
85
	{
85
	{
86
		$this->config = $config;
86
		$this->config = $config;
87
		// some host do not allow mysql_pconnect
87
		// some host do not allow mysql_pconnect
88
		$this->dblink = @mysql_connect (
88
		$this->dblink = @mysql_connect (
89
			$this->config["mysql_host"],
89
			$this->config["mysql_host"],
90
			$this->config["mysql_user"],
90
			$this->config["mysql_user"],
91
			$this->config["mysql_password"]);
91
			$this->config["mysql_password"]);
92
		if ($this->dblink)
92
		if ($this->dblink)
93
		{
93
		{
94
			if (!@mysql_select_db($this->config["mysql_database"], $this->dblink))
94
			if (!@mysql_select_db($this->config["mysql_database"], $this->dblink))
95
			{
95
			{
96
				@mysql_close($this->dblink);
96
				@mysql_close($this->dblink);
97
				$this->dblink = false;
97
				$this->dblink = false;
98
			}
98
			}
99
		}
99
		}
100
		$this->VERSION = WAKKA_VERSION;
100
		$this->VERSION = WAKKA_VERSION;
101
 
101
 
102
		// determine le chemin pour les cookies
102
		// determine le chemin pour les cookies
103
		$a = parse_url($this->GetConfigValue('base_url'));
103
		$a = parse_url($this->GetConfigValue('base_url'));
104
		$this->CookiePath = dirname($a['path']);
104
		$this->CookiePath = dirname($a['path']);
105
		// Fixe la gestion des cookie sous les OS utilisant le \ comme s?parteur de chemin
105
		// Fixe la gestion des cookie sous les OS utilisant le \ comme s?parteur de chemin
106
		$this->CookiePath = str_replace("\\","/",$this->CookiePath);
106
		$this->CookiePath = str_replace("\\","/",$this->CookiePath);
107
		// ajoute un '/' terminal sauf si on est ? la racine web
107
		// ajoute un '/' terminal sauf si on est ? la racine web
108
		if ($this->CookiePath != '/') $this->CookiePath .= '/';
108
		if ($this->CookiePath != '/') $this->CookiePath .= '/';
109
	}
109
	}
110
 
110
 
111
 
111
 
112
 
112
 
113
	// DATABASE
113
	// DATABASE
114
	function Query($query)
114
	function Query($query)
115
	{
115
	{
116
		if($this->GetConfigValue("debug")) $start = $this->GetMicroTime();
116
		if($this->GetConfigValue("debug")) $start = $this->GetMicroTime();
117
		if (!$result = mysql_query($query, $this->dblink))
117
		if (!$result = mysql_query($query, $this->dblink))
118
		{
118
		{
119
			ob_end_clean();
119
			ob_end_clean();
120
			die("Query failed: ".$query." (".mysql_error().")");
120
			die("Query failed: ".$query." (".mysql_error().")");
121
		}
121
		}
122
		if($this->GetConfigValue("debug"))
122
		if($this->GetConfigValue("debug"))
123
		{
123
		{
124
			$time = $this->GetMicroTime() - $start;
124
			$time = $this->GetMicroTime() - $start;
125
			$this->queryLog[] = array(
125
			$this->queryLog[] = array(
126
				"query"		=> $query,
126
				"query"		=> $query,
127
				"time"		=> $time);
127
				"time"		=> $time);
128
		}
128
		}
129
		return $result;
129
		return $result;
130
	}
130
	}
131
	function LoadSingle($query) {
131
	function LoadSingle($query) {
132
		if ($data = $this->LoadAll($query)) return $data[0];
132
		if ($data = $this->LoadAll($query)) return $data[0];
133
		return null;
133
		return null;
134
	}
134
	}
135
	function LoadAll($query)
135
	function LoadAll($query)
136
	{
136
	{
137
		$data=array();
137
		$data=array();
138
		if ($r = $this->Query($query))
138
		if ($r = $this->Query($query))
139
		{
139
		{
140
			while ($row = mysql_fetch_assoc($r)) $data[] = $row;
140
			while ($row = mysql_fetch_assoc($r)) $data[] = $row;
141
			mysql_free_result($r);
141
			mysql_free_result($r);
142
		}
142
		}
143
		return $data;
143
		return $data;
144
	}
144
	}
145
 
145
 
146
 
146
 
147
 
147
 
148
	// MISC
148
	// MISC
149
	function GetMicroTime()
149
	function GetMicroTime()
150
	{
150
	{
151
		list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec);
151
		list($usec, $sec) = explode(" ",microtime()); return ((float)$usec + (float)$sec);
152
	}
152
	}
153
	function IncludeBuffered($filename, $notfoundText = "", $vars = "", $path = "")
153
	function IncludeBuffered($filename, $notfoundText = "", $vars = "", $path = "")
154
	{
154
	{
155
		if ($path) $dirs = explode(":", $path);
155
		if ($path) $dirs = explode(":", $path);
156
		else $dirs = array("");
156
		else $dirs = array("");
157
 
157
 
158
		foreach($dirs as $dir)
158
		foreach($dirs as $dir)
159
		{
159
		{
160
			if ($dir) $dir .= "/";
160
			if ($dir) $dir .= "/";
161
			$fullfilename = $dir.$filename;
161
			$fullfilename = $dir.$filename;
162
			if (file_exists($fullfilename))
162
			if (file_exists($fullfilename))
163
			{
163
			{
164
				if (is_array($vars)) extract($vars);
164
				if (is_array($vars)) extract($vars);
165
 
165
 
166
				ob_start();
166
				ob_start();
167
				include($fullfilename);
167
				include($fullfilename);
168
				$output = ob_get_contents();
168
				$output = ob_get_contents();
169
				ob_end_clean();
169
				ob_end_clean();
170
				return $output;
170
				return $output;
171
			}
171
			}
172
		}
172
		}
173
		if ($notfoundText) return $notfoundText;
173
		if ($notfoundText) return $notfoundText;
174
		else return false;
174
		else return false;
175
	}
175
	}
176
 
176
 
177
 
177
 
178
 
178
 
179
	// VARIABLES
179
	// VARIABLES
180
	function GetPageTag() { return $this->tag; }
180
	function GetPageTag() { return $this->tag; }
181
	function GetPageTime() { return $this->page["time"]; }
181
	function GetPageTime() { return $this->page["time"]; }
182
	function GetMethod() { return $this->method; }
182
	function GetMethod() { return $this->method; }
183
	function GetConfigValue($name) { return isset($this->config[$name]) ? trim($this->config[$name]) : ''; }
183
	function GetConfigValue($name) { return isset($this->config[$name]) ? trim($this->config[$name]) : ''; }
184
	function GetWakkaName() { return $this->GetConfigValue("wakka_name"); }
184
	function GetWakkaName() { return $this->GetConfigValue("wakka_name"); }
185
	function GetWakkaVersion() { return $this->VERSION; }
185
	function GetWakkaVersion() { return $this->VERSION; }
186
	function GetWikiNiVersion() { return WIKINI_VERSION; }
186
	function GetWikiNiVersion() { return WIKINI_VERSION; }
187
 
187
 
188
	/**
188
	/**
189
	 * Retrieves all the triples that match some criteria.
189
	 * Retrieves all the triples that match some criteria.
190
	 * This allows to search triples by their approximate resource or property names.
190
	 * This allows to search triples by their approximate resource or property names.
191
	 * The allowed operators are the sql LIKE and the sql =
191
	 * The allowed operators are the sql LIKE and the sql =
192
	 * @param string $resource The resource of the triples
192
	 * @param string $resource The resource of the triples
193
	 * @param string $property The property of the triple to retrieve or null
193
	 * @param string $property The property of the triple to retrieve or null
194
	 * @param string $res_op The operator of comparison between the effective resource and $resource (default: 'LIKE')
194
	 * @param string $res_op The operator of comparison between the effective resource and $resource (default: 'LIKE')
195
	 * @param string $prop_op The operator of comparison between the effective property and $property (default: '=')
195
	 * @param string $prop_op The operator of comparison between the effective property and $property (default: '=')
196
	 * @return array The list of all the triples that match the asked criteria 
196
	 * @return array The list of all the triples that match the asked criteria 
197
	 */
197
	 */
198
	function GetMatchingTriples($resource, $property = null, $res_op = 'LIKE', $prop_op = '=')
198
	function GetMatchingTriples($resource, $property = null, $res_op = 'LIKE', $prop_op = '=')
199
	{
199
	{
200
		static $operators = array('=', 'LIKE'); // we might want to add other operators later
200
		static $operators = array('=', 'LIKE'); // we might want to add other operators later
201
		$res_op = strtoupper($res_op);
201
		$res_op = strtoupper($res_op);
202
		if (!in_array($res_op, $operators)) $res_op = '=';
202
		if (!in_array($res_op, $operators)) $res_op = '=';
203
		$sql = 'SELECT * FROM ' . $this->GetConfigValue('table_prefix') . 'triples '
203
		$sql = 'SELECT * FROM ' . $this->GetConfigValue('table_prefix') . 'triples '
204
			. 'WHERE resource ' . $res_op . ' "' . addslashes($resource) . '"';
204
			. 'WHERE resource ' . $res_op . ' "' . addslashes($resource) . '"';
205
		if ($property !== null)
205
		if ($property !== null)
206
		{
206
		{
207
			$prop_op = strtoupper($prop_op);
207
			$prop_op = strtoupper($prop_op);
208
			if (!in_array($prop_op, $operators)) $prop_op = '=';
208
			if (!in_array($prop_op, $operators)) $prop_op = '=';
209
			$sql .= ' AND property ' . $prop_op . ' "' . addslashes($property) . '"';
209
			$sql .= ' AND property ' . $prop_op . ' "' . addslashes($property) . '"';
210
		}
210
		}
211
		return $this->LoadAll($sql);
211
		return $this->LoadAll($sql);
212
	}
212
	}
213
 
213
 
214
	/**
214
	/**
215
	 * Retrieves all the values for a given couple (resource, property)
215
	 * Retrieves all the values for a given couple (resource, property)
216
	 * @param string $resource The resource of the triples
216
	 * @param string $resource The resource of the triples
217
	 * @param string $property The property of the triple to retrieve
217
	 * @param string $property The property of the triple to retrieve
218
	 * @param string $re_prefix The prefix to add to $resource (defaults to THISWIKI_PREFIX)
218
	 * @param string $re_prefix The prefix to add to $resource (defaults to THISWIKI_PREFIX)
219
	 * @param string $prop_prefix The prefix to add to $property (defaults to WIKINI_VOC_PREFIX)
219
	 * @param string $prop_prefix The prefix to add to $property (defaults to WIKINI_VOC_PREFIX)
220
	 * @return array An array of the retrieved values, in the form
220
	 * @return array An array of the retrieved values, in the form
221
	 * array(
221
	 * array(
222
	 * 	0 => array(id = 7 , 'value' => $value1),
222
	 * 	0 => array(id = 7 , 'value' => $value1),
223
	 * 	1 => array(id = 34, 'value' => $value2),
223
	 * 	1 => array(id = 34, 'value' => $value2),
224
	 * 	...
224
	 * 	...
225
	 * )
225
	 * )
226
	 */
226
	 */
227
	function GetAllTriplesValues($resource, $property, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
227
	function GetAllTriplesValues($resource, $property, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
228
	{
228
	{
229
		$sql = 'SELECT id, value FROM ' . $this->GetConfigValue('table_prefix') . 'triples '
229
		$sql = 'SELECT id, value FROM ' . $this->GetConfigValue('table_prefix') . 'triples '
230
			. 'WHERE resource = "' . addslashes($re_prefix . $resource) . '" '
230
			. 'WHERE resource = "' . addslashes($re_prefix . $resource) . '" '
231
			. 'AND property = "' . addslashes($prop_prefix . $property) . '" ';
231
			. 'AND property = "' . addslashes($prop_prefix . $property) . '" ';
232
		return $this->LoadAll($sql);
232
		return $this->LoadAll($sql);
233
	} 
233
	} 
234
 
234
 
235
	/**
235
	/**
236
	 * Retrieves a single value for a given couple (resource, property)
236
	 * Retrieves a single value for a given couple (resource, property)
237
	 * @param string $resource The resource of the triples
237
	 * @param string $resource The resource of the triples
238
	 * @param string $property The property of the triple to retrieve
238
	 * @param string $property The property of the triple to retrieve
239
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
239
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
240
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
240
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
241
	 * @return string The value corresponding to ($resource, $property) or null if
241
	 * @return string The value corresponding to ($resource, $property) or null if
242
	 * there is no such couple in the triples table.
242
	 * there is no such couple in the triples table.
243
	 */
243
	 */
244
	function GetTripleValue($resource, $property, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
244
	function GetTripleValue($resource, $property, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
245
	{
245
	{
246
		$res = $this->GetAllTriplesValues($resource, $property, $re_prefix, $prop_prefix);
246
		$res = $this->GetAllTriplesValues($resource, $property, $re_prefix, $prop_prefix);
247
		if ($res) return $res[0]['value'];
247
		if ($res) return $res[0]['value'];
248
		return null;
248
		return null;
249
	}
249
	}
250
 
250
 
251
	/**
251
	/**
252
	 * Checks whether a triple exists or not
252
	 * Checks whether a triple exists or not
253
	 * @param string $resource The resource of the triple to find
253
	 * @param string $resource The resource of the triple to find
254
	 * @param string $property The property of the triple to find
254
	 * @param string $property The property of the triple to find
255
	 * @param string $value The value of the triple to find
255
	 * @param string $value The value of the triple to find
256
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
256
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
257
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
257
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
258
	 * @param int The id of the found triple or 0 if there is no such triple. 
258
	 * @param int The id of the found triple or 0 if there is no such triple. 
259
	 */
259
	 */
260
	function TripleExists($resource, $property, $value, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
260
	function TripleExists($resource, $property, $value, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
261
	{
261
	{
262
		$sql = 'SELECT id FROM ' . $this->GetConfigValue('table_prefix') . 'triples '
262
		$sql = 'SELECT id FROM ' . $this->GetConfigValue('table_prefix') . 'triples '
263
			. 'WHERE resource = "' . addslashes($re_prefix . $resource) . '" '
263
			. 'WHERE resource = "' . addslashes($re_prefix . $resource) . '" '
264
			. 'AND property = "' . addslashes($prop_prefix . $property) . '" '
264
			. 'AND property = "' . addslashes($prop_prefix . $property) . '" '
265
			. 'AND value = "' . addslashes($value) . '"';
265
			. 'AND value = "' . addslashes($value) . '"';
266
		$res = $this->LoadSingle($sql);
266
		$res = $this->LoadSingle($sql);
267
		if (!$res) return 0;
267
		if (!$res) return 0;
268
		return $res['id'];
268
		return $res['id'];
269
	}
269
	}
270
 
270
 
271
	/**
271
	/**
272
	 * Inserts a new triple ($resource, $property, $value) in the triples' table
272
	 * Inserts a new triple ($resource, $property, $value) in the triples' table
273
	 * @param string $resource The resource of the triple to insert
273
	 * @param string $resource The resource of the triple to insert
274
	 * @param string $property The property of the triple to insert
274
	 * @param string $property The property of the triple to insert
275
	 * @param string $value The value of the triple to insert
275
	 * @param string $value The value of the triple to insert
276
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
276
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
277
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
277
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
278
	 * @return int An error code: 0 (success), 1 (failure) or 3 (already exists)
278
	 * @return int An error code: 0 (success), 1 (failure) or 3 (already exists)
279
	 */
279
	 */
280
	function InsertTriple($resource, $property, $value, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
280
	function InsertTriple($resource, $property, $value, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
281
	{
281
	{
282
		if ($this->TripleExists($resource, $property, $value, $re_prefix, $prop_prefix))
282
		if ($this->TripleExists($resource, $property, $value, $re_prefix, $prop_prefix))
283
		{
283
		{
284
			return 3;
284
			return 3;
285
		}
285
		}
286
		$sql = 'INSERT INTO ' . $this->GetConfigValue('table_prefix') . 'triples (resource, property, value)'
286
		$sql = 'INSERT INTO ' . $this->GetConfigValue('table_prefix') . 'triples (resource, property, value)'
287
			. 'VALUES ("' . addslashes($re_prefix . $resource) . '", "'
287
			. 'VALUES ("' . addslashes($re_prefix . $resource) . '", "'
288
				. addslashes($prop_prefix . $property) . '", "'
288
				. addslashes($prop_prefix . $property) . '", "'
289
				. addslashes($value) . '")';
289
				. addslashes($value) . '")';
290
		return $this->Query($sql) ? 0 : 1;
290
		return $this->Query($sql) ? 0 : 1;
291
	}
291
	}
292
 
292
 
293
	/**
293
	/**
294
	 * Updates a triple ($resource, $property, $value) in the triples' table
294
	 * Updates a triple ($resource, $property, $value) in the triples' table
295
	 * @param string $resource The resource of the triple to update
295
	 * @param string $resource The resource of the triple to update
296
	 * @param string $property The property of the triple to update
296
	 * @param string $property The property of the triple to update
297
	 * @param string $oldvalue The old value of the triple to update
297
	 * @param string $oldvalue The old value of the triple to update
298
	 * @param string $newvalue The new value of the triple to update
298
	 * @param string $newvalue The new value of the triple to update
299
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
299
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
300
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
300
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
301
	 * @return int An error code: 0 (succ?s), 1 (?chec),
301
	 * @return int An error code: 0 (succ?s), 1 (?chec),
302
	 * 		2 ($resource, $property, $oldvalue does not exist)
302
	 * 		2 ($resource, $property, $oldvalue does not exist)
303
	 * 		or 3 ($resource, $property, $newvalue already exists)
303
	 * 		or 3 ($resource, $property, $newvalue already exists)
304
	 */
304
	 */
305
	function UpdateTriple($resource, $property, $oldvalue, $newvalue, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
305
	function UpdateTriple($resource, $property, $oldvalue, $newvalue, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
306
	{
306
	{
307
		$id = $this->TripleExists($resource, $property, $oldvalue, $re_prefix, $prop_prefix);
307
		$id = $this->TripleExists($resource, $property, $oldvalue, $re_prefix, $prop_prefix);
308
		if (!$id) return 2;
308
		if (!$id) return 2;
309
		if ($this->TripleExists($resource, $property, $newvalue, $re_prefix, $prop_prefix))
309
		if ($this->TripleExists($resource, $property, $newvalue, $re_prefix, $prop_prefix))
310
		{
310
		{
311
			return 3;
311
			return 3;
312
		}
312
		}
313
		$sql = 'UPDATE ' . $this->GetConfigValue('table_prefix') . 'triples '
313
		$sql = 'UPDATE ' . $this->GetConfigValue('table_prefix') . 'triples '
314
			. 'SET value = "' . addslashes($newvalue) . '" '
314
			. 'SET value = "' . addslashes($newvalue) . '" '
315
			. 'WHERE id = ' . $id;
315
			. 'WHERE id = ' . $id;
316
		return $this->Query($sql) ? 0 : 1;
316
		return $this->Query($sql) ? 0 : 1;
317
	}
317
	}
318
 
318
 
319
	/**
319
	/**
320
	 * Deletes a triple ($resource, $property, $value) from the triples' table
320
	 * Deletes a triple ($resource, $property, $value) from the triples' table
321
	 * @param string $resource The resource of the triple to delete
321
	 * @param string $resource The resource of the triple to delete
322
	 * @param string $property The property of the triple to delete
322
	 * @param string $property The property of the triple to delete
323
	 * @param string $value The value of the triple to delete. If set to <tt>null</tt>,
323
	 * @param string $value The value of the triple to delete. If set to <tt>null</tt>,
324
	 * deletes all the triples corresponding to ($resource, $property). (defaults to <tt>null</tt>)
324
	 * deletes all the triples corresponding to ($resource, $property). (defaults to <tt>null</tt>)
325
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
325
	 * @param string $re_prefix The prefix to add to $resource (defaults to <tt>THISWIKI_PREFIX</tt>)
326
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
326
	 * @param string $prop_prefix The prefix to add to $property (defaults to <tt>WIKINI_VOC_PREFIX</tt>)
327
	 */
327
	 */
328
	function DeleteTriple($resource, $property, $value = null, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
328
	function DeleteTriple($resource, $property, $value = null, $re_prefix = THISWIKI_PREFIX, $prop_prefix = WIKINI_VOC_PREFIX)
329
	{
329
	{
330
		$sql = 'DELETE FROM ' . $this->GetConfigValue('table_prefix') . 'triples '
330
		$sql = 'DELETE FROM ' . $this->GetConfigValue('table_prefix') . 'triples '
331
			. 'WHERE resource = "' . addslashes($re_prefix . $resource) . '" '
331
			. 'WHERE resource = "' . addslashes($re_prefix . $resource) . '" '
332
			. 'AND property = "' . addslashes($prop_prefix . $property) . '" ';
332
			. 'AND property = "' . addslashes($prop_prefix . $property) . '" ';
333
		if ($value !== null) $sql .= 'AND value = "' . addslashes($value) . '"';
333
		if ($value !== null) $sql .= 'AND value = "' . addslashes($value) . '"';
334
		$this->Query($sql);
334
		$this->Query($sql);
335
	}
335
	}
336
 
336
 
337
	// inclusions
337
	// inclusions
338
	/**
338
	/**
339
	 * Enr?gistre une nouvelle inclusion dans la pile d'inclusions.
339
	 * Enr?gistre une nouvelle inclusion dans la pile d'inclusions.
340
	 * 
340
	 * 
341
	 * @param string $pageTag Le nom de la page qui va ?tre inclue
341
	 * @param string $pageTag Le nom de la page qui va ?tre inclue
342
	 * @return int Le nombre d'?l?ments dans la pile
342
	 * @return int Le nombre d'?l?ments dans la pile
343
	 */
343
	 */
344
	function RegisterInclusion($pageTag)
344
	function RegisterInclusion($pageTag)
345
	{
345
	{
346
		return array_unshift($this->inclusions, strtolower(trim($pageTag)));
346
		return array_unshift($this->inclusions, strtolower(trim($pageTag)));
347
	} 
347
	} 
348
	/**
348
	/**
349
	 * Retire le dernier ?l?ment de la pile d'inclusions.
349
	 * Retire le dernier ?l?ment de la pile d'inclusions.
350
	 * 
350
	 * 
351
	 * @return string Le nom de la page dont l'inclusion devrait se terminer.
351
	 * @return string Le nom de la page dont l'inclusion devrait se terminer.
352
	 * null s'il n'y a plus d'inclusion dans la pile.
352
	 * null s'il n'y a plus d'inclusion dans la pile.
353
	 */
353
	 */
354
	function UnregisterLastInclusion()
354
	function UnregisterLastInclusion()
355
	{
355
	{
356
		return array_shift($this->inclusions);
356
		return array_shift($this->inclusions);
357
	} 
357
	} 
358
	/**
358
	/**
359
	 * Renvoie le nom de la page en cours d'inclusion.
359
	 * Renvoie le nom de la page en cours d'inclusion.
360
	 * 
360
	 * 
361
	 * @example // dans le cas d'une action comme l'ActionEcrivezMoi
361
	 * @example // dans le cas d'une action comme l'ActionEcrivezMoi
362
	 * if($inc = $this->CurrentInclusion() && strtolower($this->GetPageTag()) != $inc)
362
	 * if($inc = $this->CurrentInclusion() && strtolower($this->GetPageTag()) != $inc)
363
	 * 	echo 'Cette action ne peut ?tre appel?e depuis une page inclue';
363
	 * 	echo 'Cette action ne peut ?tre appel?e depuis une page inclue';
364
	 * @return string Le nom (tag) de la page (en minuscules)
364
	 * @return string Le nom (tag) de la page (en minuscules)
365
	 * false si la pile est vide.
365
	 * false si la pile est vide.
366
	 */
366
	 */
367
	function GetCurrentInclusion()
367
	function GetCurrentInclusion()
368
	{
368
	{
369
		return isset($this->inclusions[0]) ? $this->inclusions[0]: false ;
369
		return isset($this->inclusions[0]) ? $this->inclusions[0]: false ;
370
	} 
370
	} 
371
	/**
371
	/**
372
	 * V?rifie si on est ? l'int?rieur d'une inclusion par $pageTag (sans tenir compte de la casse)
372
	 * V?rifie si on est ? l'int?rieur d'une inclusion par $pageTag (sans tenir compte de la casse)
373
	 * 
373
	 * 
374
	 * @param string $pageTag Le nom de la page ? v?rifier
374
	 * @param string $pageTag Le nom de la page ? v?rifier
375
	 * @return bool True si on est ? l'int?rieur d'une inclusion par $pageTag (false sinon)
375
	 * @return bool True si on est ? l'int?rieur d'une inclusion par $pageTag (false sinon)
376
	 */
376
	 */
377
	function IsIncludedBy($pageTag)
377
	function IsIncludedBy($pageTag)
378
	{
378
	{
379
		return in_array(strtolower($pageTag), $this->inclusions);
379
		return in_array(strtolower($pageTag), $this->inclusions);
380
	} 
380
	} 
381
	/**
381
	/**
382
	 * 
382
	 * 
383
	 * @return array La pile d'inclusions
383
	 * @return array La pile d'inclusions
384
	 * L'?l?ment 0 sera la derni?re inclusion, l'?l?ment 1 sera son parent et ainsi de suite.
384
	 * L'?l?ment 0 sera la derni?re inclusion, l'?l?ment 1 sera son parent et ainsi de suite.
385
	 */
385
	 */
386
	function GetAllInclusions()
386
	function GetAllInclusions()
387
	{
387
	{
388
		return $this->inclusions;
388
		return $this->inclusions;
389
	} 
389
	} 
390
	/**
390
	/**
391
	 * Remplace la pile des inclusions par une nouvelle pile (par d?faut une pile vide)
391
	 * Remplace la pile des inclusions par une nouvelle pile (par d?faut une pile vide)
392
	 * Permet de formatter une page sans tenir compte des inclusions pr?c?dentes.
392
	 * Permet de formatter une page sans tenir compte des inclusions pr?c?dentes.
393
	 * 
393
	 * 
394
	 * @param array $ La nouvelle pile d'inclusions.
394
	 * @param array $ La nouvelle pile d'inclusions.
395
	 * L'?l?ment 0 doit repr?senter la derni?re inclusion, l'?l?ment 1 son parent et ainsi de suite.
395
	 * L'?l?ment 0 doit repr?senter la derni?re inclusion, l'?l?ment 1 son parent et ainsi de suite.
396
	 * @return array L'ancienne pile d'inclusions, avec les noms des pages en minuscules.
396
	 * @return array L'ancienne pile d'inclusions, avec les noms des pages en minuscules.
397
	 */
397
	 */
398
	function SetInclusions($pile = array())
398
	function SetInclusions($pile = array())
399
	{
399
	{
400
		$temp = $this->inclusions;
400
		$temp = $this->inclusions;
401
		$this->inclusions = $pile;
401
		$this->inclusions = $pile;
402
		return $temp;
402
		return $temp;
403
	} 
403
	} 
404
 
404
 
405
	// PAGES
405
	// PAGES
406
	function LoadPage($tag, $time = "", $cache = 1)
406
	function LoadPage($tag, $time = "", $cache = 1)
407
	{
407
	{
408
		// retrieve from cache
408
		// retrieve from cache
409
		if (!$time && $cache && (($cachedPage = $this->GetCachedPage($tag)) !== false))
409
		if (!$time && $cache && (($cachedPage = $this->GetCachedPage($tag)) !== false))
410
		{
410
		{
411
			$page = $cachedPage;
411
			$page = $cachedPage;
412
		}
412
		}
413
		else // load page
413
		else // load page
414
		{
414
		{
415
			$sql = "SELECT * FROM ".$this->config["table_prefix"]."pages"
415
			$sql = "SELECT * FROM ".$this->config["table_prefix"]."pages"
416
				. " WHERE tag = '".mysql_real_escape_string($tag)."' AND "
416
				. " WHERE tag = '".mysql_real_escape_string($tag)."' AND "
417
				. ($time ? "time = '".mysql_real_escape_string($time)."'" : "latest = 'Y'") . " LIMIT 1";
417
				. ($time ? "time = '".mysql_real_escape_string($time)."'" : "latest = 'Y'") . " LIMIT 1";
418
			$page = $this->LoadSingle($sql);
418
			$page = $this->LoadSingle($sql);
419
			// cache result
419
			// cache result
420
			if (!$time) $this->CachePage($page, $tag);
420
			if (!$time) $this->CachePage($page, $tag);
421
		}
421
		}
422
		return $page;
422
		return $page;
423
	}
423
	}
424
	/**
424
	/**
425
	 * Retrieves the cached version of a page.
425
	 * Retrieves the cached version of a page.
426
	 *
426
	 *
427
	 * Notice that this method null or false, use
427
	 * Notice that this method null or false, use
428
	 * 	$this->GetCachedPage($tag) === false
428
	 * 	$this->GetCachedPage($tag) === false
429
	 * to check if a page is not in the cache.
429
	 * to check if a page is not in the cache.
430
	 * @return mixed The cached version of a page:
430
	 * @return mixed The cached version of a page:
431
	 * 	- the page DB line if the page exists and is in cache
431
	 * 	- the page DB line if the page exists and is in cache
432
	 * 	- null if the cache knows that the page does not exists
432
	 * 	- null if the cache knows that the page does not exists
433
	 * 	- false is the cache does not know the page
433
	 * 	- false is the cache does not know the page
434
	 */
434
	 */
435
	function GetCachedPage($tag) {return (array_key_exists($tag, $this->pageCache) ? $this->pageCache[$tag] : false); }
435
	function GetCachedPage($tag) {return (array_key_exists($tag, $this->pageCache) ? $this->pageCache[$tag] : false); }
436
	/**
436
	/**
437
	 * Caches a page's DB line.
437
	 * Caches a page's DB line.
438
	 *
438
	 *
439
	 * @param array $page The page (full) DB line or null if the page does not exists
439
	 * @param array $page The page (full) DB line or null if the page does not exists
440
	 * @param string $pageTag The tag of the page to cache. Defaults to $page['tag'] but is mendatory when $page === null
440
	 * @param string $pageTag The tag of the page to cache. Defaults to $page['tag'] but is mendatory when $page === null
441
	 */
441
	 */
442
	function CachePage($page, $pageTag = null) {
442
	function CachePage($page, $pageTag = null) {
443
		if ($pageTag === null)
443
		if ($pageTag === null)
444
		{
444
		{
445
			$pageTag = $page["tag"];
445
			$pageTag = $page["tag"];
446
		}
446
		}
447
		$this->pageCache[$pageTag] = $page;
447
		$this->pageCache[$pageTag] = $page;
448
	}
448
	}
449
	function SetPage($page) { $this->page = $page; if ($this->page["tag"]) $this->tag = $this->page["tag"]; }
449
	function SetPage($page) { $this->page = $page; if ($this->page["tag"]) $this->tag = $this->page["tag"]; }
450
	function LoadPageById($id) { return $this->LoadSingle("select * from ".$this->config["table_prefix"]."pages where id = '".mysql_real_escape_string($id)."' limit 1"); }
450
	function LoadPageById($id) { return $this->LoadSingle("select * from ".$this->config["table_prefix"]."pages where id = '".mysql_real_escape_string($id)."' limit 1"); }
451
	function LoadRevisions($page) { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where tag = '".mysql_real_escape_string($page)."' order by time desc"); }
451
	function LoadRevisions($page) { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where tag = '".mysql_real_escape_string($page)."' order by time desc"); }
452
	function LoadPagesLinkingTo($tag) { return $this->LoadAll("select from_tag as tag from ".$this->config["table_prefix"]."links where to_tag = '".mysql_real_escape_string($tag)."' order by tag"); }
452
	function LoadPagesLinkingTo($tag) { return $this->LoadAll("select from_tag as tag from ".$this->config["table_prefix"]."links where to_tag = '".mysql_real_escape_string($tag)."' order by tag"); }
453
	function LoadRecentlyChanged($limit=50)
453
	function LoadRecentlyChanged($limit=50)
454
	{
454
	{
455
		$limit= (int) $limit;
455
		$limit= (int) $limit;
456
		if ($pages = $this->LoadAll("select id, tag, time, user, owner from ".$this->config["table_prefix"]."pages where latest = 'Y' and comment_on = '' order by time desc limit $limit"))
456
		if ($pages = $this->LoadAll("select id, tag, time, user, owner from ".$this->config["table_prefix"]."pages where latest = 'Y' and comment_on = '' order by time desc limit $limit"))
457
		{
457
		{
458
			foreach ($pages as $page)
458
			foreach ($pages as $page)
459
			{
459
			{
460
				$this->CachePage($page);
460
				$this->CachePage($page);
461
			}
461
			}
462
			return $pages;
462
			return $pages;
463
		}
463
		}
464
	}
464
	}
465
	function LoadAllPages() { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where latest = 'Y' order by tag"); }
465
	function LoadAllPages() { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where latest = 'Y' order by tag"); }
466
	function FullTextSearch($phrase) { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where latest = 'Y' and match(tag, body) against('".mysql_real_escape_string($phrase)."')"); }
466
	function FullTextSearch($phrase) { return $this->LoadAll("select * from ".$this->config["table_prefix"]."pages where latest = 'Y' and match(tag, body) against('".mysql_real_escape_string($phrase)."')"); }
467
	function LoadWantedPages() {
467
	function LoadWantedPages() {
468
		$p = $this->config["table_prefix"];
468
		$p = $this->config["table_prefix"];
469
		$r = "SELECT ${p}links.to_tag AS tag, COUNT(${p}links.from_tag) AS count "
469
		$r = "SELECT ${p}links.to_tag AS tag, COUNT(${p}links.from_tag) AS count "
470
			. "FROM ${p}links LEFT JOIN ${p}pages ON ${p}links.to_tag = ${p}pages.tag "
470
			. "FROM ${p}links LEFT JOIN ${p}pages ON ${p}links.to_tag = ${p}pages.tag "
471
			. "WHERE ${p}pages.tag IS NULL GROUP BY ${p}links.to_tag ORDER BY count DESC, tag ASC";
471
			. "WHERE ${p}pages.tag IS NULL GROUP BY ${p}links.to_tag ORDER BY count DESC, tag ASC";
472
		return $this->LoadAll($r);
472
		return $this->LoadAll($r);
473
	}
473
	}
474
	function LoadOrphanedPages() { return $this->LoadAll("select distinct tag from ".$this->config["table_prefix"]."pages as p left join ".$this->config["table_prefix"]."links as l on p.tag = l.to_tag where l.to_tag is NULL and p.comment_on = '' and p.latest = 'Y' order by tag"); }
474
	function LoadOrphanedPages() { return $this->LoadAll("select distinct tag from ".$this->config["table_prefix"]."pages as p left join ".$this->config["table_prefix"]."links as l on p.tag = l.to_tag where l.to_tag is NULL and p.comment_on = '' and p.latest = 'Y' order by tag"); }
475
	function IsOrphanedPage($tag) { return $this->LoadAll("select distinct tag from ".$this->config['table_prefix']."pages as p left join ".$this->config['table_prefix']."links as l on p.tag = l.to_tag where l.to_tag is NULL and p.latest = 'Y' and tag = '".mysql_real_escape_string($tag)."'"); }
475
	function IsOrphanedPage($tag) { return $this->LoadAll("select distinct tag from ".$this->config['table_prefix']."pages as p left join ".$this->config['table_prefix']."links as l on p.tag = l.to_tag where l.to_tag is NULL and p.latest = 'Y' and tag = '".mysql_real_escape_string($tag)."'"); }
476
	function DeleteOrphanedPage($tag) {
476
	function DeleteOrphanedPage($tag) {
477
		$p = $this->config["table_prefix"];
477
		$p = $this->config["table_prefix"];
478
		$this->Query("DELETE FROM ${p}pages WHERE tag='".mysql_real_escape_string($tag)."' OR comment_on='".mysql_real_escape_string($tag)."'");
478
		$this->Query("DELETE FROM ${p}pages WHERE tag='".mysql_real_escape_string($tag)."' OR comment_on='".mysql_real_escape_string($tag)."'");
479
		$this->Query("DELETE FROM ${p}links WHERE from_tag='".mysql_real_escape_string($tag)."' ");
479
		$this->Query("DELETE FROM ${p}links WHERE from_tag='".mysql_real_escape_string($tag)."' ");
480
		$this->Query("DELETE FROM ${p}acls WHERE page_tag='".mysql_real_escape_string($tag)."' ");
480
		$this->Query("DELETE FROM ${p}acls WHERE page_tag='".mysql_real_escape_string($tag)."' ");
481
		$this->Query("DELETE FROM ${p}referrers WHERE page_tag='".mysql_real_escape_string($tag)."' ");
481
		$this->Query("DELETE FROM ${p}referrers WHERE page_tag='".mysql_real_escape_string($tag)."' ");
482
	}
482
	}
483
 
483
 
484
	/**
484
	/**
485
	 * SavePage
485
	 * SavePage
486
	 * Sauvegarde un contenu dans une page donn?e
486
	 * Sauvegarde un contenu dans une page donn?e
487
	 *
487
	 *
488
	 * @param string $body Contenu ? sauvegarder dans la page
488
	 * @param string $body Contenu ? sauvegarder dans la page
489
	 * @param string $tag Nom de la page
489
	 * @param string $tag Nom de la page
490
	 * @param string $comment_on Indication si c'est un commentaire
490
	 * @param string $comment_on Indication si c'est un commentaire
491
	 * @param boolean $bypass_acls Indication si on bypasse les droits d'?criture
491
	 * @param boolean $bypass_acls Indication si on bypasse les droits d'?criture
492
	 * @return int Code d'erreur : 0 (succ?s), 1 (l'utilisateur n'a pas les droits)
492
	 * @return int Code d'erreur : 0 (succ?s), 1 (l'utilisateur n'a pas les droits)
493
	 */	
493
	 */	
494
	function SavePage($tag, $body, $comment_on = "", $bypass_acls = false)
494
	function SavePage($tag, $body, $comment_on = "", $bypass_acls = false)
495
	{
495
	{
496
		// get current user
496
		// get current user
497
		$user = $this->GetUserName();
497
		$user = $this->GetUserName();
498
 
498
 
499
		// check bypass of rights or write privilege
499
		// check bypass of rights or write privilege
500
		$rights = $bypass_acls || ($comment_on ? $this->HasAccess("comment", $comment_on) : $this->HasAccess("write", $tag));
500
		$rights = $bypass_acls || ($comment_on ? $this->HasAccess("comment", $comment_on) : $this->HasAccess("write", $tag));
501
			
-
 
502
		if ($rights)
501
		if ($rights)
503
		{
502
		{
504
			// is page new?
503
			// is page new?
505
			if (!$oldPage = $this->LoadPage($tag))
504
			if (!$oldPage = $this->LoadPage($tag))
506
			{
505
			{
507
				// create default write acl. store empty write ACL for comments.
506
				// create default write acl. store empty write ACL for comments.
508
				$this->SaveAcl($tag, "write", ($comment_on ? $user : $this->GetConfigValue("default_write_acl")));
507
				$this->SaveAcl($tag, "write", ($comment_on ? $user : $this->GetConfigValue("default_write_acl")));
509
 
508
 
510
				// create default read acl
509
				// create default read acl
511
				$this->SaveAcl($tag, "read", $this->GetConfigValue("default_read_acl"));
510
				$this->SaveAcl($tag, "read", $this->GetConfigValue("default_read_acl"));
512
 
511
 
513
				// create default comment acl.
512
				// create default comment acl.
514
				$this->SaveAcl($tag, "comment", ($comment_on ? "" : $this->GetConfigValue("default_comment_acl")));
513
				$this->SaveAcl($tag, "comment", ($comment_on ? "" : $this->GetConfigValue("default_comment_acl")));
515
 
514
 
516
				// current user is owner; if user is logged in! otherwise, no owner.
515
				// current user is owner; if user is logged in! otherwise, no owner.
517
				if ($this->GetUser()) $owner = $user;
516
				if ($this->GetUser()) $owner = $user;
518
				else $owner = '';
517
				else $owner = '';
519
			}
518
			}
520
			else
519
			else
521
			{
520
			{
522
				// aha! page isn't new. keep owner!
521
				// aha! page isn't new. keep owner!
523
				$owner = $oldPage["owner"];
522
				$owner = $oldPage["owner"];
524
 
523
 
525
				// ...and comment_on, eventualy?
524
				// ...and comment_on, eventualy?
526
				if ($comment_on == '') $comment_on = $oldPage['comment_on'];
525
				if ($comment_on == '') $comment_on = $oldPage['comment_on'];
527
			}
526
			}
528
 
527
 
529
 
528
 
530
			// set all other revisions to old
529
			// set all other revisions to old
531
			$this->Query("update ".$this->config["table_prefix"]."pages set latest = 'N' where tag = '".mysql_real_escape_string($tag)."'");
530
			$this->Query("update ".$this->config["table_prefix"]."pages set latest = 'N' where tag = '".mysql_real_escape_string($tag)."'");
532
 
531
 
533
			// add new revision
532
			// add new revision
534
			$this->Query("insert into ".$this->config["table_prefix"]."pages set ".
533
			$this->Query("insert into ".$this->config["table_prefix"]."pages set ".
535
				"tag = '".mysql_real_escape_string($tag)."', ".
534
				"tag = '".mysql_real_escape_string($tag)."', ".
536
				($comment_on ? "comment_on = '".mysql_real_escape_string($comment_on)."', " : "").
535
				($comment_on ? "comment_on = '".mysql_real_escape_string($comment_on)."', " : "").
537
				"time = now(), ".
536
				"time = now(), ".
538
				"owner = '".mysql_real_escape_string($owner)."', ".
537
				"owner = '".mysql_real_escape_string($owner)."', ".
539
				"user = '".mysql_real_escape_string($user)."', ".
538
				"user = '".mysql_real_escape_string($user)."', ".
540
				"latest = 'Y', ".
539
				"latest = 'Y', ".
541
				"body = '".mysql_real_escape_string(chop($body))."'");
540
				"body = '".mysql_real_escape_string(chop($body))."'");
542
 
541
 
543
			unset($this->pageCache[$tag]);
542
			unset($this->pageCache[$tag]);
544
			return 0;
543
			return 0;
545
		}
544
		}
546
		else return 1;
545
		else return 1;
547
	}
546
	}
548
 
547
 
549
	
548
	
550
	/**
549
	/**
551
	 * AppendContentToPage
550
	 * AppendContentToPage
552
	 * Ajoute du contenu ? la fin d'une page
551
	 * Ajoute du contenu ? la fin d'une page
553
	 *
552
	 *
554
	 * @param string $content Contenu ? ajouter ? la page
553
	 * @param string $content Contenu ? ajouter ? la page
555
	 * @param string $page Nom de la page
554
	 * @param string $page Nom de la page
556
	 * @param boolean $bypass_acls Boul?en pour savoir s'il faut bypasser les ACLs
555
	 * @param boolean $bypass_acls Boul?en pour savoir s'il faut bypasser les ACLs
557
	 * @return int Code d'erreur : 0 (succ?s), 1 (pas de contenu sp?cifi?)
556
	 * @return int Code d'erreur : 0 (succ?s), 1 (pas de contenu sp?cifi?)
558
	 */
557
	 */
559
	function AppendContentToPage($content, $page, $bypass_acls = false)
558
	function AppendContentToPage($content, $page, $bypass_acls = false)
560
	{
559
	{
561
		// Si un contenu est sp?cifi?
560
		// Si un contenu est sp?cifi?
562
		if (isset($content))
561
		if (isset($content))
563
		{
562
		{
564
			// -- D?termine quelle est la page :
563
			// -- D?termine quelle est la page :
565
			//    -- pass?e en param?tre (que se passe-t'il si elle n'existe pas ?)
564
			//    -- pass?e en param?tre (que se passe-t'il si elle n'existe pas ?)
566
			//    -- ou la page en cours par d?faut
565
			//    -- ou la page en cours par d?faut
567
			$page = isset($page) ? $page : $this->GetPageTag();
566
			$page = isset($page) ? $page : $this->GetPageTag();
568
 
567
 
569
			// -- Chargement de la page
568
			// -- Chargement de la page
570
			$result = $this->LoadPage($page);
569
			$result = $this->LoadPage($page);
571
			$body = $result['body'];
570
			$body = $result['body'];
572
			// -- Ajout du contenu ? la fin de la page
571
			// -- Ajout du contenu ? la fin de la page
573
			$body .= $content;
572
			$body .= $content;
574
 
573
 
575
			// -- Sauvegarde de la page
574
			// -- Sauvegarde de la page
576
			// TODO : que se passe-t-il si la page est pleine ou si l'utilisateur n'a pas les droits ?
575
			// TODO : que se passe-t-il si la page est pleine ou si l'utilisateur n'a pas les droits ?
577
			$this->SavePage($page, $body, "", $bypass_acls);
576
			$this->SavePage($page, $body, "", $bypass_acls);
578
			
577
			
579
			// now we render it internally so we can write the updated link table.
578
			// now we render it internally so we can write the updated link table.
580
			$this->ClearLinkTable();
579
			$this->ClearLinkTable();
581
			$this->StartLinkTracking();
580
			$this->StartLinkTracking();
582
			$temp = $this->SetInclusions();
581
			$temp = $this->SetInclusions();
583
			$this->RegisterInclusion($this->GetPageTag()); // on simule totalement un affichage normal
582
			$this->RegisterInclusion($this->GetPageTag()); // on simule totalement un affichage normal
584
			$this->Format($body);
583
			$this->Format($body);
585
			$this->SetInclusions($temp);
584
			$this->SetInclusions($temp);
586
			if($user = $this->GetUser())
585
			if($user = $this->GetUser())
587
			{
586
			{
588
				$this->TrackLinkTo($user['name']);
587
				$this->TrackLinkTo($user['name']);
589
			}
588
			}
590
			if($owner = $this->GetPageOwner())
589
			if($owner = $this->GetPageOwner())
591
			{
590
			{
592
				$this->TrackLinkTo($owner);
591
				$this->TrackLinkTo($owner);
593
			}
592
			}
594
			$this->StopLinkTracking();
593
			$this->StopLinkTracking();
595
			$this->WriteLinkTable();
594
			$this->WriteLinkTable();
596
			$this->ClearLinkTable();/**/
595
			$this->ClearLinkTable();/**/
597
 
596
 
598
			// Retourne 0 seulement si tout c'est bien pass?
597
			// Retourne 0 seulement si tout c'est bien pass?
599
			return 0;
598
			return 0;
600
		}
599
		}
601
		else return 1;
600
		else return 1;
602
	}
601
	}
603
	
602
	
604
	/**
603
	/**
605
	 * LogAdministrativeAction($user, $content, $page = "")
604
	 * LogAdministrativeAction($user, $content, $page = "")
606
	 * 
605
	 * 
607
	 * @param string $user Utilisateur
606
	 * @param string $user Utilisateur
608
	 * @param string $content Contenu de l'enregistrement
607
	 * @param string $content Contenu de l'enregistrement
609
	 * @param string $page Page de log
608
	 * @param string $page Page de log
610
	 * 
609
	 * 
611
	 * @return int Code d'erreur : 0 (succ?s), 1 (pas de contenu sp?cifi?)
610
	 * @return int Code d'erreur : 0 (succ?s), 1 (pas de contenu sp?cifi?)
612
	 */
611
	 */
613
	function LogAdministrativeAction($user, $content, $page = "")
612
	function LogAdministrativeAction($user, $content, $page = "")
614
	{
613
	{
615
		$order   = array("\r\n", "\n", "\r");
614
		$order   = array("\r\n", "\n", "\r");
616
		$replace = '\\n';
615
		$replace = '\\n';
617
		$content = str_replace($order, $replace, $content);
616
		$content = str_replace($order, $replace, $content);
618
		$contentToAppend = "\n" . date("Y-m-d H:i:s") . " . . . . " . $user . " . . . . " . $content . "\n";
617
		$contentToAppend = "\n" . date("Y-m-d H:i:s") . " . . . . " . $user . " . . . . " . $content . "\n";
619
		$page = $page ? $page : "LogDesActionsAdministratives" . date("Ymd");
618
		$page = $page ? $page : "LogDesActionsAdministratives" . date("Ymd");
620
		return $this->AppendContentToPage($contentToAppend, $page, true);
619
		return $this->AppendContentToPage($contentToAppend, $page, true);
621
	}
620
	}
622
 
621
 
623
	
622
	
624
	/**
623
	/**
625
	 * Make the purge of page versions that are older than the last version older than 3 "pages_purge_time"
624
	 * Make the purge of page versions that are older than the last version older than 3 "pages_purge_time"
626
	 * This method permits to allways keep a version that is older than that period.
625
	 * This method permits to allways keep a version that is older than that period.
627
	 */
626
	 */
628
	function PurgePages() {
627
	function PurgePages() {
629
		if ($days = $this->GetConfigValue("pages_purge_time")) { // is purge active ?
628
		if ($days = $this->GetConfigValue("pages_purge_time")) { // is purge active ?
630
			// let's search which pages versions we have to remove
629
			// let's search which pages versions we have to remove
631
			// this is necessary beacause even MySQL does not handel multi-tables deletes before version 4.0
630
			// this is necessary beacause even MySQL does not handel multi-tables deletes before version 4.0
632
			$wnPages = $this->GetConfigValue('table_prefix') . 'pages';
631
			$wnPages = $this->GetConfigValue('table_prefix') . 'pages';
633
			$sql = 'SELECT DISTINCT a.id FROM ' . $wnPages . ' a,' . $wnPages . ' b WHERE a.latest = \'N\' AND a.time < date_sub(now(), INTERVAL \'' . addslashes($days) . '\' DAY) AND a.tag = b.tag AND a.time < b.time AND b.time < date_sub(now(), INTERVAL \'' . addslashes($days) . '\' DAY)';
632
			$sql = 'SELECT DISTINCT a.id FROM ' . $wnPages . ' a,' . $wnPages . ' b WHERE a.latest = \'N\' AND a.time < date_sub(now(), INTERVAL \'' . addslashes($days) . '\' DAY) AND a.tag = b.tag AND a.time < b.time AND b.time < date_sub(now(), INTERVAL \'' . addslashes($days) . '\' DAY)';
634
			$ids = $this->LoadAll($sql);
633
			$ids = $this->LoadAll($sql);
635
 
634
 
636
			if (count($ids)) { // there are some versions to remove from DB
635
			if (count($ids)) { // there are some versions to remove from DB
637
				// let's build one big request, that's better...
636
				// let's build one big request, that's better...
638
				$sql = 'DELETE FROM ' . $wnPages . ' WHERE id IN (';
637
				$sql = 'DELETE FROM ' . $wnPages . ' WHERE id IN (';
639
				foreach($ids as $key => $line){
638
				foreach($ids as $key => $line){
640
					$sql .= ($key ? ', ':'') . $line['id']; // NB.: id is an int, no need of quotes
639
					$sql .= ($key ? ', ':'') . $line['id']; // NB.: id is an int, no need of quotes
641
				}
640
				}
642
				$sql .= ')';
641
				$sql .= ')';
643
 
642
 
644
				// ... and send it !
643
				// ... and send it !
645
				$this->Query($sql);
644
				$this->Query($sql);
646
			}
645
			}
647
		}
646
		}
648
	}
647
	}
649
 
648
 
650
 
649
 
651
 
650
 
652
	// COOKIES
651
	// COOKIES
653
	function SetSessionCookie($name, $value)
652
	function SetSessionCookie($name, $value)
654
	{
653
	{
655
		SetCookie($name, $value, 0, $this->CookiePath);
654
		SetCookie($name, $value, 0, $this->CookiePath);
656
		$_COOKIE[$name] = $value;
655
		$_COOKIE[$name] = $value;
657
	}
656
	}
658
	function SetPersistentCookie($name, $value, $remember = 0)
657
	function SetPersistentCookie($name, $value, $remember = 0)
659
	{
658
	{
660
		SetCookie($name, $value, time() + ($remember ? 90*24*60*60 : 60 * 60), $this->CookiePath);
659
		SetCookie($name, $value, time() + ($remember ? 90*24*60*60 : 60 * 60), $this->CookiePath);
661
		$_COOKIE[$name] = $value;
660
		$_COOKIE[$name] = $value;
662
	}
661
	}
663
	function DeleteCookie($name)
662
	function DeleteCookie($name)
664
	{
663
	{
665
		SetCookie($name, "", 1, $this->CookiePath);
664
		SetCookie($name, "", 1, $this->CookiePath);
666
		$_COOKIE[$name] = "";
665
		$_COOKIE[$name] = "";
667
	}
666
	}
668
	function GetCookie($name) { return $_COOKIE[$name]; }
667
	function GetCookie($name) { return $_COOKIE[$name]; }
669
 
668
 
670
 
669
 
671
 
670
 
672
	// HTTP/REQUEST/LINK RELATED
671
	// HTTP/REQUEST/LINK RELATED
673
	function SetMessage($message) { $_SESSION["message"] = $message; }
672
	function SetMessage($message) { $_SESSION["message"] = $message; }
674
	function GetMessage()
673
	function GetMessage()
675
	{
674
	{
676
		if (isset($_SESSION["message"])) $message = $_SESSION["message"];
675
		if (isset($_SESSION["message"])) $message = $_SESSION["message"];
677
		else $message = "";
676
		else $message = "";
678
		$_SESSION["message"] = "";
677
		$_SESSION["message"] = "";
679
		return $message;
678
		return $message;
680
	}
679
	}
681
	function Redirect($url)
680
	function Redirect($url)
682
	{
681
	{
683
		header("Location: $url");
682
		header("Location: $url");
684
		exit;
683
		exit;
685
	}
684
	}
686
	// returns just PageName[/method].
685
	// returns just PageName[/method].
687
	function MiniHref($method = "", $tag = "")
686
	function MiniHref($method = "", $tag = "")
688
	{
687
	{
689
		if (!$tag = trim($tag)) $tag = $this->tag;
688
		if (!$tag = trim($tag)) $tag = $this->tag;
690
		return $tag.($method ? "/".$method : "");
689
		return $tag.($method ? "/".$method : "");
691
	}
690
	}
692
	// returns the full url to a page/method.
691
	// returns the full url to a page/method.
693
	function Href($method = "", $tag = "", $params = "", $htmlspchars = true)
692
	function Href($method = "", $tag = "", $params = "", $htmlspchars = true)
694
	{
693
	{
695
		$href = $this->config["base_url"].$this->MiniHref($method, $tag);
694
		$href = $this->config["base_url"].$this->MiniHref($method, $tag);
696
		if ($params)
695
		if ($params)
697
		{
696
		{
698
			$href .= ($this->config["rewrite_mode"] ? "?" : ($htmlspchars ? "&amp;" : '&')).$params;
697
			$href .= ($this->config["rewrite_mode"] ? "?" : ($htmlspchars ? "&amp;" : '&')).$params;
699
		}
698
		}
700
		return $href;
699
		return $href;
701
	}
700
	}
702
	function Link($tag, $method = "", $text = "", $track = 1)
701
	function Link($tag, $method = "", $text = "", $track = 1)
703
	{
702
	{
704
		$displayText = $text ? $text : $tag;
703
		$displayText = $text ? $text : $tag;
705
		// is this an interwiki link?
704
		// is this an interwiki link?
706
		if (preg_match('/^' . WN_INTERWIKI_CAPTURE . '$/', $tag, $matches))
705
		if (preg_match('/^' . WN_INTERWIKI_CAPTURE . '$/', $tag, $matches))
707
		{
706
		{
708
			if ($tagInterWiki = $this->GetInterWikiUrl($matches[1], $matches[2])) {
707
			if ($tagInterWiki = $this->GetInterWikiUrl($matches[1], $matches[2])) {
709
				return '<a href="'.htmlspecialchars($tagInterWiki).'">'
708
				return '<a href="'.htmlspecialchars($tagInterWiki).'">'
710
					.htmlspecialchars($displayText).' (interwiki)</a>';
709
					.htmlspecialchars($displayText).' (interwiki)</a>';
711
			}
710
			}
712
			else return '<a href="'.htmlspecialchars($tag).'">'
711
			else return '<a href="'.htmlspecialchars($tag).'">'
713
				.htmlspecialchars($displayText).' (interwiki inconnu)</a>';
712
				.htmlspecialchars($displayText).' (interwiki inconnu)</a>';
714
		}
713
		}
715
		// is this a full link? ie, does it contain non alpha-numeric characters?
714
		// is this a full link? ie, does it contain non alpha-numeric characters?
716
		// Note : [:alnum:] is equivalent [0-9A-Za-z]
715
		// Note : [:alnum:] is equivalent [0-9A-Za-z]
717
		//		  [^[:alnum:]] means : some caracters other than [0-9A-Za-z]
716
		//		  [^[:alnum:]] means : some caracters other than [0-9A-Za-z]
718
		// For example : "www.adress.com", "mailto:adress@domain.com", "http://www.adress.com"
717
		// For example : "www.adress.com", "mailto:adress@domain.com", "http://www.adress.com"
719
		else if (preg_match("/[^[:alnum:]]/", $tag))
718
		else if (preg_match("/[^[:alnum:]]/", $tag))
720
		{
719
		{
721
			// check for various modifications to perform on $tag
720
			// check for various modifications to perform on $tag
722
			if (preg_match("/^[\w.-]+\@[\w.-]+$/", $tag))
721
			if (preg_match("/^[\w.-]+\@[\w.-]+$/", $tag))
723
			{ // email addresses
722
			{ // email addresses
724
				$tag = 'mailto:'.$tag;
723
				$tag = 'mailto:'.$tag;
725
			}
724
			}
726
			// Note : in Perl regexp, (?: ... ) is a non-catching cluster
725
			// Note : in Perl regexp, (?: ... ) is a non-catching cluster
727
			else if (preg_match('/^[[:alnum:]][[:alnum:].-]*(?:\/|$)/', $tag))
726
			else if (preg_match('/^[[:alnum:]][[:alnum:].-]*(?:\/|$)/', $tag))
728
			{ // protocol-less URLs
727
			{ // protocol-less URLs
729
				$tag = 'http://'.$tag;
728
				$tag = 'http://'.$tag;
730
			}
729
			}
731
			// Finally, block script schemes (see RFC 3986 about
730
			// Finally, block script schemes (see RFC 3986 about
732
			// schemes) and allow relative link & protocol-full URLs
731
			// schemes) and allow relative link & protocol-full URLs
733
			else if (preg_match('/^[a-z0-9.+-]*script[a-z0-9.+-]*:/i', $tag)
732
			else if (preg_match('/^[a-z0-9.+-]*script[a-z0-9.+-]*:/i', $tag)
734
				|| !(preg_match('/^\.?\.?\//', $tag)
733
				|| !(preg_match('/^\.?\.?\//', $tag)
735
					|| preg_match('/^[a-z0-9.+-]+:\/\//i', $tag)))
734
					|| preg_match('/^[a-z0-9.+-]+:\/\//i', $tag)))
736
			{
735
			{
737
				// If does't fit, we can't qualify $tag as an URL.
736
				// If does't fit, we can't qualify $tag as an URL.
738
				// There is a high risk that $tag is just XSS (bad
737
				// There is a high risk that $tag is just XSS (bad
739
				// javascript: code) or anything nasty. So we must not
738
				// javascript: code) or anything nasty. So we must not
740
				// produce any link at all.
739
				// produce any link at all.
741
				return htmlspecialchars($tag.($text ? ' '.$text : ''));
740
				return htmlspecialchars($tag.($text ? ' '.$text : ''));
742
			}
741
			}
743
			// Important: Here, we know that $tag is not something bad
742
			// Important: Here, we know that $tag is not something bad
744
			// and that we must produce a link with it
743
			// and that we must produce a link with it
745
 
744
 
746
			// An inline image? (text!=tag and url ends by png,gif,jpeg)
745
			// An inline image? (text!=tag and url ends by png,gif,jpeg)
747
			if ($text and preg_match("/\.(gif|jpeg|png|jpg)$/i",$tag))
746
			if ($text and preg_match("/\.(gif|jpeg|png|jpg)$/i",$tag))
748
			{
747
			{
749
				return '<img src="'.htmlspecialchars($tag)
748
				return '<img src="'.htmlspecialchars($tag)
750
					.'" alt="'.htmlspecialchars($displayText).'"/>';
749
					.'" alt="'.htmlspecialchars($displayText).'"/>';
751
			}
750
			}
752
			else
751
			else
753
			{
752
			{
754
				// Even if we know $tag is harmless, we MUST encode it
753
				// Even if we know $tag is harmless, we MUST encode it
755
				// in HTML with htmlspecialchars() before echoing it.
754
				// in HTML with htmlspecialchars() before echoing it.
756
				// This is not about being paranoiac. This is about
755
				// This is not about being paranoiac. This is about
757
				// being compliant to the HTML standard.
756
				// being compliant to the HTML standard.
758
				return '<a href="'.htmlspecialchars($tag).'">'
757
				return '<a href="'.htmlspecialchars($tag).'">'
759
					.htmlspecialchars($displayText).'</a>';
758
					.htmlspecialchars($displayText).'</a>';
760
			}
759
			}
761
		}
760
		}
762
		else
761
		else
763
		{
762
		{
764
			// it's a Wiki link!
763
			// it's a Wiki link!
765
			if (!empty($track)) $this->TrackLinkTo($tag);
764
			if (!empty($track)) $this->TrackLinkTo($tag);
766
			if ($this->LoadPage($tag))
765
			if ($this->LoadPage($tag))
767
				return '<a href="'.htmlspecialchars($this->href($method, $tag)).'">'
766
				return '<a href="'.htmlspecialchars($this->href($method, $tag)).'">'
768
					.htmlspecialchars($displayText).'</a>';
767
					.htmlspecialchars($displayText).'</a>';
769
			else
768
			else
770
				return '<span class="missingpage">'.htmlspecialchars($displayText)
769
				return '<span class="missingpage">'.htmlspecialchars($displayText)
771
				.'</span><a href="'.htmlspecialchars($this->href("edit", $tag)).'">?</a>';
770
				.'</span><a href="'.htmlspecialchars($this->href("edit", $tag)).'">?</a>';
772
		}
771
		}
773
	}
772
	}
774
	function ComposeLinkToPage($tag, $method = "", $text = "", $track = 1) {
773
	function ComposeLinkToPage($tag, $method = "", $text = "", $track = 1) {
775
		if (!$text) $text = $tag;
774
		if (!$text) $text = $tag;
776
		$text = htmlspecialchars($text);
775
		$text = htmlspecialchars($text);
777
		if ($track)
776
		if ($track)
778
			$this->TrackLinkTo($tag);
777
			$this->TrackLinkTo($tag);
779
		return '<a href="'.$this->href($method, $tag).'">'.$text.'</a>';
778
		return '<a href="'.$this->href($method, $tag).'">'.$text.'</a>';
780
	}
779
	}
781
	function IsWikiName($text) {
780
	function IsWikiName($text) {
782
		return preg_match('/^' . WN_CAMEL_CASE . '$/', $text);
781
		return preg_match('/^' . WN_CAMEL_CASE . '$/', $text);
783
	}
782
	}
784
 
783
 
785
	// LinkTracking management
784
	// LinkTracking management
786
	/**
785
	/**
787
	 * Tracks the link to a given page (only if the LinkTracking is activated)
786
	 * Tracks the link to a given page (only if the LinkTracking is activated)
788
	 * @param string $tag The tag (name) of the page to track a link to.
787
	 * @param string $tag The tag (name) of the page to track a link to.
789
	 */
788
	 */
790
	function TrackLinkTo($tag) {
789
	function TrackLinkTo($tag) {
791
		if ($this->LinkTracking()) $this->linktable[] = $tag;
790
		if ($this->LinkTracking()) $this->linktable[] = $tag;
792
	}
791
	}
793
	/**
792
	/**
794
	 * @return array The current link tracking table
793
	 * @return array The current link tracking table
795
	 */
794
	 */
796
	function GetLinkTable() { return $this->linktable; }
795
	function GetLinkTable() { return $this->linktable; }
797
	/**
796
	/**
798
	 * Clears the link tracking table
797
	 * Clears the link tracking table
799
	 */
798
	 */
800
	function ClearLinkTable() { $this->linktable = array(); }
799
	function ClearLinkTable() { $this->linktable = array(); }
801
	/**
800
	/**
802
	 * Starts the LinkTracking
801
	 * Starts the LinkTracking
803
	 * @return bool The previous state of the link tracking
802
	 * @return bool The previous state of the link tracking
804
	 */
803
	 */
805
	function StartLinkTracking() {
804
	function StartLinkTracking() {
806
		return $this->LinkTracking(true);
805
		return $this->LinkTracking(true);
807
	}
806
	}
808
	/**
807
	/**
809
	 * Stops the LinkTracking
808
	 * Stops the LinkTracking
810
	 * @return bool The previous state of the link tracking
809
	 * @return bool The previous state of the link tracking
811
	 */
810
	 */
812
	function StopLinkTracking() {
811
	function StopLinkTracking() {
813
		return $this->LinkTracking(false);
812
		return $this->LinkTracking(false);
814
	}
813
	}
815
	/**
814
	/**
816
	 * Sets and/or retrieve the state of the LinkTracking
815
	 * Sets and/or retrieve the state of the LinkTracking
817
	 * @param bool $newStatus The new status of the LinkTracking
816
	 * @param bool $newStatus The new status of the LinkTracking
818
	 * (defaults to <tt>null</tt> which lets it unchanged)
817
	 * (defaults to <tt>null</tt> which lets it unchanged)
819
	 * @return bool The previous state of the link tracking
818
	 * @return bool The previous state of the link tracking
820
	 */
819
	 */
821
	function LinkTracking($newStatus = null)
820
	function LinkTracking($newStatus = null)
822
	{
821
	{
823
		$old = $this->isTrackingLinks;
822
		$old = $this->isTrackingLinks;
824
		if ($newStatus !== null) $this->isTrackingLinks = $newStatus;
823
		if ($newStatus !== null) $this->isTrackingLinks = $newStatus;
825
		return $old;
824
		return $old;
826
	}
825
	}
827
	function WriteLinkTable() {
826
	function WriteLinkTable() {
828
		// delete old link table
827
		// delete old link table
829
		$this->Query("delete from ".$this->config["table_prefix"]."links where from_tag = '".mysql_real_escape_string($this->GetPageTag())."'");
828
		$this->Query("delete from ".$this->config["table_prefix"]."links where from_tag = '".mysql_real_escape_string($this->GetPageTag())."'");
830
		if ($linktable = $this->GetLinkTable())
829
		if ($linktable = $this->GetLinkTable())
831
		{
830
		{
832
			$from_tag = mysql_real_escape_string($this->GetPageTag());
831
			$from_tag = mysql_real_escape_string($this->GetPageTag());
833
			foreach ($linktable as $to_tag)
832
			foreach ($linktable as $to_tag)
834
			{
833
			{
835
				$lower_to_tag = strtolower($to_tag);
834
				$lower_to_tag = strtolower($to_tag);
836
				if (!isset($written[$lower_to_tag]))
835
				if (!isset($written[$lower_to_tag]))
837
				{
836
				{
838
					$this->Query("insert into ".$this->config["table_prefix"]."links set from_tag = '".$from_tag."', to_tag = '".mysql_real_escape_string($to_tag)."'");
837
					$this->Query("insert into ".$this->config["table_prefix"]."links set from_tag = '".$from_tag."', to_tag = '".mysql_real_escape_string($to_tag)."'");
839
					$written[$lower_to_tag] = 1;
838
					$written[$lower_to_tag] = 1;
840
				}
839
				}
841
			}
840
			}
842
		}
841
		}
843
	}
842
	}
844
 
843
 
845
	function Header() {
844
	function Header() {
846
		$action = $this->GetConfigValue("header_action");
845
		$action = $this->GetConfigValue("header_action");
847
		if (($actionObj = &$this->GetActionObject($action)) && is_object($actionObj))
846
		if (($actionObj = &$this->GetActionObject($action)) && is_object($actionObj))
848
		{
847
		{
849
			return $actionObj->GenerateHeader();
848
			return $actionObj->GenerateHeader();
850
		}
849
		}
851
		return $this->Action($action, 1);
850
		return $this->Action($action, 1);
852
	}
851
	}
853
 
852
 
854
	function Footer() {
853
	function Footer() {
855
		$action = $this->GetConfigValue("footer_action");
854
		$action = $this->GetConfigValue("footer_action");
856
		if (($actionObj = &$this->GetActionObject($action)) && is_object($actionObj))
855
		if (($actionObj = &$this->GetActionObject($action)) && is_object($actionObj))
857
		{
856
		{
858
			return $actionObj->GenerateFooter();
857
			return $actionObj->GenerateFooter();
859
		}
858
		}
860
		return $this->Action($action, 1);
859
		return $this->Action($action, 1);
861
	}
860
	}
862
 
861
 
863
	// FORMS
862
	// FORMS
864
	function FormOpen($method = "", $tag = "", $formMethod = "post") {
863
	function FormOpen($method = "", $tag = "", $formMethod = "post") {
865
		$result = "<form action=\"".$this->href($method, $tag)."\" method=\"".$formMethod."\">\n";
864
		$result = "<form action=\"".$this->href($method, $tag)."\" method=\"".$formMethod."\">\n";
866
		if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wiki\" value=\"".$this->MiniHref($method, $tag)."\" />\n";
865
		if (!$this->config["rewrite_mode"]) $result .= "<input type=\"hidden\" name=\"wiki\" value=\"".$this->MiniHref($method, $tag)."\" />\n";
867
		return $result;
866
		return $result;
868
	}
867
	}
869
	function FormClose() {
868
	function FormClose() {
870
		return "</form>\n";
869
		return "</form>\n";
871
	}
870
	}
872
 
871
 
873
 
872
 
874
 
873
 
875
	// INTERWIKI STUFF
874
	// INTERWIKI STUFF
876
	function ReadInterWikiConfig() {
875
	function ReadInterWikiConfig() {
877
		if ($lines = file("interwiki.conf"))
876
		if ($lines = file("interwiki.conf"))
878
		{
877
		{
879
			foreach ($lines as $line)
878
			foreach ($lines as $line)
880
			{
879
			{
881
				if ($line = trim($line))
880
				if ($line = trim($line))
882
				{
881
				{
883
					list($wikiName, $wikiUrl) = explode(" ", trim($line));
882
					list($wikiName, $wikiUrl) = explode(" ", trim($line));
884
					$this->AddInterWiki($wikiName, $wikiUrl);
883
					$this->AddInterWiki($wikiName, $wikiUrl);
885
				}
884
				}
886
			}
885
			}
887
		}
886
		}
888
	}
887
	}
889
	function AddInterWiki($name, $url) {
888
	function AddInterWiki($name, $url) {
890
		$this->interWiki[strtolower($name)] = $url;
889
		$this->interWiki[strtolower($name)] = $url;
891
	}
890
	}
892
	function GetInterWikiUrl($name, $tag)
891
	function GetInterWikiUrl($name, $tag)
893
	{
892
	{
894
		if (isset($this->interWiki[strtolower($name)])) return $this->interWiki[strtolower($name)].$tag;
893
		if (isset($this->interWiki[strtolower($name)])) return $this->interWiki[strtolower($name)].$tag;
895
		else return FALSE;
894
		else return FALSE;
896
	}
895
	}
897
 
896
 
898
 
897
 
899
 
898
 
900
	// REFERRERS
899
	// REFERRERS
901
	function LogReferrer($tag = "", $referrer = "") {
900
	function LogReferrer($tag = "", $referrer = "") {
902
		// fill values
901
		// fill values
903
		if (!$tag = trim($tag)) $tag = $this->GetPageTag();
902
		if (!$tag = trim($tag)) $tag = $this->GetPageTag();
904
		if (!$referrer = trim($referrer) AND isset($_SERVER["HTTP_REFERER"])) $referrer = $_SERVER["HTTP_REFERER"];
903
		if (!$referrer = trim($referrer) AND isset($_SERVER["HTTP_REFERER"])) $referrer = $_SERVER["HTTP_REFERER"];
905
 
904
 
906
		// check if it's coming from another site
905
		// check if it's coming from another site
907
		if ($referrer && !preg_match("/^".preg_quote($this->GetConfigValue("base_url"), "/")."/", $referrer))
906
		if ($referrer && !preg_match("/^".preg_quote($this->GetConfigValue("base_url"), "/")."/", $referrer))
908
		{
907
		{
909
			// avoid XSS (with urls like "javascript:alert()" and co)
908
			// avoid XSS (with urls like "javascript:alert()" and co)
910
			// by forcing http/https prefix
909
			// by forcing http/https prefix
911
			// NB.: this does NOT exempt to htmlspecialchars() the collected URIs !
910
			// NB.: this does NOT exempt to htmlspecialchars() the collected URIs !
912
			if (!preg_match('`^https?://`', $referrer)) return;
911
			if (!preg_match('`^https?://`', $referrer)) return;
913
 
912
 
914
			$this->Query("insert into ".$this->config["table_prefix"]."referrers set ".
913
			$this->Query("insert into ".$this->config["table_prefix"]."referrers set ".
915
				"page_tag = '".mysql_real_escape_string($tag)."', ".
914
				"page_tag = '".mysql_real_escape_string($tag)."', ".
916
				"referrer = '".mysql_real_escape_string($referrer)."', ".
915
				"referrer = '".mysql_real_escape_string($referrer)."', ".
917
				"time = now()");
916
				"time = now()");
918
		}
917
		}
919
	}
918
	}
920
	function LoadReferrers($tag = "") {
919
	function LoadReferrers($tag = "") {
921
		return $this->LoadAll("select referrer, count(referrer) as num from ".$this->config["table_prefix"]."referrers ".($tag = trim($tag) ? "where page_tag = '".mysql_real_escape_string($tag)."'" : "")." group by referrer order by num desc");
920
		return $this->LoadAll("select referrer, count(referrer) as num from ".$this->config["table_prefix"]."referrers ".($tag = trim($tag) ? "where page_tag = '".mysql_real_escape_string($tag)."'" : "")." group by referrer order by num desc");
922
	}
921
	}
923
	function PurgeReferrers() {
922
	function PurgeReferrers() {
924
		if ($days = $this->GetConfigValue("referrers_purge_time")) {
923
		if ($days = $this->GetConfigValue("referrers_purge_time")) {
925
			$this->Query("delete from ".$this->config["table_prefix"]."referrers where time < date_sub(now(), interval '".mysql_real_escape_string($days)."' day)");
924
			$this->Query("delete from ".$this->config["table_prefix"]."referrers where time < date_sub(now(), interval '".mysql_real_escape_string($days)."' day)");
926
		}
925
		}
927
	}
926
	}
928
 
927
 
929
 
928
 
930
 
929
 
931
	// PLUGINS
930
	// PLUGINS
932
	/**
931
	/**
933
	 * Exacutes an "action" module and returns the generated output
932
	 * Exacutes an "action" module and returns the generated output
934
	 * @param string $action The name of the action and its eventual parameters,
933
	 * @param string $action The name of the action and its eventual parameters,
935
	 * as it appears in the page between "{{" and "}}"
934
	 * as it appears in the page between "{{" and "}}"
936
	 * @param boolean $forceLinkTracking By default, the link tracking will be disabled
935
	 * @param boolean $forceLinkTracking By default, the link tracking will be disabled
937
	 * during the call of an action. Set this value to <code>true</code> to allow it.
936
	 * during the call of an action. Set this value to <code>true</code> to allow it.
938
	 * @param array $vars An array of additionnal parameters to give to the action, in the form
937
	 * @param array $vars An array of additionnal parameters to give to the action, in the form
939
	 * array( 'param' => 'value').
938
	 * array( 'param' => 'value').
940
	 * This allows you to call Action() internally, setting $action to the name of the action
939
	 * This allows you to call Action() internally, setting $action to the name of the action
941
	 * you want to call and it's parameters in an array, wich is more efficient than
940
	 * you want to call and it's parameters in an array, wich is more efficient than
942
	 * the pattern-matching algorithm used to extract the parameters from $action.
941
	 * the pattern-matching algorithm used to extract the parameters from $action.
943
	 * @return The output generated by the action.
942
	 * @return The output generated by the action.
944
	 */
943
	 */
945
	function Action($action, $forceLinkTracking = 0, $vars = array())
944
	function Action($action, $forceLinkTracking = 0, $vars = array())
946
	{
945
	{
947
		$cmd = trim($action);
946
		$cmd = trim($action);
948
		// extract $action and $vars_temp ("raw" attributes)
947
		// extract $action and $vars_temp ("raw" attributes)
949
		if (!preg_match("/^([a-zA-Z-0-9]+)\/?(.*)$/", $cmd, $matches))
948
		if (!preg_match("/^([a-zA-Z-0-9]+)\/?(.*)$/", $cmd, $matches))
950
		{
949
		{
951
			return '<i>Action invalide &quot;' . htmlspecialchars($cmd) . '&quot;</i>';
950
			return '<i>Action invalide &quot;' . htmlspecialchars($cmd) . '&quot;</i>';
952
		}
951
		}
953
		list(, $action, $vars_temp) = $matches;
952
		list(, $action, $vars_temp) = $matches;
954
		$vars[$vars_temp] = $vars_temp; // usefull for {{action/vars_temp}}
953
		$vars[$vars_temp] = $vars_temp; // usefull for {{action/vars_temp}}
955
 
954
 
956
		// now that we have the action's name, we can check if the user satisfies the ACLs
955
		// now that we have the action's name, we can check if the user satisfies the ACLs
957
		if (!$this->CheckModuleACL($action, 'action'))
956
		if (!$this->CheckModuleACL($action, 'action'))
958
		{
957
		{
959
			return 'Erreur: vous n\'avez pas acc&egrave;s &agrave; l\'action ' . $action . '.';
958
			return 'Erreur: vous n\'avez pas acc&egrave;s &agrave; l\'action ' . $action . '.';
960
		}
959
		}
961
 
960
 
962
		// match all attributes (key and value)
961
		// match all attributes (key and value)
963
		// prepare an array for extract() to work with (in $this->IncludeBuffered())
962
		// prepare an array for extract() to work with (in $this->IncludeBuffered())
964
		if (preg_match_all("/([a-zA-Z0-9]*)=\"(.*)\"/U", $vars_temp, $matches))
963
		if (preg_match_all("/([a-zA-Z0-9]*)=\"(.*)\"/U", $vars_temp, $matches))
965
		{
964
		{
966
			for ($a = 0; $a < count($matches[1]); $a++)
965
			for ($a = 0; $a < count($matches[1]); $a++)
967
			{
966
			{
968
				$vars[$matches[1][$a]] = $matches[2][$a];
967
				$vars[$matches[1][$a]] = $matches[2][$a];
969
			}
968
			}
970
		}
969
		}
971
 
970
 
972
		if (!$forceLinkTracking) $this->StopLinkTracking();
971
		if (!$forceLinkTracking) $this->StopLinkTracking();
973
		if ($actionObj = &$this->GetActionObject($action))
972
		if ($actionObj = &$this->GetActionObject($action))
974
		{
973
		{
975
			if (is_object($actionObj))
974
			if (is_object($actionObj))
976
			{
975
			{
977
				$result = $actionObj->PerformAction($vars, $cmd);
976
				$result = $actionObj->PerformAction($vars, $cmd);
978
			}
977
			}
979
			else // $actionObj is an error message
978
			else // $actionObj is an error message
980
			{
979
			{
981
				$result = $actionObj;
980
				$result = $actionObj;
982
			}
981
			}
983
		}
982
		}
984
		else // $actionObj == null (not found, no error message)
983
		else // $actionObj == null (not found, no error message)
985
		{
984
		{
986
			$this->parameter = &$vars;
985
			$this->parameter = &$vars;
987
			$result = $this->IncludeBuffered(strtolower($action).".php", "<i>Action inconnue &quot;$action&quot;</i>", $vars, $this->config["action_path"]);
986
			$result = $this->IncludeBuffered(strtolower($action).".php", "<i>Action inconnue &quot;$action&quot;</i>", $vars, $this->config["action_path"]);
988
			unset($this->parameter);
987
			unset($this->parameter);
989
		}
988
		}
990
		$this->StartLinkTracking(); // shouldn't we restore the previous status ?
989
		$this->StartLinkTracking(); // shouldn't we restore the previous status ?
991
		return $result;
990
		return $result;
992
	}
991
	}
993
 
992
 
994
	/**
993
	/**
995
	 * Finds the object corresponding to an action, if it exists.
994
	 * Finds the object corresponding to an action, if it exists.
996
	 * @param string $name The name of an action (should be alphanumeric)
995
	 * @param string $name The name of an action (should be alphanumeric)
997
	 * @return mixed
996
	 * @return mixed
998
	 * 	- null if the corresponding file was not found or the corresponding class didn't exist after inclusion
997
	 * 	- null if the corresponding file was not found or the corresponding class didn't exist after inclusion
999
	 *  - an error string if the corresponding file was found but an error append while loading it
998
	 *  - an error string if the corresponding file was found but an error append while loading it
1000
	 *  - the object corresponding to this action if no problem happend
999
	 *  - the object corresponding to this action if no problem happend
1001
	 * To check the result, you should use is_object() on it.
1000
	 * To check the result, you should use is_object() on it.
1002
	 * You should always assign the result of this method by referrence
1001
	 * You should always assign the result of this method by referrence
1003
	 * to avoid copying the object, which is the default beheviour in PHP4.
1002
	 * to avoid copying the object, which is the default beheviour in PHP4.
1004
	 * @example
1003
	 * @example
1005
	 * $var = &$wiki->GetActionObject('actionname');
1004
	 * $var = &$wiki->GetActionObject('actionname');
1006
	 * if (is_object($var))
1005
	 * if (is_object($var))
1007
	 * {
1006
	 * {
1008
	 * 		// normal behaviour
1007
	 * 		// normal behaviour
1009
	 * }
1008
	 * }
1010
	 * elseif ($var) // $var is not an object but an error string
1009
	 * elseif ($var) // $var is not an object but an error string
1011
	 * {
1010
	 * {
1012
	 * 		// threat error
1011
	 * 		// threat error
1013
	 * }
1012
	 * }
1014
	 * else // action was not found
1013
	 * else // action was not found
1015
	 * {
1014
	 * {
1016
	 * 		// rescue from inexising action or sth
1015
	 * 		// rescue from inexising action or sth
1017
	 * } 
1016
	 * } 
1018
	 */
1017
	 */
1019
	function &GetActionObject($name)
1018
	function &GetActionObject($name)
1020
	{
1019
	{
1021
		$name = strtolower($name);
1020
		$name = strtolower($name);
1022
		$actionObj = null; // the generated object
1021
		$actionObj = null; // the generated object
1023
		if (!preg_match('/^[a-z0-9]+$/', $name)) // paranoiac
1022
		if (!preg_match('/^[a-z0-9]+$/', $name)) // paranoiac
1024
		{
1023
		{
1025
			return $actionObj;
1024
			return $actionObj;
1026
		}
1025
		}
1027
 
1026
 
1028
		// already tried to load this object ? (may be null)
1027
		// already tried to load this object ? (may be null)
1029
		if (isset($this->actionObjects[$name]))
1028
		if (isset($this->actionObjects[$name]))
1030
		{
1029
		{
1031
			return $this->actionObjects[$name];
1030
			return $this->actionObjects[$name];
1032
		}
1031
		}
1033
 
1032
 
1034
		// object not loaded, try to load it
1033
		// object not loaded, try to load it
1035
		$filename = $name . '.class.php';
1034
		$filename = $name . '.class.php';
1036
		// load parent class for all action objects (only once)
1035
		// load parent class for all action objects (only once)
1037
		require_once 'includes/action.class.php';
1036
		require_once 'includes/action.class.php';
1038
		// include the action file, this should return an empty string
1037
		// include the action file, this should return an empty string
1039
		$result = $this->IncludeBuffered($filename, null, null, $this->GetConfigValue('action_path'));
1038
		$result = $this->IncludeBuffered($filename, null, null, $this->GetConfigValue('action_path'));
1040
		if ($result) // the result was not an empty string, certainly an error message
1039
		if ($result) // the result was not an empty string, certainly an error message
1041
		{
1040
		{
1042
			$actionObj = $result;
1041
			$actionObj = $result;
1043
		}
1042
		}
1044
		elseif ($result !== false) // the result was empty but the file was found
1043
		elseif ($result !== false) // the result was empty but the file was found
1045
		{
1044
		{
1046
			$class = 'Action' . ucfirst($name);
1045
			$class = 'Action' . ucfirst($name);
1047
			if (class_exists($class))
1046
			if (class_exists($class))
1048
			{
1047
			{
1049
				$actionObj = new $class($this);
1048
				$actionObj = new $class($this);
1050
				if (!is_a($actionObj, 'WikiniAction'))
1049
				if (!is_a($actionObj, 'WikiniAction'))
1051
				{
1050
				{
1052
					die("Action invalide '$name': classe incorrecte");
1051
					die("Action invalide '$name': classe incorrecte");
1053
				}
1052
				}
1054
			}
1053
			}
1055
		}
1054
		}
1056
		$this->actionObjects[$name] = &$actionObj;
1055
		$this->actionObjects[$name] = &$actionObj;
1057
		return $actionObj;
1056
		return $actionObj;
1058
	}
1057
	}
1059
 
1058
 
1060
	/**
1059
	/**
1061
	 * Retrieves the list of existing actions
1060
	 * Retrieves the list of existing actions
1062
	 * @return array An unordered array of all the available actions.
1061
	 * @return array An unordered array of all the available actions.
1063
	 */
1062
	 */
1064
	function GetActionsList()
1063
	function GetActionsList()
1065
	{
1064
	{
1066
		$action_path = $this->GetConfigValue('action_path');
1065
		$action_path = $this->GetConfigValue('action_path');
1067
		$list = array();
1066
		$list = array();
1068
		if ($dh = opendir($action_path))
1067
		if ($dh = opendir($action_path))
1069
		{
1068
		{
1070
			while (($file = readdir($dh)) !== false)
1069
			while (($file = readdir($dh)) !== false)
1071
			{
1070
			{
1072
				if (preg_match('/^([a-zA-Z-0-9]+)(.class)?.php$/', $file, $matches))
1071
				if (preg_match('/^([a-zA-Z-0-9]+)(.class)?.php$/', $file, $matches))
1073
				{
1072
				{
1074
					$list[] = $matches[1];
1073
					$list[] = $matches[1];
1075
				}
1074
				}
1076
			}
1075
			}
1077
		}
1076
		}
1078
		return $list;
1077
		return $list;
1079
	}
1078
	}
1080
 
1079
 
1081
	/**
1080
	/**
1082
	 * Retrieves the list of existing handlers
1081
	 * Retrieves the list of existing handlers
1083
	 * @return array An unordered array of all the available handlers.
1082
	 * @return array An unordered array of all the available handlers.
1084
	 */
1083
	 */
1085
	function GetHandlersList()
1084
	function GetHandlersList()
1086
	{
1085
	{
1087
		$handler_path = $this->GetConfigValue('handler_path') . '/page/';
1086
		$handler_path = $this->GetConfigValue('handler_path') . '/page/';
1088
		$list = array();
1087
		$list = array();
1089
		if ($dh = opendir($handler_path))
1088
		if ($dh = opendir($handler_path))
1090
		{
1089
		{
1091
			while (($file = readdir($dh)) !== false)
1090
			while (($file = readdir($dh)) !== false)
1092
			{
1091
			{
1093
				if (preg_match('/^([a-zA-Z-0-9]+)(.class)?.php$/', $file, $matches))
1092
				if (preg_match('/^([a-zA-Z-0-9]+)(.class)?.php$/', $file, $matches))
1094
				{
1093
				{
1095
					$list[] = $matches[1];
1094
					$list[] = $matches[1];
1096
				}
1095
				}
1097
			}
1096
			}
1098
		}
1097
		}
1099
		return $list;
1098
		return $list;
1100
	}
1099
	}
1101
 
1100
 
1102
	function Method($method) {
1101
	function Method($method) {
1103
		if (!$handler = $this->page["handler"]) $handler = "page";
1102
		if (!$handler = $this->page["handler"]) $handler = "page";
1104
		$methodLocation = $handler."/".$method.".php";
1103
		$methodLocation = $handler."/".$method.".php";
1105
		return $this->IncludeBuffered($methodLocation, "<i>M&eacute;thode inconnue \"$methodLocation\"</i>", "", $this->config["handler_path"]);
1104
		return $this->IncludeBuffered($methodLocation, "<i>M&eacute;thode inconnue \"$methodLocation\"</i>", "", $this->config["handler_path"]);
1106
	}
1105
	}
1107
	function Format($text, $formatter = "wakka") {
1106
	function Format($text, $formatter = "wakka") {
1108
		return $this->IncludeBuffered("formatters/".$formatter.".php", "<i>Impossible de trouver le formateur \"$formatter\"</i>", compact("text")); 
1107
		return $this->IncludeBuffered("formatters/".$formatter.".php", "<i>Impossible de trouver le formateur \"$formatter\"</i>", compact("text")); 
1109
	}
1108
	}
1110
 
1109
 
1111
 
1110
 
1112
 
1111
 
1113
	// USERS
1112
	// USERS
1114
	function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config["table_prefix"]."users where name = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_real_escape_string($password)."'")." limit 1"); }
1113
	function LoadUser($name, $password = 0) { return $this->LoadSingle("select * from ".$this->config["table_prefix"]."users where name = '".mysql_real_escape_string($name)."' ".($password === 0 ? "" : "and password = '".mysql_real_escape_string($password)."'")." limit 1"); }
1115
	function LoadUsers() { return $this->LoadAll("select * from ".$this->config["table_prefix"]."users order by name"); }
1114
	function LoadUsers() { return $this->LoadAll("select * from ".$this->config["table_prefix"]."users order by name"); }
1116
	function GetUserName() { if ($user = $this->GetUser()) $name = $user["name"]; else if (!$name = gethostbyaddr($_SERVER["REMOTE_ADDR"])) $name = $_SERVER["REMOTE_ADDR"]; return $name; }
1115
	function GetUserName() { if ($user = $this->GetUser()) $name = $user["name"]; else if (!$name = gethostbyaddr($_SERVER["REMOTE_ADDR"])) $name = $_SERVER["REMOTE_ADDR"]; return $name; }
1117
	function GetUser() { return (isset($_SESSION["user"]) ? $_SESSION["user"] : '');}
1116
	function GetUser() { return (isset($_SESSION["user"]) ? $_SESSION["user"] : '');}
1118
	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); }
1117
	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); }
1119
	function LogoutUser() { $_SESSION["user"] = ""; $this->DeleteCookie("name"); $this->DeleteCookie("password"); }
1118
	function LogoutUser() { $_SESSION["user"] = ""; $this->DeleteCookie("name"); $this->DeleteCookie("password"); }
1120
	function UserWantsComments() { if (!$user = $this->GetUser()) return false; return ($user["show_comments"] == "Y"); }
1119
	function UserWantsComments() { if (!$user = $this->GetUser()) return false; return ($user["show_comments"] == "Y"); }
1121
	function GetParameter($parameter, $default = '') { return (isset($this->parameter[$parameter]) ? $this->parameter[$parameter] : $default); }
1120
	function GetParameter($parameter, $default = '') { return (isset($this->parameter[$parameter]) ? $this->parameter[$parameter] : $default); }
1122
 
1121
 
1123
 
1122
 
1124
	// COMMENTS
1123
	// COMMENTS
1125
	/**
1124
	/**
1126
	 * Charge les commentaires relatifs ? une page.
1125
	 * Charge les commentaires relatifs ? une page.
1127
	 * 
1126
	 * 
1128
	 * @param string $tag Nom de la page. Ex : "PagePrincipale"
1127
	 * @param string $tag Nom de la page. Ex : "PagePrincipale"
1129
	 * @return array Tableau contenant tous les commentaires et leurs
1128
	 * @return array Tableau contenant tous les commentaires et leurs
1130
	 * propri?t?s correspondantes.
1129
	 * propri?t?s correspondantes.
1131
	 */
1130
	 */
1132
	function LoadComments($tag)
1131
	function LoadComments($tag)
1133
	{
1132
	{
1134
		return $this->LoadAll(
1133
		return $this->LoadAll(
1135
			"select * " .
1134
			"select * " .
1136
			"from ".$this->config["table_prefix"]."pages " .
1135
			"from ".$this->config["table_prefix"]."pages " .
1137
			"where comment_on = '".mysql_real_escape_string($tag)."' " .
1136
			"where comment_on = '".mysql_real_escape_string($tag)."' " .
1138
			"and latest = 'Y' " .
1137
			"and latest = 'Y' " .
1139
			"order by substring(tag, 8) + 0");
1138
			"order by substring(tag, 8) + 0");
1140
	}
1139
	}
1141
	/**
1140
	/**
1142
	 * Charge les derniers commentaires de toutes les pages.
1141
	 * Charge les derniers commentaires de toutes les pages.
1143
	 * 
1142
	 * 
1144
	 * @param int $limit Nombre de commentaires charg?s.
1143
	 * @param int $limit Nombre de commentaires charg?s.
1145
	 *                   0 par d?faut (ie tous les commentaires).
1144
	 *                   0 par d?faut (ie tous les commentaires).
1146
	 * @return array Tableau contenant chaque commentaire et ses
1145
	 * @return array Tableau contenant chaque commentaire et ses
1147
	 *               propri?t?s associ?es.
1146
	 *               propri?t?s associ?es.
1148
	 * @todo Ajouter le param?tre $start pour permettre une pagination
1147
	 * @todo Ajouter le param?tre $start pour permettre une pagination
1149
	 *       des commentaires : ->LoadRecentComments(10, 10)
1148
	 *       des commentaires : ->LoadRecentComments(10, 10)
1150
	 */
1149
	 */
1151
	function LoadRecentComments($limit = 0)
1150
	function LoadRecentComments($limit = 0)
1152
	{
1151
	{
1153
		// The part of the query which limit the number of comments  
1152
		// The part of the query which limit the number of comments  
1154
		if(is_numeric($limit) && $limit > 0) $lim = " limit ".$limit;
1153
		if(is_numeric($limit) && $limit > 0) $lim = " limit ".$limit;
1155
		else $lim = "";
1154
		else $lim = "";
1156
 
1155
 
1157
		// Query
1156
		// Query
1158
		return $this->LoadAll(
1157
		return $this->LoadAll(
1159
			"select * " .
1158
			"select * " .
1160
			"from " . $this->config["table_prefix"] . "pages " .
1159
			"from " . $this->config["table_prefix"] . "pages " .
1161
			"where comment_on != '' " .
1160
			"where comment_on != '' " .
1162
			"and latest = 'Y' " .
1161
			"and latest = 'Y' " .
1163
			"order by time desc " .
1162
			"order by time desc " .
1164
			$lim);
1163
			$lim);
1165
	}
1164
	}
1166
	function LoadRecentlyCommented($limit = 50)
1165
	function LoadRecentlyCommented($limit = 50)
1167
	{
1166
	{
1168
		$pages = array();
1167
		$pages = array();
1169
 
1168
 
1170
		// NOTE: this is really stupid. Maybe my SQL-Fu is too weak, but apparently there is no easier way to simply select
1169
		// NOTE: this is really stupid. Maybe my SQL-Fu is too weak, but apparently there is no easier way to simply select
1171
		//       all comment pages sorted by their first revision's (!) time. ugh!
1170
		//       all comment pages sorted by their first revision's (!) time. ugh!
1172
 
1171
 
1173
		// load ids of the first revisions of latest comments. err, huh?
1172
		// load ids of the first revisions of latest comments. err, huh?
1174
		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"))
1173
		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"))
1175
		{
1174
		{
1176
			// load complete comments
1175
			// load complete comments
1177
			$num=0;
1176
			$num=0;
1178
			foreach ($ids as $id)
1177
			foreach ($ids as $id)
1179
			{
1178
			{
1180
				$comment = $this->LoadSingle("select * from ".$this->config["table_prefix"]."pages where id = '".$id["id"]."' limit 1");
1179
				$comment = $this->LoadSingle("select * from ".$this->config["table_prefix"]."pages where id = '".$id["id"]."' limit 1");
1181
				if (!isset($comments[$comment["comment_on"]]) && $num < $limit)
1180
				if (!isset($comments[$comment["comment_on"]]) && $num < $limit)
1182
				{
1181
				{
1183
					$comments[$comment["comment_on"]] = $comment;
1182
					$comments[$comment["comment_on"]] = $comment;
1184
					$num++;
1183
					$num++;
1185
				}
1184
				}
1186
			}
1185
			}
1187
 
1186
 
1188
			// now load pages
1187
			// now load pages
1189
			if ($comments)
1188
			if ($comments)
1190
			{
1189
			{
1191
				// now using these ids, load the actual pages
1190
				// now using these ids, load the actual pages
1192
				foreach ($comments as $comment)
1191
				foreach ($comments as $comment)
1193
				{
1192
				{
1194
					$page = $this->LoadPage($comment["comment_on"]);
1193
					$page = $this->LoadPage($comment["comment_on"]);
1195
					$page["comment_user"] = $comment["user"];
1194
					$page["comment_user"] = $comment["user"];
1196
					$page["comment_time"] = $comment["time"];
1195
					$page["comment_time"] = $comment["time"];
1197
					$page["comment_tag"] = $comment["tag"];
1196
					$page["comment_tag"] = $comment["tag"];
1198
					$pages[] = $page;
1197
					$pages[] = $page;
1199
				}
1198
				}
1200
			}
1199
			}
1201
		}
1200
		}
1202
		// load tags of pages 
1201
		// load tags of pages 
1203
		//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");
1202
		//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");
1204
		return $pages;
1203
		return $pages;
1205
	}
1204
	}
1206
 
1205
 
1207
 
1206
 
1208
 
1207
 
1209
	// ACCESS CONTROL
1208
	// ACCESS CONTROL
1210
	// returns true if logged in user is owner of current page, or page specified in $tag
1209
	// returns true if logged in user is owner of current page, or page specified in $tag
1211
	function UserIsOwner($tag = "") {
1210
	function UserIsOwner($tag = "") {
1212
		// check if user is logged in
1211
		// check if user is logged in
1213
		if (!$this->GetUser()) return false;
1212
		if (!$this->GetUser()) return false;
1214
 
1213
 
1215
		// set default tag
1214
		// set default tag
1216
		if (!$tag = trim($tag)) $tag = $this->GetPageTag();
1215
		if (!$tag = trim($tag)) $tag = $this->GetPageTag();
1217
 
1216
 
1218
		// check if user is owner
1217
		// check if user is owner
1219
		if ($this->GetPageOwner($tag) == $this->GetUserName()) return true;
1218
		if ($this->GetPageOwner($tag) == $this->GetUserName()) return true;
1220
	}
1219
	}
1221
 
1220
 
1222
	/**
1221
	/**
1223
	 * @param string $group The name of a group
1222
	 * @param string $group The name of a group
1224
	 * @return string the ACL associated with the group $gname
1223
	 * @return string the ACL associated with the group $gname
1225
	 * @see UserIsInGroup to check if a user belongs to some group
1224
	 * @see UserIsInGroup to check if a user belongs to some group
1226
	 */
1225
	 */
1227
	function GetGroupACL($group)
1226
	function GetGroupACL($group)
1228
	{
1227
	{
1229
		if (array_key_exists($group, $this->_groupsCache))
1228
		if (array_key_exists($group, $this->_groupsCache))
1230
		{
1229
		{
1231
			return $this->_groupsCache[$group];
1230
			return $this->_groupsCache[$group];
1232
		}
1231
		}
1233
		return $this->_groupsCache[$group] = $this->GetTripleValue($group, WIKINI_VOC_ACLS, GROUP_PREFIX);
1232
		return $this->_groupsCache[$group] = $this->GetTripleValue($group, WIKINI_VOC_ACLS, GROUP_PREFIX);
1234
	}
1233
	}
1235
 
1234
 
1236
	/**
1235
	/**
1237
	 * Checks if a new group acl is not defined recursively
1236
	 * Checks if a new group acl is not defined recursively
1238
	 * (this method expects that groups that are already defined are not themselves defined recursively...)
1237
	 * (this method expects that groups that are already defined are not themselves defined recursively...)
1239
	 * @param string $gname The name of the group
1238
	 * @param string $gname The name of the group
1240
	 * @param string $acl The new acl for that group
1239
	 * @param string $acl The new acl for that group
1241
	 * @return boolean True iff the new acl defines the group recursively
1240
	 * @return boolean True iff the new acl defines the group recursively
1242
	 */
1241
	 */
1243
	function MakesGroupRecursive($gname, $acl, $origin = null, $checked = array())
1242
	function MakesGroupRecursive($gname, $acl, $origin = null, $checked = array())
1244
	{
1243
	{
1245
		$gname = strtolower($gname);
1244
		$gname = strtolower($gname);
1246
		if ($origin === null)
1245
		if ($origin === null)
1247
		{
1246
		{
1248
			$origin = $gname;
1247
			$origin = $gname;
1249
		}
1248
		}
1250
		elseif ($gname === $origin)
1249
		elseif ($gname === $origin)
1251
		{
1250
		{
1252
			return true;
1251
			return true;
1253
		}
1252
		}
1254
		foreach (explode("\n", $acl) as $line)
1253
		foreach (explode("\n", $acl) as $line)
1255
		{
1254
		{
1256
			if (!$line) continue;
1255
			if (!$line) continue;
1257
			if ($line[0] == '!')
1256
			if ($line[0] == '!')
1258
			{
1257
			{
1259
				$line = substr($line, 1);
1258
				$line = substr($line, 1);
1260
			}
1259
			}
1261
			if (!$line) continue;
1260
			if (!$line) continue;
1262
			if ($line[0] == '@')
1261
			if ($line[0] == '@')
1263
			{
1262
			{
1264
				$line = substr($line, 1);
1263
				$line = substr($line, 1);
1265
				if (!in_array($line, $checked))
1264
				if (!in_array($line, $checked))
1266
				{
1265
				{
1267
					if ($this->MakesGroupRecursive($line, $this->GetGroupACL($line), $origin, $checked))
1266
					if ($this->MakesGroupRecursive($line, $this->GetGroupACL($line), $origin, $checked))
1268
					{
1267
					{
1269
						return true;
1268
						return true;
1270
					}
1269
					}
1271
				}
1270
				}
1272
			}
1271
			}
1273
		}
1272
		}
1274
		$checked[] = $gname;
1273
		$checked[] = $gname;
1275
		return false;
1274
		return false;
1276
	}
1275
	}
1277
 
1276
 
1278
	/**
1277
	/**
1279
	 * Sets a new ACL to a given group
1278
	 * Sets a new ACL to a given group
1280
	 * @param string $gname The name of a group
1279
	 * @param string $gname The name of a group
1281
	 * @param string $acl The new ACL to associate with the group $gname
1280
	 * @param string $acl The new ACL to associate with the group $gname
1282
	 * @return int 0 if successful, a triple error code or a specific error code:
1281
	 * @return int 0 if successful, a triple error code or a specific error code:
1283
	 * 	1000 if the new value would define the group recursively
1282
	 * 	1000 if the new value would define the group recursively
1284
	 * 	1001 if $gname is not named with alphanumeric chars
1283
	 * 	1001 if $gname is not named with alphanumeric chars
1285
	 * @see GetGroupACL
1284
	 * @see GetGroupACL
1286
	 */
1285
	 */
1287
	function SetGroupACL($gname, $acl)
1286
	function SetGroupACL($gname, $acl)
1288
	{
1287
	{
1289
		if (preg_match('/[^A-Za-z0-9]/', $gname))
1288
		if (preg_match('/[^A-Za-z0-9]/', $gname))
1290
		{
1289
		{
1291
			return 1001;
1290
			return 1001;
1292
		}
1291
		}
1293
		$old = $this->GetGroupACL($gname);
1292
		$old = $this->GetGroupACL($gname);
1294
		if ($this->MakesGroupRecursive($gname, $acl))
1293
		if ($this->MakesGroupRecursive($gname, $acl))
1295
		{
1294
		{
1296
			return 1000;
1295
			return 1000;
1297
		}
1296
		}
1298
		$this->_groupsCache[$gname] = $acl;
1297
		$this->_groupsCache[$gname] = $acl;
1299
		if ($old === null)
1298
		if ($old === null)
1300
		{
1299
		{
1301
			return $this->InsertTriple($gname, WIKINI_VOC_ACLS, $acl, GROUP_PREFIX);
1300
			return $this->InsertTriple($gname, WIKINI_VOC_ACLS, $acl, GROUP_PREFIX);
1302
		}
1301
		}
1303
		elseif ($old === $acl)
1302
		elseif ($old === $acl)
1304
		{
1303
		{
1305
			return 0; // nothing has changed
1304
			return 0; // nothing has changed
1306
		}
1305
		}
1307
		else
1306
		else
1308
		{
1307
		{
1309
			return $this->UpdateTriple($gname, WIKINI_VOC_ACLS, $old, $acl, GROUP_PREFIX);
1308
			return $this->UpdateTriple($gname, WIKINI_VOC_ACLS, $old, $acl, GROUP_PREFIX);
1310
		}
1309
		}
1311
	}
1310
	}
1312
	/**
1311
	/**
1313
	 * @return array The list of all group names
1312
	 * @return array The list of all group names
1314
	 */
1313
	 */
1315
	function GetGroupsList()
1314
	function GetGroupsList()
1316
	{
1315
	{
1317
		$res = $this->GetMatchingTriples(GROUP_PREFIX . '%', WIKINI_VOC_ACLS_URI);
1316
		$res = $this->GetMatchingTriples(GROUP_PREFIX . '%', WIKINI_VOC_ACLS_URI);
1318
		$prefix_len = strlen(GROUP_PREFIX);
1317
		$prefix_len = strlen(GROUP_PREFIX);
1319
		$list = array();
1318
		$list = array();
1320
		foreach ($res as $line)
1319
		foreach ($res as $line)
1321
		{
1320
		{
1322
			$list[] = substr($line['resource'], $prefix_len);
1321
			$list[] = substr($line['resource'], $prefix_len);
1323
		}
1322
		}
1324
		return $list;
1323
		return $list;
1325
	}
1324
	}
1326
 
1325
 
1327
	/**
1326
	/**
1328
	 * @param string $group The name of a group
1327
	 * @param string $group The name of a group
1329
	 * @return boolean true iff the user is in the given $group 
1328
	 * @return boolean true iff the user is in the given $group 
1330
	 */
1329
	 */
1331
	function UserIsInGroup($group, $user = null, $admincheck = true)
1330
	function UserIsInGroup($group, $user = null, $admincheck = true)
1332
	{
1331
	{
1333
		return $this->CheckACL($this->GetGroupACL($group), $user, $admincheck);
1332
		return $this->CheckACL($this->GetGroupACL($group), $user, $admincheck);
1334
	}
1333
	}
1335
 
1334
 
1336
	/**
1335
	/**
1337
	 * Checks if a given user is andministrator
1336
	 * Checks if a given user is andministrator
1338
	 * @param string $user The name of the user (defaults to the current user if not given)
1337
	 * @param string $user The name of the user (defaults to the current user if not given)
1339
	 * @return boolean true iff the user is an administrator
1338
	 * @return boolean true iff the user is an administrator
1340
	 */
1339
	 */
1341
	function UserIsAdmin($user = null)
1340
	function UserIsAdmin($user = null)
1342
	{
1341
	{
1343
		return $this->UserIsInGroup(ADMIN_GROUP, $user, false);
1342
		return $this->UserIsInGroup(ADMIN_GROUP, $user, false);
1344
	}
1343
	}
1345
 
1344
 
1346
	function GetPageOwner($tag = "", $time = "") { if (!$tag = trim($tag)) $tag = $this->GetPageTag(); if ($page = $this->LoadPage($tag, $time)) return $page["owner"]; }
1345
	function GetPageOwner($tag = "", $time = "") { if (!$tag = trim($tag)) $tag = $this->GetPageTag(); if ($page = $this->LoadPage($tag, $time)) return $page["owner"]; }
1347
	function SetPageOwner($tag, $user) {
1346
	function SetPageOwner($tag, $user) {
1348
		// check if user exists
1347
		// check if user exists
1349
		if (!$this->LoadUser($user)) return;
1348
		if (!$this->LoadUser($user)) return;
1350
 
1349
 
1351
		// updated latest revision with new owner
1350
		// updated latest revision with new owner
1352
		$this->Query("update ".$this->config["table_prefix"]."pages set owner = '".mysql_real_escape_string($user)."' where tag = '".mysql_real_escape_string($tag)."' and latest = 'Y' limit 1");
1351
		$this->Query("update ".$this->config["table_prefix"]."pages set owner = '".mysql_real_escape_string($user)."' where tag = '".mysql_real_escape_string($tag)."' and latest = 'Y' limit 1");
1353
	}
1352
	}
1354
	function LoadAcl($tag, $privilege, $useDefaults = 1) {
1353
	function LoadAcl($tag, $privilege, $useDefaults = 1) {
1355
		if ((!$acl = $this->LoadSingle("select * from ".$this->config["table_prefix"]."acls where page_tag = '".mysql_real_escape_string($tag)."' and privilege = '".mysql_real_escape_string($privilege)."' limit 1")) && $useDefaults)
1354
		if ((!$acl = $this->LoadSingle("select * from ".$this->config["table_prefix"]."acls where page_tag = '".mysql_real_escape_string($tag)."' and privilege = '".mysql_real_escape_string($privilege)."' limit 1")) && $useDefaults)
1356
		{
1355
		{
1357
			$acl = array("page_tag" => $tag, "privilege" => $privilege, "list" => $this->GetConfigValue("default_".$privilege."_acl"));
1356
			$acl = array("page_tag" => $tag, "privilege" => $privilege, "list" => $this->GetConfigValue("default_".$privilege."_acl"));
1358
		}
1357
		}
1359
		return $acl;
1358
		return $acl;
1360
	}
1359
	}
1361
	function SaveAcl($tag, $privilege, $list) {
1360
	function SaveAcl($tag, $privilege, $list) {
1362
		if ($this->LoadAcl($tag, $privilege, 0)) $this->Query("update ".$this->config["table_prefix"]."acls set list = '".mysql_real_escape_string(trim(str_replace("\r", "", $list)))."' where page_tag = '".mysql_real_escape_string($tag)."' and privilege = '".mysql_real_escape_string($privilege)."' limit 1");
1361
		if ($this->LoadAcl($tag, $privilege, 0)) $this->Query("update ".$this->config["table_prefix"]."acls set list = '".mysql_real_escape_string(trim(str_replace("\r", "", $list)))."' where page_tag = '".mysql_real_escape_string($tag)."' and privilege = '".mysql_real_escape_string($privilege)."' limit 1");
1363
		else $this->Query("insert into ".$this->config["table_prefix"]."acls set list = '".mysql_real_escape_string(trim(str_replace("\r", "", $list)))."', page_tag = '".mysql_real_escape_string($tag)."', privilege = '".mysql_real_escape_string($privilege)."'");
1362
		else $this->Query("insert into ".$this->config["table_prefix"]."acls set list = '".mysql_real_escape_string(trim(str_replace("\r", "", $list)))."', page_tag = '".mysql_real_escape_string($tag)."', privilege = '".mysql_real_escape_string($privilege)."'");
1364
	}
1363
	}
1365
	// returns true if $user (defaults to current user) has access to $privilege on $page_tag (defaults to current page)
1364
	// returns true if $user (defaults to current user) has access to $privilege on $page_tag (defaults to current page)
1366
	function HasAccess($privilege, $tag = "", $user = "") {
1365
	function HasAccess($privilege, $tag = "", $user = "") {
1367
		// set defaults
1366
		// set defaults
1368
		if (!$tag = trim($tag)) $tag = $this->GetPageTag();
1367
		if (!$tag = trim($tag)) $tag = $this->GetPageTag();
1369
		if (!$user)
1368
		if (!$user)
1370
		{
1369
		{
1371
			// if current user is owner, return true. owner can do anything!
1370
			// if current user is owner, return true. owner can do anything!
1372
			if ($this->UserIsOwner($tag)) return true;
1371
			if ($this->UserIsOwner($tag)) return true;
1373
			$user = $this->GetUserName();
1372
			$user = $this->GetUserName();
1374
		}
1373
		}
1375
 
1374
 
1376
		// TODO: we might want to check if a given $user (other than the current user)
1375
		// TODO: we might want to check if a given $user (other than the current user)
1377
		// has access to a given page. If the $user is the owner of that page,
1376
		// has access to a given page. If the $user is the owner of that page,
1378
		// this method might give a wrong result (because we can't check that)
1377
		// this method might give a wrong result (because we can't check that)
1379
 
1378
 
1380
		// load acl
1379
		// load acl
1381
		$acl = $this->LoadAcl($tag, $privilege);
1380
		$acl = $this->LoadAcl($tag, $privilege);
1382
 
1381
 
1383
		// fine fine... now go through acl
1382
		// fine fine... now go through acl
1384
		return $this->CheckACL($acl["list"], $user);
1383
		return $this->CheckACL($acl["list"], $user);
1385
	}
1384
	}
1386
 
1385
 
1387
	/**
1386
	/**
1388
	 * Checks if some $user satisfies the given $acl
1387
	 * Checks if some $user satisfies the given $acl
1389
	 * @param string $acl The acl to check, in the same format than for pages ACL's
1388
	 * @param string $acl The acl to check, in the same format than for pages ACL's
1390
	 * @param string $user The name of the user that must satisfy the ACL. By default
1389
	 * @param string $user The name of the user that must satisfy the ACL. By default
1391
	 * the current remote user.
1390
	 * the current remote user.
1392
	 * @return bool True if the $user satisfies the $acl, false otherwise
1391
	 * @return bool True if the $user satisfies the $acl, false otherwise
1393
	 */
1392
	 */
1394
	function CheckACL($acl, $user = null, $admincheck = true)
1393
	function CheckACL($acl, $user = null, $admincheck = true)
1395
	{
1394
	{
1396
		if (!$user)
1395
		if (!$user)
1397
		{
1396
		{
1398
			$user = $this->GetUserName();
1397
			$user = $this->GetUserName();
1399
		}
1398
		}
1400
 
1399
 
1401
		if ($admincheck && $this->UserIsAdmin($user))
1400
		if ($admincheck && $this->UserIsAdmin($user))
1402
		{
1401
		{
1403
			return true;
1402
			return true;
1404
		}
1403
		}
1405
 
1404
 
1406
 
1405
 
1407
		foreach (explode("\n", $acl) as $line)
1406
		foreach (explode("\n", $acl) as $line)
1408
		{
1407
		{
1409
			$line = trim($line);
1408
			$line = trim($line);
1410
 
1409
 
1411
			// check for inversion character "!"
1410
			// check for inversion character "!"
1412
			if (preg_match("/^[!](.*)$/", $line, $matches))
1411
			if (preg_match("/^[!](.*)$/", $line, $matches))
1413
			{
1412
			{
1414
				$negate = 1;
1413
				$negate = 1;
1415
				$line = $matches[1];
1414
				$line = $matches[1];
1416
			}
1415
			}
1417
			else
1416
			else
1418
			{
1417
			{
1419
				$negate = 0;
1418
				$negate = 0;
1420
			}
1419
			}
1421
 
1420
 
1422
			// if there's still anything left... lines with just a "!" don't count!
1421
			// if there's still anything left... lines with just a "!" don't count!
1423
			if ($line)
1422
			if ($line)
1424
			{
1423
			{
1425
				switch ($line[0])
1424
				switch ($line[0])
1426
				{
1425
				{
1427
				case "#": // comments
1426
				case "#": // comments
1428
					break;
1427
					break;
1429
				case "*": // everyone
1428
				case "*": // everyone
1430
					return !$negate;
1429
					return !$negate;
1431
				case "+": // registered users
1430
				case "+": // registered users
1432
					if (!$this->LoadUser($user)) 
1431
					if (!$this->LoadUser($user)) 
1433
					{
1432
					{
1434
						return $negate;
1433
						return $negate;
1435
					}
1434
					}
1436
					else
1435
					else
1437
					{
1436
					{
1438
						return !$negate;
1437
						return !$negate;
1439
					}
1438
					}
1440
				case '@': // groups
1439
				case '@': // groups
1441
					$gname = substr($line, 1);
1440
					$gname = substr($line, 1);
1442
					// paranoiac: avoid line = '@'
1441
					// paranoiac: avoid line = '@'
1443
					if ($gname && $this->UserIsInGroup($gname, $user, false /* we have allready checked if user was an admin */))
1442
					if ($gname && $this->UserIsInGroup($gname, $user, false /* we have allready checked if user was an admin */))
1444
					{
1443
					{
1445
						return !$negate;
1444
						return !$negate;
1446
					}
1445
					}
1447
					break;
1446
					break;
1448
				default: // simple user entry
1447
				default: // simple user entry
1449
					if ($line == $user)
1448
					if ($line == $user)
1450
					{
1449
					{
1451
						return !$negate;
1450
						return !$negate;
1452
					}
1451
					}
1453
				}
1452
				}
1454
			}
1453
			}
1455
		}
1454
		}
1456
 
1455
 
1457
		// tough luck.
1456
		// tough luck.
1458
		return false;
1457
		return false;
1459
	}
1458
	}
1460
 
1459
 
1461
	/**
1460
	/**
1462
	 * Loads the module ACL for a certain module
1461
	 * Loads the module ACL for a certain module
1463
	 * @param string $module The name of the module
1462
	 * @param string $module The name of the module
1464
	 * @param string $module_type The type of module: 'action' or 'handler'
1463
	 * @param string $module_type The type of module: 'action' or 'handler'
1465
	 * @return mixed The ACL for the given module or <tt>null</tt> if no such
1464
	 * @return mixed The ACL for the given module or <tt>null</tt> if no such
1466
	 * ACL was found (which should probably be interpreted as '*'). 
1465
	 * ACL was found (which should probably be interpreted as '*'). 
1467
	 */
1466
	 */
1468
	function GetModuleACL($module, $module_type)
1467
	function GetModuleACL($module, $module_type)
1469
	{
1468
	{
1470
		$module = strtolower($module);
1469
		$module = strtolower($module);
1471
		switch ($module_type)
1470
		switch ($module_type)
1472
		{
1471
		{
1473
		case 'action':
1472
		case 'action':
1474
			if (array_key_exists($module, $this->_actionsAclsCache))
1473
			if (array_key_exists($module, $this->_actionsAclsCache))
1475
			{
1474
			{
1476
				$acl = $this->_actionsAclsCache[$module];
1475
				$acl = $this->_actionsAclsCache[$module];
1477
				break;
1476
				break;
1478
			}
1477
			}
1479
			$this->_actionsAclsCache[$module] = $acl = $this->GetTripleValue($module, WIKINI_VOC_ACLS, WIKINI_VOC_ACTIONS_PREFIX);
1478
			$this->_actionsAclsCache[$module] = $acl = $this->GetTripleValue($module, WIKINI_VOC_ACLS, WIKINI_VOC_ACTIONS_PREFIX);
1480
			if ($acl === null)
1479
			if ($acl === null)
1481
			{
1480
			{
1482
				$action = &$this->GetActionObject($module);
1481
				$action = &$this->GetActionObject($module);
1483
				if (is_object($action))
1482
				if (is_object($action))
1484
				{
1483
				{
1485
					return $this->_actionsAclsCache[$module] = $action->GetDefaultACL();
1484
					return $this->_actionsAclsCache[$module] = $action->GetDefaultACL();
1486
				}
1485
				}
1487
			}
1486
			}
1488
			break;
1487
			break;
1489
		case 'handler':
1488
		case 'handler':
1490
			$acl = $this->GetTripleValue($module, WIKINI_VOC_ACLS, WIKINI_VOC_HANDLERS_PREFIX);
1489
			$acl = $this->GetTripleValue($module, WIKINI_VOC_ACLS, WIKINI_VOC_HANDLERS_PREFIX);
1491
			break;
1490
			break;
1492
		default:
1491
		default:
1493
			return null; // TODO error msg ?
1492
			return null; // TODO error msg ?
1494
		}
1493
		}
1495
		return $acl === null ? '*' : $acl;
1494
		return $acl === null ? '*' : $acl;
1496
	}
1495
	}
1497
 
1496
 
1498
	/**
1497
	/**
1499
	 * Sets the $acl for a given $module
1498
	 * Sets the $acl for a given $module
1500
	 * @param string $module The name of the module
1499
	 * @param string $module The name of the module
1501
	 * @param string $module_type The type of module ('action' or 'handler')
1500
	 * @param string $module_type The type of module ('action' or 'handler')
1502
	 * @param string $acl The new ACL for that module
1501
	 * @param string $acl The new ACL for that module
1503
	 * @return 0 on success, > 0 on error (see InsertTriple and UpdateTriple)
1502
	 * @return 0 on success, > 0 on error (see InsertTriple and UpdateTriple)
1504
	 */
1503
	 */
1505
	function SetModuleACL($module, $module_type, $acl)
1504
	function SetModuleACL($module, $module_type, $acl)
1506
	{
1505
	{
1507
		$module = strtolower($module);
1506
		$module = strtolower($module);
1508
		$voc_prefix = $module_type == 'action' ? WIKINI_VOC_ACTIONS_PREFIX : WIKINI_VOC_HANDLERS_PREFIX;
1507
		$voc_prefix = $module_type == 'action' ? WIKINI_VOC_ACTIONS_PREFIX : WIKINI_VOC_HANDLERS_PREFIX;
1509
		$old = $this->GetTripleValue($module, WIKINI_VOC_ACLS, $voc_prefix);
1508
		$old = $this->GetTripleValue($module, WIKINI_VOC_ACLS, $voc_prefix);
1510
		if ($module_type == 'action')
1509
		if ($module_type == 'action')
1511
		{
1510
		{
1512
			$this->_actionsAclsCache[$module] = $acl;
1511
			$this->_actionsAclsCache[$module] = $acl;
1513
		}
1512
		}
1514
		if ($old === null)
1513
		if ($old === null)
1515
		{
1514
		{
1516
			return $this->InsertTriple($module, WIKINI_VOC_ACLS, $acl, $voc_prefix);
1515
			return $this->InsertTriple($module, WIKINI_VOC_ACLS, $acl, $voc_prefix);
1517
		}
1516
		}
1518
		elseif ($old === $acl)
1517
		elseif ($old === $acl)
1519
		{
1518
		{
1520
			return 0; // nothing has changed
1519
			return 0; // nothing has changed
1521
		}
1520
		}
1522
		else
1521
		else
1523
		{
1522
		{
1524
			return $this->UpdateTriple($module, WIKINI_VOC_ACLS, $old, $acl, $voc_prefix);
1523
			return $this->UpdateTriple($module, WIKINI_VOC_ACLS, $old, $acl, $voc_prefix);
1525
		}
1524
		}
1526
	}
1525
	}
1527
 
1526
 
1528
	/**
1527
	/**
1529
	 * Checks if a $user satisfies the ACL to access a certain $module
1528
	 * Checks if a $user satisfies the ACL to access a certain $module
1530
	 * @param string $module The name of the module to access
1529
	 * @param string $module The name of the module to access
1531
	 * @param string $module_type The type of the module ('action' or 'handler')
1530
	 * @param string $module_type The type of the module ('action' or 'handler')
1532
	 * @param string $user The name of the user. By default
1531
	 * @param string $user The name of the user. By default
1533
	 * the current remote user.
1532
	 * the current remote user.
1534
	 * @return bool True if the $user has access to the given $module, false otherwise.
1533
	 * @return bool True if the $user has access to the given $module, false otherwise.
1535
	 */
1534
	 */
1536
	function CheckModuleACL($module, $module_type, $user = null)
1535
	function CheckModuleACL($module, $module_type, $user = null)
1537
	{
1536
	{
1538
		$acl = $this->GetModuleACL($module, $module_type);
1537
		$acl = $this->GetModuleACL($module, $module_type);
1539
		if ($acl === null) return true; // undefined ACL means everybody has access
1538
		if ($acl === null) return true; // undefined ACL means everybody has access
1540
		return $this->CheckACL($acl, $user);
1539
		return $this->CheckACL($acl, $user);
1541
	}
1540
	}
1542
 
1541
 
1543
 
1542
 
1544
	// MAINTENANCE
1543
	// MAINTENANCE
1545
	function Maintenance() {
1544
	function Maintenance() {
1546
		// purge referrers
1545
		// purge referrers
1547
		$this->PurgeReferrers();
1546
		$this->PurgeReferrers();
1548
		// purge old page revisions
1547
		// purge old page revisions
1549
		$this->PurgePages();
1548
		$this->PurgePages();
1550
	}
1549
	}
1551
 
1550
 
1552
 
1551
 
1553
 
1552
 
1554
	// THE BIG EVIL NASTY ONE!
1553
	// THE BIG EVIL NASTY ONE!
1555
	function Run($tag, $method = "") {
1554
	function Run($tag, $method = "") {
1556
		if(!($this->GetMicroTime()%9)) $this->Maintenance(); 
1555
		if(!($this->GetMicroTime()%9)) $this->Maintenance(); 
1557
 
1556
 
1558
		$this->ReadInterWikiConfig();
1557
		$this->ReadInterWikiConfig();
1559
 
1558
 
1560
		// do our stuff!
1559
		// do our stuff!
1561
		if (!$this->method = trim($method)) $this->method = "show";
1560
		if (!$this->method = trim($method)) $this->method = "show";
1562
		if (!$this->tag = trim($tag)) $this->Redirect($this->href("", $this->config["root_page"]));
1561
		if (!$this->tag = trim($tag)) $this->Redirect($this->href("", $this->config["root_page"]));
1563
		if ((!$this->GetUser() && isset($_COOKIE["name"])) && ($user = $this->LoadUser($_COOKIE["name"], $_COOKIE["password"]))) $this->SetUser($user, $_COOKIE["remember"]);
1562
		if ((!$this->GetUser() && isset($_COOKIE["name"])) && ($user = $this->LoadUser($_COOKIE["name"], $_COOKIE["password"]))) $this->SetUser($user, $_COOKIE["remember"]);
1564
		$this->SetPage($this->LoadPage($tag, (isset($_REQUEST["time"]) ? $_REQUEST["time"] :'')));
1563
		$this->SetPage($this->LoadPage($tag, (isset($_REQUEST["time"]) ? $_REQUEST["time"] :'')));
1565
		$this->LogReferrer();
1564
		$this->LogReferrer();
1566
 
1565
 
1567
		//correction pour un support plus facile de nouveaux handlers
1566
		//correction pour un support plus facile de nouveaux handlers
1568
		if ($this->CheckModuleACL($this->method, 'handler'))
1567
		if ($this->CheckModuleACL($this->method, 'handler'))
1569
		{
1568
		{
1570
			echo $this->Method($this->method);
1569
			echo $this->Method($this->method);
1571
		}
1570
		}
1572
		else
1571
		else
1573
		{
1572
		{
1574
			echo 'Vous ne pouvez pas acc&eacute;der &agrave; cette page par le handler sp&eacute;cifi&eacute;.';
1573
			echo 'Vous ne pouvez pas acc&eacute;der &agrave; cette page par le handler sp&eacute;cifi&eacute;.';
1575
		}
1574
		}
1576
 
1575
 
1577
		// action redirect: aucune redirection n'a eu lieu, effacer la liste des redirections pr?c?dentes
1576
		// action redirect: aucune redirection n'a eu lieu, effacer la liste des redirections pr?c?dentes
1578
		if(!empty($_SESSION['redirects'])) session_unregister('redirects');
1577
		if(!empty($_SESSION['redirects'])) session_unregister('redirects');
1579
	}
1578
	}
1580
}
1579
}
1581
 
1580
 
1582
 
1581
 
1583
 
1582
 
1584
// stupid version check
1583
// stupid version check
1585
if (!isset($_REQUEST)) die('$_REQUEST[] not found. Wakka requires PHP 4.1.0 or higher!');
1584
if (!isset($_REQUEST)) die('$_REQUEST[] not found. Wakka requires PHP 4.1.0 or higher!');
1586
 
1585
 
1587
// workaround for the amazingly annoying magic quotes.
1586
// workaround for the amazingly annoying magic quotes.
1588
function magicQuotesSuck(&$a)
1587
function magicQuotesSuck(&$a)
1589
{
1588
{
1590
	if (is_array($a))
1589
	if (is_array($a))
1591
	{
1590
	{
1592
		foreach ($a as $k => $v)
1591
		foreach ($a as $k => $v)
1593
		{
1592
		{
1594
			if (is_array($v))
1593
			if (is_array($v))
1595
				magicQuotesSuck($a[$k]);
1594
				magicQuotesSuck($a[$k]);
1596
			else
1595
			else
1597
				$a[$k] = stripslashes($v);
1596
				$a[$k] = stripslashes($v);
1598
		}
1597
		}
1599
	}
1598
	}
1600
}
1599
}
1601
 
1600
 
1602
if (get_magic_quotes_runtime())
1601
if (get_magic_quotes_runtime())
1603
{
1602
{
1604
    // Deactivate
1603
    // Deactivate
1605
    set_magic_quotes_runtime(false);
1604
    set_magic_quotes_runtime(false);
1606
}
1605
}
1607
 
1606
 
1608
if (get_magic_quotes_gpc())
1607
if (get_magic_quotes_gpc())
1609
{
1608
{
1610
	magicQuotesSuck($_POST);
1609
	magicQuotesSuck($_POST);
1611
	magicQuotesSuck($_GET);
1610
	magicQuotesSuck($_GET);
1612
	magicQuotesSuck($_COOKIE);
1611
	magicQuotesSuck($_COOKIE);
1613
}
1612
}
1614
 
1613
 
1615
 
1614
 
1616
// default configuration values
1615
// default configuration values
1617
$wakkaConfig= array();
1616
$wakkaConfig= array();
1618
$_rewrite_mode = detectRewriteMode();
1617
$_rewrite_mode = detectRewriteMode();
1619
$wakkaDefaultConfig = array(
1618
$wakkaDefaultConfig = array(
1620
	'wakka_version'		=> '',
1619
	'wakka_version'		=> '',
1621
	'wikini_version'	=> '',
1620
	'wikini_version'	=> '',
1622
	'debug'				=> 'no',
1621
	'debug'				=> 'no',
1623
	"mysql_host"		=> "localhost",
1622
	"mysql_host"		=> "localhost",
1624
	"mysql_database"	=> "wikini",
1623
	"mysql_database"	=> "wikini",
1625
	"mysql_user"		=> "wikini",
1624
	"mysql_user"		=> "wikini",
1626
	"mysql_password"	=> '',
1625
	"mysql_password"	=> '',
1627
	"table_prefix"		=> "wikini_",
1626
	"table_prefix"		=> "wikini_",
1628
	"root_page"			=> "PagePrincipale",
1627
	"root_page"			=> "PagePrincipale",
1629
	"wakka_name"		=> "MonSiteWikiNi",
1628
	"wakka_name"		=> "MonSiteWikiNi",
1630
	"base_url"			=> computeBaseURL($_rewrite_mode),
1629
	"base_url"			=> computeBaseURL($_rewrite_mode),
1631
	"rewrite_mode"		=> $_rewrite_mode,
1630
	"rewrite_mode"		=> $_rewrite_mode,
1632
	'meta_keywords'		=> '',
1631
	'meta_keywords'		=> '',
1633
	'meta_description'	=> '',
1632
	'meta_description'	=> '',
1634
	"action_path"		=> "actions",
1633
	"action_path"		=> "actions",
1635
	"handler_path"		=> "handlers",
1634
	"handler_path"		=> "handlers",
1636
	"header_action"		=> "header",
1635
	"header_action"		=> "header",
1637
	"footer_action"		=> "footer",
1636
	"footer_action"		=> "footer",
1638
	"navigation_links"		=> "DerniersChangements :: DerniersCommentaires :: ParametresUtilisateur",
1637
	"navigation_links"		=> "DerniersChangements :: DerniersCommentaires :: ParametresUtilisateur",
1639
	"referrers_purge_time"	=> 24,
1638
	"referrers_purge_time"	=> 24,
1640
	"pages_purge_time"	=> 90,
1639
	"pages_purge_time"	=> 90,
1641
	"default_write_acl"	=> "*",
1640
	"default_write_acl"	=> "*",
1642
	"default_read_acl"	=> "*",
1641
	"default_read_acl"	=> "*",
1643
	"default_comment_acl"	=> "*",
1642
	"default_comment_acl"	=> "*",
1644
	"preview_before_save"	=> 0,
1643
	"preview_before_save"	=> 0,
1645
	'allow_raw_html'	=> false);
1644
	'allow_raw_html'	=> false);
1646
unset($_rewrite_mode);
1645
unset($_rewrite_mode);
1647
 
1646
 
1648
// load config
1647
// load config
1649
if (!$configfile = GetEnv("WAKKA_CONFIG")) $configfile = "wakka.config.php";
1648
if (!$configfile = GetEnv("WAKKA_CONFIG")) $configfile = "wakka.config.php";
1650
if (file_exists($configfile)) include($configfile);
1649
if (file_exists($configfile)) include($configfile);
1651
$wakkaConfigLocation = $configfile;
1650
$wakkaConfigLocation = $configfile;
1652
$wakkaConfig = array_merge($wakkaDefaultConfig, $wakkaConfig);
1651
$wakkaConfig = array_merge($wakkaDefaultConfig, $wakkaConfig);
1653
 
1652
 
1654
// check for locking
1653
// check for locking
1655
if (file_exists("locked")) {
1654
if (file_exists("locked")) {
1656
	// read password from lockfile
1655
	// read password from lockfile
1657
	$lines = file("locked");
1656
	$lines = file("locked");
1658
	$lockpw = trim($lines[0]);
1657
	$lockpw = trim($lines[0]);
1659
 
1658
 
1660
	// is authentification given?
1659
	// is authentification given?
1661
	if (isset($_SERVER["PHP_AUTH_USER"])) {
1660
	if (isset($_SERVER["PHP_AUTH_USER"])) {
1662
		if (!(($_SERVER["PHP_AUTH_USER"] == "admin") && ($_SERVER["PHP_AUTH_PW"] == $lockpw))) {
1661
		if (!(($_SERVER["PHP_AUTH_USER"] == "admin") && ($_SERVER["PHP_AUTH_PW"] == $lockpw))) {
1663
			$ask = 1;
1662
			$ask = 1;
1664
		}
1663
		}
1665
	} else {
1664
	} else {
1666
		$ask = 1;
1665
		$ask = 1;
1667
	}
1666
	}
1668
 
1667
 
1669
	if ($ask) {
1668
	if ($ask) {
1670
		header("WWW-Authenticate: Basic realm=\"".$wakkaConfig["wakka_name"]." Install/Upgrade Interface\"");
1669
		header("WWW-Authenticate: Basic realm=\"".$wakkaConfig["wakka_name"]." Install/Upgrade Interface\"");
1671
		header("HTTP/1.0 401 Unauthorized");
1670
		header("HTTP/1.0 401 Unauthorized");
1672
		echo "Ce site est en cours de mise &agrave; jour. Veuillez essayer plus tard." ;
1671
		echo "Ce site est en cours de mise &agrave; jour. Veuillez essayer plus tard." ;
1673
		exit;
1672
		exit;
1674
	}
1673
	}
1675
}
1674
}
1676
 
1675
 
1677
 
1676
 
1678
// compare versions, start installer if necessary
1677
// compare versions, start installer if necessary
1679
if ($wakkaConfig["wakka_version"] && (!$wakkaConfig["wikini_version"])) { $wakkaConfig["wikini_version"]=$wakkaConfig["wakka_version"]; }
1678
if ($wakkaConfig["wakka_version"] && (!$wakkaConfig["wikini_version"])) { $wakkaConfig["wikini_version"]=$wakkaConfig["wakka_version"]; }
1680
if (($wakkaConfig["wakka_version"] != WAKKA_VERSION) || ($wakkaConfig["wikini_version"] != WIKINI_VERSION)) {
1679
if (($wakkaConfig["wakka_version"] != WAKKA_VERSION) || ($wakkaConfig["wikini_version"] != WIKINI_VERSION)) {
1681
	// start installer
1680
	// start installer
1682
	if (!isset($_REQUEST["installAction"]) OR !$installAction = trim($_REQUEST["installAction"])) $installAction = "default";
1681
	if (!isset($_REQUEST["installAction"]) OR !$installAction = trim($_REQUEST["installAction"])) $installAction = "default";
1683
	include("setup/header.php");
1682
	include("setup/header.php");
1684
	if (file_exists("setup/".$installAction.".php")) include("setup/".$installAction.".php"); else echo "<i>Invalid action</i>" ;
1683
	if (file_exists("setup/".$installAction.".php")) include("setup/".$installAction.".php"); else echo "<i>Invalid action</i>" ;
1685
	include("setup/footer.php");
1684
	include("setup/footer.php");
1686
	exit;
1685
	exit;
1687
}
1686
}
1688
 
1687
 
1689
// Check if the server is configured to automatically compress the output
1688
// Check if the server is configured to automatically compress the output
1690
if (!ini_get('zlib.output_compression') && !ini_get('zlib.output_handler'))
1689
if (!ini_get('zlib.output_compression') && !ini_get('zlib.output_handler'))
1691
{ 
1690
{ 
1692
	// Check if we can use ob_gzhandler (requires the zlib extension)
1691
	// Check if we can use ob_gzhandler (requires the zlib extension)
1693
	if (function_exists('ob_gzhandler'))
1692
	if (function_exists('ob_gzhandler'))
1694
	{
1693
	{
1695
		// let ob_gzhandler do the dirty job
1694
		// let ob_gzhandler do the dirty job
1696
		// NB.: this must be done BEFORE session_start() when session.use_trans_sid is on
1695
		// NB.: this must be done BEFORE session_start() when session.use_trans_sid is on
1697
		ob_start('ob_gzhandler');
1696
		ob_start('ob_gzhandler');
1698
	}
1697
	}
1699
	// else lets do the dirty job by ourselves...
1698
	// else lets do the dirty job by ourselves...
1700
	elseif (!empty($_SERVER['HTTP_ACCEPT_ENCODING']) && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode'))
1699
	elseif (!empty($_SERVER['HTTP_ACCEPT_ENCODING']) && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode'))
1701
	{
1700
	{
1702
		ob_start ('gzencode');
1701
		ob_start ('gzencode');
1703
		// Tell the browser the content is compressed with gzip 
1702
		// Tell the browser the content is compressed with gzip 
1704
		header ("Content-Encoding: gzip"); 
1703
		header ("Content-Encoding: gzip"); 
1705
	}
1704
	}
1706
}
1705
}
1707
 
1706
 
1708
// configuration du cookie de session
1707
// configuration du cookie de session
1709
// determine le chemin pour les cookies
1708
// determine le chemin pour les cookies
1710
$a = parse_url($wakkaConfig['base_url']);
1709
$a = parse_url($wakkaConfig['base_url']);
1711
$CookiePath = dirname($a['path']);
1710
$CookiePath = dirname($a['path']);
1712
// Fixe la gestion des cookie sous les OS utilisant le \ comme s?parteur de chemin
1711
// Fixe la gestion des cookie sous les OS utilisant le \ comme s?parteur de chemin
1713
$CookiePath = str_replace("\\","/",$CookiePath);
1712
$CookiePath = str_replace("\\","/",$CookiePath);
1714
// ajoute un '/' terminal sauf si on est ? la racine web
1713
// ajoute un '/' terminal sauf si on est ? la racine web
1715
if ($CookiePath != '/') $CookiePath .= '/';
1714
if ($CookiePath != '/') $CookiePath .= '/';
1716
$a = session_get_cookie_params();
1715
$a = session_get_cookie_params();
1717
session_set_cookie_params($a['lifetime'],$CookiePath);
1716
session_set_cookie_params($a['lifetime'],$CookiePath);
1718
unset($a);
1717
unset($a);
1719
unset($CookiePath);
1718
unset($CookiePath);
1720
 
1719
 
1721
// start session
1720
// start session
1722
session_start();
1721
session_start();
1723
 
1722
 
1724
// create wiki object
1723
// create wiki object
1725
$wiki = new Wiki($wakkaConfig);
1724
$wiki = new Wiki($wakkaConfig);
1726
// check for database access
1725
// check for database access
1727
if (!$wiki->dblink)
1726
if (!$wiki->dblink)
1728
{
1727
{
1729
	echo	"<p>Pour des raisons ind&eacute;pendantes de notre volont&eacute;, ".
1728
	echo	"<p>Pour des raisons ind&eacute;pendantes de notre volont&eacute;, ".
1730
		"le contenu de ce Wiki est temporairement inaccessible. Veuillez ".
1729
		"le contenu de ce Wiki est temporairement inaccessible. Veuillez ".
1731
		"r&eacute;essayer ult&eacute;rieurement, merci de votre ".
1730
		"r&eacute;essayer ult&eacute;rieurement, merci de votre ".
1732
		"compr&eacute;hension.</p>";
1731
		"compr&eacute;hension.</p>";
1733
	// Log error (useful to find the buggy server in a load balancing platform)
1732
	// Log error (useful to find the buggy server in a load balancing platform)
1734
	trigger_error("WikiNi : DB connection failed");
1733
	trigger_error("WikiNi : DB connection failed");
1735
	exit;
1734
	exit;
1736
}
1735
}
1737
 
1736
 
1738
 
1737
 
1739
// go!
1738
// go!
1740
if (!isset($method)) $method='';
1739
if (!isset($method)) $method='';
1741
 
1740
 
1742
 
1741
 
1743
// Security (quick hack)  : Check method syntax
1742
// Security (quick hack)  : Check method syntax
1744
if (!(preg_match('#^[A-Za-z0-9_]*$#',$method))) {
1743
if (!(preg_match('#^[A-Za-z0-9_]*$#',$method))) {
1745
	$method='';
1744
	$method='';
1746
}
1745
}
1747
include('tools/prepend.php');//$wiki->Run($page, $method);
1746
include('tools/prepend.php');//$wiki->Run($page, $method);
1748
?>
1747
?>