1
+ − 1
<?php
+ − 2
+ − 3
/**
+ − 4
* Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ − 5
* Version 1.0 (Banshee)
+ − 6
* Copyright (C) 2006-2007 Dan Fuhry
+ − 7
* paths.php - The part of Enano that actually manages content. Everything related to page handling and namespaces is in here.
+ − 8
*
+ − 9
* This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ − 10
* as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ − 11
*
+ − 12
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ − 13
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ − 14
*
+ − 15
* @package Enano
+ − 16
* @subpackage PathManager
+ − 17
* @see http://enano.homelinux.org/Help:API_Documentation
+ − 18
*/
+ − 19
+ − 20
class pathManager {
+ − 21
var $pages, $custom_page, $cpage, $page, $fullpage, $page_exists, $namespace, $nslist, $admin_tree, $wiki_mode, $page_protected, $template_cache;
+ − 22
function __construct()
+ − 23
{
+ − 24
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 25
+ − 26
$GLOBALS['paths'] =& $this;
+ − 27
$this->pages = Array();
+ − 28
+ − 29
dc_here('paths: setting up namespaces, admin nodes');
+ − 30
+ − 31
// DEFINE NAMESPACES HERE
+ − 32
// The key names should NOT EVER be changed, or Enano will be very broken
+ − 33
$this->nslist = Array(
+ − 34
'Article' =>'',
+ − 35
'User' =>'User:',
+ − 36
'File' =>'File:',
+ − 37
'Help' =>'Help:',
+ − 38
'Admin' =>'Admin:',
+ − 39
'Special' =>'Special:',
+ − 40
'System' =>'Enano:',
+ − 41
'Template'=>'Template:',
+ − 42
'Category'=>'Category:',
+ − 43
'Project' =>str_replace(' ', '_', getConfig('site_name')).':',
+ − 44
);
+ − 45
+ − 46
// ACL types
+ − 47
// These can also be added from within plugins
+ − 48
+ − 49
$session->register_acl_type('read', AUTH_ALLOW, 'Read page(s)');
+ − 50
$session->register_acl_type('post_comments', AUTH_ALLOW, 'Post comments', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 51
$session->register_acl_type('edit_comments', AUTH_ALLOW, 'Edit own comments', Array('post_comments'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 52
$session->register_acl_type('edit_page', AUTH_WIKIMODE, 'Edit page', Array('view_source'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 53
$session->register_acl_type('view_source', AUTH_WIKIMODE, 'View source', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); // Only used if the page is protected
+ − 54
$session->register_acl_type('mod_comments', AUTH_DISALLOW, 'Moderate comments', Array('edit_comments'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 55
$session->register_acl_type('history_view', AUTH_WIKIMODE, 'View history/diffs', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 56
$session->register_acl_type('history_rollback', AUTH_DISALLOW, 'Rollback history', Array('history_view'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 57
$session->register_acl_type('history_rollback_extra', AUTH_DISALLOW, 'Undelete page(s)', Array('history_rollback'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 58
$session->register_acl_type('protect', AUTH_DISALLOW, 'Protect page(s)', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 59
$session->register_acl_type('rename', AUTH_WIKIMODE, 'Rename page(s)', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 60
$session->register_acl_type('clear_logs', AUTH_DISALLOW, 'Clear page logs (dangerous)', Array('read', 'protect', 'even_when_protected'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 61
$session->register_acl_type('vote_delete', AUTH_ALLOW, 'Vote to delete', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 62
$session->register_acl_type('vote_reset', AUTH_DISALLOW, 'Reset delete votes', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 63
$session->register_acl_type('delete_page', AUTH_DISALLOW, 'Delete page(s)', Array(), 'Article|User|Project|Template|File|Help|System|Category');
+ − 64
$session->register_acl_type('set_wiki_mode', AUTH_DISALLOW, 'Set per-page wiki mode', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 65
$session->register_acl_type('password_set', AUTH_DISALLOW, 'Set password', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 66
$session->register_acl_type('password_reset', AUTH_DISALLOW, 'Disable/reset password', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 67
$session->register_acl_type('mod_misc', AUTH_DISALLOW, 'Super moderator (generate SQL backtraces, view IP addresses, and send large numbers of private messages)', Array(), 'All');
+ − 68
$session->register_acl_type('edit_cat', AUTH_WIKIMODE, 'Edit categorization', Array('read'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 69
$session->register_acl_type('even_when_protected', AUTH_DISALLOW, 'Allow editing, renaming, and categorization even when protected', Array('edit_page', 'rename', 'mod_comments', 'edit_cat'), 'Article|User|Project|Template|File|Help|System|Category');
+ − 70
$session->register_acl_type('upload_files', AUTH_DISALLOW, 'Upload files', Array('create_page'), 'Article|User|Project|Template|File|Help|System|Category|Special');
+ − 71
$session->register_acl_type('upload_new_version', AUTH_WIKIMODE, 'Upload new versions of files', Array('upload_files'), 'Article|User|Project|Template|File|Help|System|Category|Special');
+ − 72
$session->register_acl_type('create_page', AUTH_WIKIMODE, 'Create pages', Array(), 'Article|User|Project|Template|File|Help|System|Category|Special');
11
ccad6026a168
Finalized permissions on files and directories; adding PHP shutoff button (actual shutoff not implemented)
Dan
diff
changeset
+ − 73
$session->register_acl_type('php_in_pages', AUTH_DISALLOW, 'Embed PHP code in pages', Array('edit_page'), 'Article|User|Project|Template|File|Help|System|Category|Admin');
1
+ − 74
$session->register_acl_type('edit_acl', AUTH_DISALLOW, 'Edit access control lists', Array('read', 'post_comments', 'edit_comments', 'edit_page', 'view_source', 'mod_comments', 'history_view', 'history_rollback', 'history_rollback_extra', 'protect', 'rename', 'clear_logs', 'vote_delete', 'vote_reset', 'delete_page', 'set_wiki_mode', 'password_set', 'password_reset', 'mod_misc', 'edit_cat', 'even_when_protected', 'upload_files', 'upload_new_version', 'create_page', 'php_in_pages'));
+ − 75
+ − 76
// DO NOT add new admin pages here! Use a plugin to call $paths->addAdminNode();
+ − 77
$this->addAdminNode('General', 'General Configuration', 'GeneralConfig');
+ − 78
$this->addAdminNode('General', 'File uploads', 'UploadConfig');
+ − 79
$this->addAdminNode('General', 'Allowed file types', 'UploadAllowedMimeTypes');
+ − 80
$this->addAdminNode('General', 'Manage Plugins', 'PluginManager');
+ − 81
$this->addAdminNode('General', 'Backup database', 'DBBackup');
+ − 82
$this->addAdminNode('Content', 'Manage Pages', 'PageManager');
+ − 83
$this->addAdminNode('Content', 'Edit page content', 'PageEditor');
+ − 84
$this->addAdminNode('Appearance', 'Manage themes', 'ThemeManager');
+ − 85
$this->addAdminNode('Users', 'Manage users', 'UserManager');
+ − 86
$this->addAdminNode('Users', 'Edit groups', 'GroupManager');
+ − 87
$this->addAdminNode('Users', 'Ban control', 'BanControl');
+ − 88
$this->addAdminNode('Users', 'Mass e-mail', 'MassEmail');
+ − 89
+ − 90
$code = $plugins->setHook('acl_rule_init');
+ − 91
foreach ( $code as $cmd )
+ − 92
{
+ − 93
eval($cmd);
+ − 94
}
+ − 95
+ − 96
$this->wiki_mode = (int)getConfig('wiki_mode')=='1';
+ − 97
$this->template_cache = Array();
+ − 98
}
+ − 99
function pathManager()
+ − 100
{
+ − 101
$this->__construct();
+ − 102
}
+ − 103
function init()
+ − 104
{
+ − 105
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 106
+ − 107
dc_here('paths: selecting master page data');
+ − 108
+ − 109
$code = $plugins->setHook('paths_init_before');
+ − 110
foreach ( $code as $cmd )
+ − 111
{
+ − 112
eval($cmd);
+ − 113
}
+ − 114
+ − 115
$e = $db->sql_query('SELECT name,urlname,namespace,special,visible,comments_on,protected,delvotes,delvote_ips,wiki_mode,password FROM '.table_prefix.'pages ORDER BY name;');
+ − 116
if( !$e )
+ − 117
{
+ − 118
$db->_die('The error seems to have occured while selecting the page information. File: includes/paths.php; line: '.__LINE__);
+ − 119
}
+ − 120
while($r = $db->fetchrow())
+ − 121
{
+ − 122
+ − 123
$r['urlname_nons'] = $r['urlname'];
+ − 124
$r['urlname'] = $this->nslist[$r['namespace']] . $r['urlname']; // Applies the User:/File:/etc prefixes to the URL names
+ − 125
+ − 126
if ( $r['delvotes'] == null)
+ − 127
{
+ − 128
$r['delvotes'] = 0;
+ − 129
}
+ − 130
if ( $r['protected'] == 0 || $r['protected'] == 1 )
+ − 131
{
+ − 132
$r['really_protected'] = (int)$r['protected'];
+ − 133
}
+ − 134
else if ( $r['protected'] == 2 && getConfig('wiki_mode') == '1')
+ − 135
{
+ − 136
$r['really_protected'] = 1;
+ − 137
}
+ − 138
else if ( $r['protected'] == 2 && getConfig('wiki_mode') == '0' )
+ − 139
{
+ − 140
$r['really_protected'] = 0;
+ − 141
}
+ − 142
+ − 143
$this->pages[$r['urlname']] = $r;
+ − 144
$this->pages[] =& $this->pages[$r['urlname']];
+ − 145
+ − 146
}
+ − 147
$db->free_result();
+ − 148
dc_here('paths: determining page ID');
+ − 149
if( isset($_GET['title']) )
+ − 150
{
+ − 151
if ( $_GET['title'] == '' && getConfig('main_page') != '' )
+ − 152
{
+ − 153
$this->main_page();
+ − 154
}
+ − 155
if(strstr($_GET['title'], ' '))
+ − 156
{
+ − 157
$loc = urldecode(rawurldecode($_SERVER['REQUEST_URI']));
+ − 158
$loc = str_replace(' ', '_', $loc);
+ − 159
$loc = str_replace('+', '_', $loc);
+ − 160
$loc = str_replace('%20', '_', $loc);
+ − 161
redirect($loc, 'Redirecting...', 'Space detected in the URL, please wait whilst you are redirected', 0);
+ − 162
exit;
+ − 163
}
+ − 164
$url_namespace_special = substr($_GET['title'], 0, strlen($this->nslist['Special']) );
+ − 165
$url_namespace_template = substr($_GET['title'], 0, strlen($this->nslist['Template']) );
+ − 166
if($url_namespace_special == $this->nslist['Special'] || $url_namespace_template == $this->nslist['Template'] )
+ − 167
{
+ − 168
$ex = explode('/', $_GET['title']);
+ − 169
$this->page = $ex[0];
+ − 170
}
+ − 171
else
+ − 172
{
+ − 173
$this->page = $_GET['title'];
+ − 174
}
+ − 175
$this->fullpage = $_GET['title'];
+ − 176
}
+ − 177
elseif( isset($_SERVER['PATH_INFO']) )
+ − 178
{
+ − 179
$pi = explode('/', $_SERVER['PATH_INFO']);
+ − 180
+ − 181
if( !isset($pi[1]) || (isset($pi[1]) && $pi[1] == '' && getConfig('main_page') != '') )
+ − 182
{
+ − 183
$this->main_page();
+ − 184
}
+ − 185
if( strstr($pi[1], ' ') )
+ − 186
{
+ − 187
$loc = str_replace(' ', '_', urldecode(rawurldecode($_SERVER['REQUEST_URI'])));
+ − 188
$loc = str_replace('+', '_', $loc);
+ − 189
$loc = str_replace('%20', '_', $loc);
+ − 190
redirect($loc, 'Redirecting...', 'Please wait whilst you are redirected', 3);
+ − 191
exit;
+ − 192
}
+ − 193
unset($pi[0]);
+ − 194
if( substr($pi[1], 0, strlen($this->nslist['Special'])) == $this->nslist['Special'] || substr($pi[1], 0, strlen($this->nslist['Template'])) == $this->nslist['Template'] )
+ − 195
{
+ − 196
$pi2 = $pi[1];
+ − 197
}
+ − 198
else
+ − 199
{
+ − 200
$pi2 = implode('/', $pi);
+ − 201
}
+ − 202
$this->page = $pi2;
+ − 203
$this->fullpage = implode('/', $pi);
+ − 204
}
+ − 205
else
+ − 206
{
+ − 207
$k = array_keys($_GET);
+ − 208
foreach($k as $c)
+ − 209
{
+ − 210
if(substr($c, 0, 1) == '/')
+ − 211
{
+ − 212
$this->page = substr($c, 1, strlen($c));
+ − 213
+ − 214
// Bugfix for apache somehow passing dots as underscores
+ − 215
global $mime_types;
+ − 216
+ − 217
$exts = array_keys($mime_types);
+ − 218
$exts = '(' . implode('|', $exts) . ')';
+ − 219
+ − 220
if ( preg_match( '#_'.$exts.'#i', $this->page ) )
+ − 221
{
+ − 222
$this->page = preg_replace( '#_'.$exts.'#i', '.\\1', $this->page );
+ − 223
}
+ − 224
+ − 225
$this->fullpage = $this->page;
+ − 226
+ − 227
if(substr($this->page, 0, strlen($this->nslist['Special']))==$this->nslist['Special'] || substr($this->page, 0, strlen($this->nslist['Template']))==$this->nslist['Template'])
+ − 228
{
+ − 229
$ex = explode('/', $this->page);
+ − 230
$this->page = $ex[0];
+ − 231
}
+ − 232
if(strstr($this->page, ' '))
+ − 233
{
+ − 234
$loc = str_replace(' ', '_', urldecode(rawurldecode($_SERVER['REQUEST_URI'])));
+ − 235
$loc = str_replace('+', '_', $loc);
+ − 236
$loc = str_replace('%20', '_', $loc);
+ − 237
redirect($loc, 'Redirecting...', 'Space in the URL detected, please wait whilst you are redirected', 0);
+ − 238
exit;
+ − 239
}
+ − 240
break;
+ − 241
}
+ − 242
}
+ − 243
if(!$this->page && !($this->page == '' && getConfig('main_page') == ''))
+ − 244
{
+ − 245
$this->main_page();
+ − 246
}
+ − 247
}
+ − 248
+ − 249
dc_here('paths: setting $paths->cpage');
+ − 250
+ − 251
if(isset($this->pages[$this->page]))
+ − 252
{
+ − 253
dc_here('paths: page existence verified, our page ID is: '.$this->page);
+ − 254
$this->page_exists = true;
+ − 255
$this->cpage = $this->pages[$this->page];
+ − 256
$this->namespace = $this->cpage['namespace'];
+ − 257
if(!isset($this->cpage['wiki_mode'])) $this->cpage['wiki_mode'] = 2;
+ − 258
+ − 259
// Determine the wiki mode for this page, now that we have this->cpage established
+ − 260
if($this->cpage['wiki_mode'] == 2)
+ − 261
{
+ − 262
$this->wiki_mode = (int)getConfig('wiki_mode');
+ − 263
}
+ − 264
else
+ − 265
{
+ − 266
$this->wiki_mode = $this->cpage['wiki_mode'];
+ − 267
}
+ − 268
// Allow the user to create/modify his user page uncondtionally (admins can still protect the page)
+ − 269
if($this->page == $this->nslist['User'].str_replace(' ', '_', $session->username))
+ − 270
{
+ − 271
$this->wiki_mode = true;
+ − 272
}
+ − 273
// And above all, if the site requires wiki mode to be off for non-logged-in users, disable it now
+ − 274
if(getConfig('wiki_mode_require_login')=='1' && !$session->user_logged_in)
+ − 275
{
+ − 276
$this->wiki_mode = false;
+ − 277
}
+ − 278
if($this->cpage['protected'] == 2)
+ − 279
{
+ − 280
// The page is semi-protected, determine permissions
+ − 281
if($session->user_logged_in && $session->reg_time + 60*60*24*4 < time())
+ − 282
{
+ − 283
$this->page_protected = 0;
+ − 284
}
+ − 285
else
+ − 286
{
+ − 287
$this->page_protected = 1;
+ − 288
}
+ − 289
}
+ − 290
else
+ − 291
{
+ − 292
$this->page_protected = $this->cpage['protected'];
+ − 293
}
+ − 294
}
+ − 295
else
+ − 296
{
+ − 297
dc_here('paths: page doesn\'t exist, creating new page in memory<br />our page ID is: '.$this->page);
+ − 298
$this->page_exists = false;
+ − 299
$this->cpage = Array(
+ − 300
'name'=>str_replace('_', ' ', $this->page),
+ − 301
'urlname'=>$this->page,
+ − 302
'namespace'=>'Article',
+ − 303
'special'=>0,
+ − 304
'visible'=>0,
+ − 305
'comments_on'=>1,
+ − 306
'protected'=>0,
+ − 307
'delvotes'=>0,
+ − 308
'delvote_ips'=>'',
+ − 309
'wiki_mode'=>2,
+ − 310
);
+ − 311
// Look for a namespace prefix in the urlname, and assign a different namespace, if necessary
+ − 312
$k = array_keys($this->nslist);
+ − 313
for($i=0;$i<sizeof($this->nslist);$i++)
+ − 314
{
+ − 315
$ln = strlen($this->nslist[$k[$i]]);
+ − 316
if( substr($this->page, 0, $ln) == $this->nslist[$k[$i]] )
+ − 317
{
+ − 318
$this->cpage['namespace'] = $k[$i];
+ − 319
$this->cpage['urlname_nons'] = substr($this->page, strlen($this->nslist[$this->cpage['namespace']]), strlen($this->page));
+ − 320
if(!isset($this->cpage['wiki_mode']))
+ − 321
{
+ − 322
$this->cpage['wiki_mode'] = 2;
+ − 323
}
+ − 324
}
+ − 325
}
+ − 326
$this->namespace = $this->cpage['namespace'];
+ − 327
+ − 328
if($this->namespace=='System')
+ − 329
{
+ − 330
$this->cpage['protected'] = 1;
+ − 331
}
+ − 332
if($this->namespace=='Special')
+ − 333
{
+ − 334
// Can't load nonexistent pages
+ − 335
$this->main_page();
+ − 336
}
+ − 337
// Allow the user to create/modify his user page uncondtionally (admins can still protect the page)
+ − 338
if($this->page == $this->nslist['User'].str_replace(' ', '_', $session->username))
+ − 339
{
+ − 340
$this->wiki_mode = true;
+ − 341
}
+ − 342
}
+ − 343
// This is used in the admin panel to keep track of form submission targets
+ − 344
$this->cpage['module'] = $this->cpage['urlname'];
+ − 345
+ − 346
// Page is set up, call any hooks
+ − 347
$code = $plugins->setHook('page_set');
+ − 348
foreach ( $code as $cmd )
+ − 349
{
+ − 350
eval($cmd);
+ − 351
}
+ − 352
+ − 353
$session->init_permissions();
+ − 354
}
+ − 355
+ − 356
function add_page($flags)
+ − 357
{
+ − 358
//dc_dump($flags, 'paths: page added by plugin:');
+ − 359
$flags['urlname_nons'] = $flags['urlname'];
+ − 360
$flags['urlname'] = $this->nslist[$flags['namespace']] . $flags['urlname']; // Applies the User:/File:/etc prefixes to the URL names
+ − 361
$pages_len = sizeof($this->pages)/2;
+ − 362
$this->pages[$pages_len] = $flags;
+ − 363
$this->pages[$flags['urlname']] =& $this->pages[$pages_len];
+ − 364
}
+ − 365
+ − 366
function main_page()
+ − 367
{
+ − 368
if( is_string(getConfig('main_page')) )
+ − 369
{
+ − 370
header('Location: '.makeUrl(getConfig('main_page')));
+ − 371
die('If you aren\'t redirected, <a href="' . makeUrl(getConfig('main_page')) . '">click here</a>.');
+ − 372
}
+ − 373
else
+ − 374
{
+ − 375
header('Location: '.makeUrl($this->pages[0]['urlname']));
+ − 376
die('If you aren\'t redirected, <a href="' . makeUrl($this->pages[0]['urlname']) . '">click here</a>.');
+ − 377
}
+ − 378
exit;
+ − 379
}
+ − 380
+ − 381
function sysmsg($n)
+ − 382
{
+ − 383
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 384
dc_here('paths: system message requested: '.$n);
+ − 385
$q = $db->sql_query('SELECT page_text, char_tag FROM '.table_prefix.'page_text WHERE page_id=\''.$db->escape($n).'\' AND namespace=\'System\'');
+ − 386
if( !$q )
+ − 387
{
+ − 388
$db->_die('Error during generic selection of system page data.');
+ − 389
}
+ − 390
if($db->numrows() < 1)
+ − 391
{
+ − 392
return false;
+ − 393
//$db->_die('Error during generic selection of system page data: there were no rows in the text table that matched the page text query.');
+ − 394
}
+ − 395
$r = $db->fetchrow();
+ − 396
$db->free_result();
+ − 397
$message = $r['page_text'];
+ − 398
+ − 399
$message = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '', $message);
+ − 400
+ − 401
return $message;
+ − 402
}
+ − 403
function get_pageid_from_url()
+ − 404
{
+ − 405
if(isset($_GET['title']))
+ − 406
{
+ − 407
if( $_GET['title'] == '' && getConfig('main_page') != '' )
+ − 408
{
+ − 409
$this->main_page();
+ − 410
}
+ − 411
if(strstr($_GET['title'], ' '))
+ − 412
{
+ − 413
$loc = urldecode(rawurldecode($_SERVER['REQUEST_URI']));
+ − 414
$loc = str_replace(' ', '_', $loc);
+ − 415
$loc = str_replace('+', '_', $loc);
+ − 416
header('Location: '.$loc);
+ − 417
exit;
+ − 418
}
+ − 419
$ret = $_GET['title'];
+ − 420
}
+ − 421
elseif(isset($_SERVER['PATH_INFO']))
+ − 422
{
+ − 423
$pi = explode('/', $_SERVER['PATH_INFO']);
+ − 424
+ − 425
if(!isset($pi[1]) || (isset($pi[1]) && $pi[1] == ''))
+ − 426
{
+ − 427
return false;
+ − 428
}
+ − 429
+ − 430
if(strstr($pi[1], ' '))
+ − 431
{
+ − 432
$loc = urldecode(rawurldecode($_SERVER['REQUEST_URI']));
+ − 433
$loc = str_replace(' ', '_', $loc);
+ − 434
$loc = str_replace('+', '_', $loc);
+ − 435
header('Location: '.$loc);
+ − 436
exit;
+ − 437
}
+ − 438
if( !( substr($pi[1], 0, strlen($this->nslist['Special'])) == $this->nslist['Special'] ) )
+ − 439
{
+ − 440
unset($pi[0]);
+ − 441
$pi[1] = implode('/', $pi);
+ − 442
}
+ − 443
$ret = $pi[1];
+ − 444
}
+ − 445
else
+ − 446
{
+ − 447
$k = array_keys($_GET);
+ − 448
foreach($k as $c)
+ − 449
{
+ − 450
if(substr($c, 0, 1) == '/')
+ − 451
{
+ − 452
$ret = substr($c, 1, strlen($c));
+ − 453
if(substr($ret, 0, strlen($this->nslist['Special'])) == $this->nslist['Special'] ||
+ − 454
substr($ret, 0, strlen($this->nslist['Admin'])) == $this->nslist['Admin'])
+ − 455
{
+ − 456
$ret = explode('/', $ret);
+ − 457
$ret = $ret[0];
+ − 458
}
+ − 459
break;
+ − 460
}
+ − 461
}
+ − 462
}
+ − 463
+ − 464
return ( isset($ret) ) ? $ret : false;
+ − 465
}
+ − 466
// Parses a (very carefully formed) array into Javascript code compatible with the Tigra Tree Menu used in the admin menu
+ − 467
function parseAdminTree()
+ − 468
{
+ − 469
$k = array_keys($this->admin_tree);
+ − 470
$i = 0;
+ − 471
$ret = '';
+ − 472
$ret .= "var TREE_ITEMS = [\n ['Administration panel home', 'javascript:ajaxPage(\'".$this->nslist['Admin']."Home\');',\n ";
+ − 473
foreach($k as $key)
+ − 474
{
+ − 475
$i++;
+ − 476
$ret .= "['".$key."', 'javascript:trees[0].toggle($i)', \n";
+ − 477
foreach($this->admin_tree[$key] as $c)
+ − 478
{
+ − 479
$i++;
+ − 480
$ret .= " ['".$c['name']."', 'javascript:ajaxPage(\\'".$this->nslist['Admin'].$c['pageid']."\\');'],\n";
+ − 481
}
+ − 482
$ret .= " ],\n";
+ − 483
}
+ − 484
$ret .= " ['Log out of admin panel', 'javascript:ajaxPage(\\'".$this->nslist['Admin']."AdminLogout\\');'],\n";
+ − 485
// I used this while I painstakingly wrote the Runt code that auto-expands certain nodes based on the value of a bitfield stored in a cookie. *shudders*
+ − 486
// $ret .= " ['(debug) Clear menu bitfield', 'javascript:createCookie(\\'admin_menu_state\\', \\'1\\', 365);'],\n";
+ − 487
$ret .= "]\n];";
+ − 488
return $ret;
+ − 489
}
+ − 490
function addAdminNode($section, $page_title, $url)
+ − 491
{
+ − 492
if(!isset($this->admin_tree[$section]))
+ − 493
{
+ − 494
$this->admin_tree[$section] = Array();
+ − 495
}
+ − 496
$this->admin_tree[$section][] = Array(
+ − 497
'name'=>$page_title,
+ − 498
'pageid'=>$url
+ − 499
);
+ − 500
}
+ − 501
function getParam($id = 0)
+ − 502
{
+ − 503
if(isset($_SERVER['PATH_INFO']))
+ − 504
{
+ − 505
$pi = explode('/', $_SERVER['PATH_INFO']);
+ − 506
$id = $id + 2;
+ − 507
return isset($pi[$id]) ? $pi[$id] : false;
+ − 508
}
+ − 509
else if( isset($_GET['title']) )
+ − 510
{
+ − 511
$pi = explode('/', $_GET['title']);
+ − 512
$id = $id + 1;
+ − 513
return isset($pi[$id]) ? $pi[$id] : false;
+ − 514
}
+ − 515
else
+ − 516
{
+ − 517
$k = array_keys($_GET);
+ − 518
foreach($k as $c)
+ − 519
{
+ − 520
if(substr($c, 0, 1) == '/')
+ − 521
{
+ − 522
+ − 523
// Bugfix for apache somehow passing dots as underscores
+ − 524
global $mime_types;
+ − 525
$exts = array_keys($mime_types);
+ − 526
$exts = '(' . implode('|', $exts) . ')';
+ − 527
if ( preg_match( '#_'.$exts.'#i', $c ) )
+ − 528
$c = preg_replace( '#_'.$exts.'#i', '.\\1', $c );
+ − 529
+ − 530
$pi = explode('/', $c);
+ − 531
$id = $id + 2;
+ − 532
return isset($pi[$id]) ? $pi[$id] : false;
+ − 533
}
+ − 534
}
+ − 535
return false;
+ − 536
}
+ − 537
}
+ − 538
+ − 539
function getAllParams()
+ − 540
{
+ − 541
if(isset($_SERVER['PATH_INFO']))
+ − 542
{
+ − 543
$pi = explode('/', $_SERVER['PATH_INFO']);
+ − 544
unset($pi[0], $pi[1]);
+ − 545
return implode('/', $pi);
+ − 546
}
+ − 547
else if( isset($_GET['title']) )
+ − 548
{
+ − 549
$pi = explode('/', $_GET['title']);
+ − 550
unset($pi[0]);
+ − 551
return implode('/', $pi);
+ − 552
}
+ − 553
else
+ − 554
{
+ − 555
$k = array_keys($_GET);
+ − 556
foreach($k as $c)
+ − 557
{
+ − 558
if(substr($c, 0, 1) == '/')
+ − 559
{
+ − 560
// Bugfix for apache somehow passing dots as underscores
+ − 561
global $mime_types;
+ − 562
$exts = array_keys($mime_types);
+ − 563
$exts = '(' . implode('|', $exts) . ')';
+ − 564
if ( preg_match( '#_'.$exts.'#i', $c ) )
+ − 565
$c = preg_replace( '#_'.$exts.'#i', '.\\1', $c );
+ − 566
+ − 567
$pi = explode('/', $c);
+ − 568
unset($pi[0], $pi[1]);
+ − 569
return implode('/', $pi);
+ − 570
}
+ − 571
}
+ − 572
return false;
+ − 573
}
+ − 574
}
+ − 575
+ − 576
/**
+ − 577
* Creates a new namespace in memory
+ − 578
* @param string $id the namespace ID
+ − 579
* @param string $prefix the URL prefix, must not be blank or already used
+ − 580
* @return bool true on success false on failure
+ − 581
*/
+ − 582
+ − 583
function create_namespace($id, $prefix)
+ − 584
{
+ − 585
if(in_array($prefix, $this->nslist))
+ − 586
{
+ − 587
// echo '<b>Warning:</b> pathManager::create_namespace: Prefix "'.$prefix.'" is already taken<br />';
+ − 588
return false;
+ − 589
}
+ − 590
if( isset($this->nslist[$id]) )
+ − 591
{
+ − 592
// echo '<b>Warning:</b> pathManager::create_namespace: Namespace ID "'.$prefix.'" is already taken<br />';
+ − 593
return false;
+ − 594
}
+ − 595
$this->nslist[$id] = $prefix;
+ − 596
}
+ − 597
+ − 598
/**
+ − 599
* Fetches the page texts for searching
+ − 600
*/
+ − 601
+ − 602
function fetch_page_search_texts()
+ − 603
{
+ − 604
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 605
$texts = Array();
+ − 606
$q = $db->sql_query('SELECT t.page_id,t.namespace,t.page_text,t.char_tag FROM '.table_prefix.'page_text AS t
+ − 607
LEFT JOIN '.table_prefix.'pages AS p
+ − 608
ON t.page_id=p.urlname
+ − 609
WHERE p.namespace=t.namespace
+ − 610
AND ( p.password=\'\' OR p.password=\'da39a3ee5e6b4b0d3255bfef95601890afd80709\' )
+ − 611
AND p.visible=1;'); // Only indexes "visible" pages
+ − 612
+ − 613
if( !$q )
+ − 614
{
+ − 615
return false;
+ − 616
}
+ − 617
while($row = $db->fetchrow())
+ − 618
{
+ − 619
$pid = $this->nslist[$row['namespace']] . $row['page_id'];
+ − 620
$texts[$pid] = $row['page_text'];
+ − 621
}
+ − 622
$db->free_result();
+ − 623
+ − 624
return $texts;
+ − 625
}
+ − 626
+ − 627
/**
+ − 628
* Fetches a MySQL search query to use for Searcher::searchMySQL()
+ − 629
*/
+ − 630
+ − 631
function fetch_page_search_resource()
+ − 632
{
+ − 633
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 634
// sha1('') returns "da39a3ee5e6b4b0d3255bfef95601890afd80709"
+ − 635
$texts = 'SELECT t.page_text,CONCAT(\'ns=\',t.namespace,\';pid=\',t.page_id) FROM '.table_prefix.'page_text AS t
+ − 636
LEFT JOIN '.table_prefix.'pages AS p
+ − 637
ON ( t.page_id=p.urlname AND t.namespace=p.namespace )
+ − 638
WHERE p.namespace=t.namespace
+ − 639
AND ( p.password=\'\' OR p.password=\'da39a3ee5e6b4b0d3255bfef95601890afd80709\' )
+ − 640
AND p.visible=1;'; // Only indexes "visible" pages
+ − 641
return $texts;
+ − 642
}
+ − 643
+ − 644
/**
+ − 645
* Rebuilds the search index
+ − 646
*/
+ − 647
+ − 648
function rebuild_search_index()
+ − 649
{
+ − 650
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 651
$search = new Searcher();
+ − 652
$texts = Array();
+ − 653
$textq = $db->sql_unbuffered_query($this->fetch_page_search_resource());
+ − 654
if(!$textq) $db->_die('');
+ − 655
while($row = $db->fetchrow_num())
+ − 656
{
+ − 657
$texts[(string)$row[1]] = $row[0];
+ − 658
}
+ − 659
$search->buildIndex($texts);
+ − 660
// echo '<pre>'.print_r($search->index, true).'</pre>';
+ − 661
// return;
+ − 662
$q = $db->sql_query('DELETE FROM '.table_prefix.'search_index');
+ − 663
if(!$q) return false;
+ − 664
$secs = Array();
+ − 665
$q = 'INSERT INTO '.table_prefix.'search_index(word,page_names) VALUES';
+ − 666
foreach($search->index as $word => $pages)
+ − 667
{
+ − 668
$secs[] = '(\''.$db->escape($word).'\', \''.$db->escape($pages).'\')';
+ − 669
}
+ − 670
$q .= implode(',', $secs);
+ − 671
unset($secs);
+ − 672
$q .= ';';
+ − 673
$result = $db->sql_query($q);
+ − 674
$db->free_result();
+ − 675
if($result)
+ − 676
return true;
+ − 677
else
+ − 678
$db->_die('The search index was trying to rebuild itself when the error occured.');
+ − 679
}
+ − 680
+ − 681
/**
+ − 682
* Partially rebuilds the search index, removing/inserting entries only for the current page
+ − 683
* @param string $page_id
+ − 684
* @param string $namespace
+ − 685
*/
+ − 686
+ − 687
function rebuild_page_index($page_id, $namespace)
+ − 688
{
+ − 689
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 690
if(!$db->sql_query('SELECT page_text FROM '.table_prefix.'page_text
+ − 691
WHERE page_id=\''.$db->escape($page_id).'\' AND namespace=\''.$db->escape($namespace).'\';'))
+ − 692
{
+ − 693
return $db->get_error();
+ − 694
}
+ − 695
$row = $db->fetchrow();
+ − 696
$db->free_result();
+ − 697
$search = new Searcher();
+ − 698
$search->buildIndex(Array("ns={$namespace};pid={$page_id}"=>$row['page_text']));
+ − 699
$new_index = $search->index;
+ − 700
+ − 701
$keys = array_keys($search->index);
+ − 702
foreach($keys as $i => $k)
+ − 703
{
+ − 704
$c =& $keys[$i];
+ − 705
$c = hexencode($c, '', '');
+ − 706
}
+ − 707
$keys = "word=0x" . implode ( " OR word=0x", $keys ) . "";
+ − 708
+ − 709
// Zap the cache
+ − 710
$cache = array_keys($search->index);
+ − 711
if ( count($cache) < 1 )
+ − 712
{
+ − 713
return false;
+ − 714
}
+ − 715
$cache = "query LIKE '%" . implode ( "%' OR query LIKE '%", $cache ) . "%'";
+ − 716
$db->sql_query('DELETE FROM '.table_prefix.'search_cache WHERE '.$cache);
+ − 717
+ − 718
$query = $db->sql_query('SELECT word,page_names FROM '.table_prefix.'search_index WHERE '.$keys.';');
+ − 719
+ − 720
while($row = $db->fetchrow())
+ − 721
{
+ − 722
$row['word'] = rtrim($row['word'], "\0");
+ − 723
$new_index[ $row['word'] ] = $row['page_names'] . ',' . $search->index[ $row['word'] ];
+ − 724
}
+ − 725
$db->free_result();
+ − 726
+ − 727
$db->sql_query('DELETE FROM '.table_prefix.'search_index WHERE '.$keys.';');
+ − 728
+ − 729
$secs = Array();
+ − 730
$q = 'INSERT INTO '.table_prefix.'search_index(word,page_names) VALUES';
+ − 731
foreach($new_index as $word => $pages)
+ − 732
{
+ − 733
$secs[] = '(\''.$db->escape($word).'\', \''.$db->escape($pages).'\')';
+ − 734
}
+ − 735
$q .= implode(',', $secs);
+ − 736
unset($secs);
+ − 737
$q .= ';';
+ − 738
if(!$db->check_query($q))
+ − 739
{
+ − 740
die('BUG: PathManager::rebuild_page_index: Query rejected by SQL parser:<pre>'.$q.'</pre>');
+ − 741
}
+ − 742
$result = $db->sql_query($q);
+ − 743
if($result)
+ − 744
return true;
+ − 745
else
+ − 746
$db->_die('The search index was trying to rebuild itself when the error occured.');
+ − 747
+ − 748
}
+ − 749
+ − 750
/**
+ − 751
* Creates an instance of the Searcher class, including index info
+ − 752
* @return object
+ − 753
*/
+ − 754
+ − 755
function makeSearcher($match_case = false)
+ − 756
{
+ − 757
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 758
$search = new Searcher();
+ − 759
$q = $db->sql_query('SELECT word,page_names FROM '.table_prefix.'search_index;');
+ − 760
if(!$q)
+ − 761
{
+ − 762
echo $db->get_error();
+ − 763
return false;
+ − 764
}
+ − 765
$idx = Array();
+ − 766
while($row = $db->fetchrow($q))
+ − 767
{
+ − 768
$row['word'] = rtrim($row['word'], "\0");
+ − 769
$idx[$row['word']] = $row['page_names'];
+ − 770
}
+ − 771
$db->free_result();
+ − 772
$search->index = $idx;
+ − 773
if($match_case)
+ − 774
$search->match_case = true;
+ − 775
return $search;
+ − 776
}
+ − 777
+ − 778
/**
+ − 779
* Creates an associative array filled with the values of all the page titles
+ − 780
* @return array
+ − 781
*/
+ − 782
+ − 783
function get_page_titles()
+ − 784
{
+ − 785
$texts = Array();
+ − 786
for ( $i = 0; $i < sizeof($this->pages) / 2; $i++ )
+ − 787
{
+ − 788
$texts[$this->pages[$i]['urlname']] = $this->pages[$i]['name'];
+ − 789
}
+ − 790
return $texts;
+ − 791
}
+ − 792
+ − 793
/**
+ − 794
* Creates an instance of the Searcher class, including index info for page titles
+ − 795
* @return object
+ − 796
*/
+ − 797
+ − 798
function makeTitleSearcher($match_case = false)
+ − 799
{
+ − 800
global $db, $session, $paths, $template, $plugins; // Common objects
+ − 801
$search = new Searcher();
+ − 802
$texts = $this->get_page_titles();
+ − 803
$search->buildIndex($texts);
+ − 804
if($match_case)
+ − 805
$search->match_case = true;
+ − 806
return $search;
+ − 807
}
+ − 808
+ − 809
}
+ − 810
+ − 811
?>