16 * @see http://enanocms.org/Help:API_Documentation |
16 * @see http://enanocms.org/Help:API_Documentation |
17 */ |
17 */ |
18 |
18 |
19 class pathManager |
19 class pathManager |
20 { |
20 { |
21 public $title, $pages, $custom_page, $cpage, $page, $fullpage, $page_exists, $page_id, $namespace, $nslist, $admin_tree, $wiki_mode, $page_protected, $template_cache, $external_api_page; |
21 public $title, $pages, $custom_page, $cpage, $page, $fullpage, $page_exists, $page_id, $namespace, $nslist, $admin_tree, $wiki_mode, $page_protected, $template_cache, $external_api_page; |
22 |
22 |
23 /** |
23 /** |
24 * List of custom processing functions for namespaces. This is protected so trying to do anything with it will throw an error. |
24 * List of custom processing functions for namespaces. This is protected so trying to do anything with it will throw an error. |
25 * @access private |
25 * @access private |
26 * @var array |
26 * @var array |
27 */ |
27 */ |
28 |
28 |
29 protected $namespace_processors; |
29 protected $namespace_processors; |
30 |
30 |
31 function __construct() |
31 function __construct() |
32 { |
32 { |
33 global $db, $session, $paths, $template, $plugins; // Common objects |
33 global $db, $session, $paths, $template, $plugins; // Common objects |
34 |
34 |
35 $GLOBALS['paths'] =& $this; |
35 $GLOBALS['paths'] =& $this; |
36 $this->pages = Array(); |
36 $this->pages = Array(); |
37 |
37 |
38 // DEFINE NAMESPACES HERE |
38 // DEFINE NAMESPACES HERE |
39 // The key names should NOT EVER be changed, or Enano will be very broken |
39 // The key names should NOT EVER be changed, or Enano will be very broken |
40 $namespace_delimiter = ( defined('WINDOWS_MOD_REWRITE_WORKAROUNDS') ) ? '.' : ':'; |
40 $namespace_delimiter = ( defined('WINDOWS_MOD_REWRITE_WORKAROUNDS') ) ? '.' : ':'; |
41 $this->nslist = Array( |
41 $this->nslist = Array( |
42 'Article' => '', |
42 'Article' => '', |
43 'User' => 'User' . $namespace_delimiter, |
43 'User' => 'User' . $namespace_delimiter, |
44 'File' => 'File' . $namespace_delimiter, |
44 'File' => 'File' . $namespace_delimiter, |
45 'Help' => 'Help' . $namespace_delimiter, |
45 'Help' => 'Help' . $namespace_delimiter, |
46 'Admin' => 'Admin' . $namespace_delimiter, |
46 'Admin' => 'Admin' . $namespace_delimiter, |
47 'Special' => 'Special' . $namespace_delimiter, |
47 'Special' => 'Special' . $namespace_delimiter, |
48 'System' => 'Enano' . $namespace_delimiter, |
48 'System' => 'Enano' . $namespace_delimiter, |
49 'Template' => 'Template' . $namespace_delimiter, |
49 'Template' => 'Template' . $namespace_delimiter, |
50 'Category' => 'Category' . $namespace_delimiter, |
50 'Category' => 'Category' . $namespace_delimiter, |
51 'API' => 'SystemAPI' . $namespace_delimiter, |
51 'API' => 'SystemAPI' . $namespace_delimiter, |
52 'Project' => sanitize_page_id(getConfig('site_name')) . $namespace_delimiter, |
52 'Project' => sanitize_page_id(getConfig('site_name')) . $namespace_delimiter, |
53 ); |
53 ); |
54 |
54 |
55 // ACL types |
55 // ACL types |
56 // These can also be added from within plugins |
56 // These can also be added from within plugins |
57 |
57 |
58 $session->register_acl_type('read', AUTH_ALLOW, 'perm_read'); |
58 $session->register_acl_type('read', AUTH_ALLOW, 'perm_read'); |
59 $session->register_acl_type('post_comments', AUTH_ALLOW, 'perm_post_comments', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
59 $session->register_acl_type('post_comments', AUTH_ALLOW, 'perm_post_comments', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
60 $session->register_acl_type('edit_comments', AUTH_ALLOW, 'perm_edit_comments', Array('post_comments'), 'Article|User|Project|Template|File|Help|System|Category'); |
60 $session->register_acl_type('edit_comments', AUTH_ALLOW, 'perm_edit_comments', Array('post_comments'), 'Article|User|Project|Template|File|Help|System|Category'); |
61 $session->register_acl_type('edit_page', AUTH_WIKIMODE, 'perm_edit_page', Array('view_source'), 'Article|User|Project|Template|File|Help|System|Category'); |
61 $session->register_acl_type('edit_page', AUTH_WIKIMODE, 'perm_edit_page', Array('view_source'), 'Article|User|Project|Template|File|Help|System|Category'); |
62 $session->register_acl_type('edit_wysiwyg', AUTH_ALLOW, 'perm_edit_wysiwyg', Array(), 'Article|User|Project|Template|File|Help|System|Category'); |
62 $session->register_acl_type('edit_wysiwyg', AUTH_ALLOW, 'perm_edit_wysiwyg', Array(), 'Article|User|Project|Template|File|Help|System|Category'); |
63 $session->register_acl_type('view_source', AUTH_WIKIMODE, 'perm_view_source', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); // Only used if the page is protected |
63 $session->register_acl_type('view_source', AUTH_WIKIMODE, 'perm_view_source', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); // Only used if the page is protected |
64 $session->register_acl_type('mod_comments', AUTH_DISALLOW, 'perm_mod_comments', Array('edit_comments'), 'Article|User|Project|Template|File|Help|System|Category'); |
64 $session->register_acl_type('mod_comments', AUTH_DISALLOW, 'perm_mod_comments', Array('edit_comments'), 'Article|User|Project|Template|File|Help|System|Category'); |
65 $session->register_acl_type('history_view', AUTH_WIKIMODE, 'perm_history_view', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
65 $session->register_acl_type('history_view', AUTH_WIKIMODE, 'perm_history_view', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
66 $session->register_acl_type('history_rollback', AUTH_DISALLOW, 'perm_history_rollback', Array('history_view'), 'Article|User|Project|Template|File|Help|System|Category'); |
66 $session->register_acl_type('history_rollback', AUTH_DISALLOW, 'perm_history_rollback', Array('history_view'), 'Article|User|Project|Template|File|Help|System|Category'); |
67 $session->register_acl_type('history_rollback_extra', AUTH_DISALLOW, 'perm_history_rollback_extra', Array('history_rollback'), 'Article|User|Project|Template|File|Help|System|Category'); |
67 $session->register_acl_type('history_rollback_extra', AUTH_DISALLOW, 'perm_history_rollback_extra', Array('history_rollback'), 'Article|User|Project|Template|File|Help|System|Category'); |
68 $session->register_acl_type('protect', AUTH_DISALLOW, 'perm_protect', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
68 $session->register_acl_type('protect', AUTH_DISALLOW, 'perm_protect', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
69 $session->register_acl_type('rename', AUTH_WIKIMODE, 'perm_rename', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
69 $session->register_acl_type('rename', AUTH_WIKIMODE, 'perm_rename', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
70 $session->register_acl_type('clear_logs', AUTH_DISALLOW, 'perm_clear_logs', Array('read', 'protect', 'even_when_protected'), 'Article|User|Project|Template|File|Help|System|Category'); |
70 $session->register_acl_type('clear_logs', AUTH_DISALLOW, 'perm_clear_logs', Array('read', 'protect', 'even_when_protected'), 'Article|User|Project|Template|File|Help|System|Category'); |
71 $session->register_acl_type('vote_delete', AUTH_ALLOW, 'perm_vote_delete', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
71 $session->register_acl_type('vote_delete', AUTH_ALLOW, 'perm_vote_delete', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
72 $session->register_acl_type('vote_reset', AUTH_DISALLOW, 'perm_vote_reset', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
72 $session->register_acl_type('vote_reset', AUTH_DISALLOW, 'perm_vote_reset', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
73 $session->register_acl_type('delete_page', AUTH_DISALLOW, 'perm_delete_page', Array(), 'Article|User|Project|Template|File|Help|System|Category'); |
73 $session->register_acl_type('delete_page', AUTH_DISALLOW, 'perm_delete_page', Array(), 'Article|User|Project|Template|File|Help|System|Category'); |
74 $session->register_acl_type('tag_create', AUTH_ALLOW, 'perm_tag_create', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
74 $session->register_acl_type('tag_create', AUTH_ALLOW, 'perm_tag_create', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
75 $session->register_acl_type('tag_delete_own', AUTH_ALLOW, 'perm_tag_delete_own', Array('read', 'tag_create'), 'Article|User|Project|Template|File|Help|System|Category'); |
75 $session->register_acl_type('tag_delete_own', AUTH_ALLOW, 'perm_tag_delete_own', Array('read', 'tag_create'), 'Article|User|Project|Template|File|Help|System|Category'); |
76 $session->register_acl_type('tag_delete_other', AUTH_DISALLOW, 'perm_tag_delete_other', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
76 $session->register_acl_type('tag_delete_other', AUTH_DISALLOW, 'perm_tag_delete_other', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
77 $session->register_acl_type('set_wiki_mode', AUTH_DISALLOW, 'perm_set_wiki_mode', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
77 $session->register_acl_type('set_wiki_mode', AUTH_DISALLOW, 'perm_set_wiki_mode', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
78 $session->register_acl_type('password_set', AUTH_DISALLOW, 'perm_password_set', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
78 $session->register_acl_type('password_set', AUTH_DISALLOW, 'perm_password_set', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
79 $session->register_acl_type('password_reset', AUTH_DISALLOW, 'perm_password_reset', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
79 $session->register_acl_type('password_reset', AUTH_DISALLOW, 'perm_password_reset', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
80 $session->register_acl_type('mod_misc', AUTH_DISALLOW, 'perm_mod_misc', Array(), 'All'); |
80 $session->register_acl_type('mod_misc', AUTH_DISALLOW, 'perm_mod_misc', Array(), 'All'); |
81 $session->register_acl_type('edit_cat', AUTH_WIKIMODE, 'perm_edit_cat', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
81 $session->register_acl_type('edit_cat', AUTH_WIKIMODE, 'perm_edit_cat', Array('read'), 'Article|User|Project|Template|File|Help|System|Category'); |
82 $session->register_acl_type('even_when_protected', AUTH_DISALLOW, 'perm_even_when_protected', Array('edit_page', 'rename', 'mod_comments', 'edit_cat'), 'Article|User|Project|Template|File|Help|System|Category'); |
82 $session->register_acl_type('even_when_protected', AUTH_DISALLOW, 'perm_even_when_protected', Array('edit_page', 'rename', 'mod_comments', 'edit_cat'), 'Article|User|Project|Template|File|Help|System|Category'); |
83 $session->register_acl_type('create_page', AUTH_WIKIMODE, 'perm_create_page', Array(), 'All'); |
83 $session->register_acl_type('create_page', AUTH_WIKIMODE, 'perm_create_page', Array(), 'All'); |
84 $session->register_acl_type('upload_files', AUTH_DISALLOW, 'perm_upload_files', Array('create_page'), 'All'); |
84 $session->register_acl_type('upload_files', AUTH_DISALLOW, 'perm_upload_files', Array('create_page'), 'All'); |
85 $session->register_acl_type('upload_new_version', AUTH_WIKIMODE, 'perm_upload_new_version', Array('upload_files'), 'All'); |
85 $session->register_acl_type('upload_new_version', AUTH_WIKIMODE, 'perm_upload_new_version', Array('upload_files'), 'All'); |
86 $session->register_acl_type('html_in_pages', AUTH_DISALLOW, 'perm_html_in_pages', Array('edit_page'), 'Article|User|Project|Template|File|Help|System|Category|Admin'); |
86 $session->register_acl_type('html_in_pages', AUTH_DISALLOW, 'perm_html_in_pages', Array('edit_page'), 'Article|User|Project|Template|File|Help|System|Category|Admin'); |
87 $session->register_acl_type('php_in_pages', AUTH_DISALLOW, 'perm_php_in_pages', Array('edit_page', 'html_in_pages'), 'Article|User|Project|Template|File|Help|System|Category|Admin'); |
87 $session->register_acl_type('php_in_pages', AUTH_DISALLOW, 'perm_php_in_pages', Array('edit_page', 'html_in_pages'), 'Article|User|Project|Template|File|Help|System|Category|Admin'); |
88 $session->register_acl_type('custom_user_title', AUTH_DISALLOW, 'perm_custom_user_title', Array(), 'User|Special'); |
88 $session->register_acl_type('custom_user_title', AUTH_DISALLOW, 'perm_custom_user_title', Array(), 'User|Special'); |
89 $session->register_acl_type('edit_acl', AUTH_DISALLOW, 'perm_edit_acl', Array()); |
89 $session->register_acl_type('edit_acl', AUTH_DISALLOW, 'perm_edit_acl', Array()); |
90 |
90 |
91 // DO NOT add new admin pages here! Use a plugin to call $paths->addAdminNode(); |
91 // DO NOT add new admin pages here! Use a plugin to call $paths->addAdminNode(); |
92 $this->addAdminNode('adm_cat_general', 'adm_page_general_config', 'GeneralConfig', array(2, 2)); |
92 $this->addAdminNode('adm_cat_general', 'adm_page_general_config', 'GeneralConfig', array(2, 2)); |
93 $this->addAdminNode('adm_cat_general', 'adm_page_file_uploads', 'UploadConfig', array(2, 5)); |
93 $this->addAdminNode('adm_cat_general', 'adm_page_file_uploads', 'UploadConfig', array(2, 5)); |
94 $this->addAdminNode('adm_cat_general', 'adm_page_file_types', 'UploadAllowedMimeTypes', array(1, 5)); |
94 $this->addAdminNode('adm_cat_general', 'adm_page_file_types', 'UploadAllowedMimeTypes', array(1, 5)); |
95 $this->addAdminNode('adm_cat_content', 'adm_page_manager', 'PageManager', array(1, 4)); |
95 $this->addAdminNode('adm_cat_content', 'adm_page_manager', 'PageManager', array(1, 4)); |
96 $this->addAdminNode('adm_cat_content', 'adm_page_editor', 'PageEditor', array(3, 3)); |
96 $this->addAdminNode('adm_cat_content', 'adm_page_editor', 'PageEditor', array(3, 3)); |
97 $this->addAdminNode('adm_cat_content', 'adm_page_pg_groups', 'PageGroups', array(4, 3)); |
97 $this->addAdminNode('adm_cat_content', 'adm_page_pg_groups', 'PageGroups', array(4, 3)); |
98 $this->addAdminNode('adm_cat_appearance', 'adm_page_themes', 'ThemeManager', array(4, 4)); |
98 $this->addAdminNode('adm_cat_appearance', 'adm_page_themes', 'ThemeManager', array(4, 4)); |
99 $this->addAdminNode('adm_cat_appearance', 'adm_page_plugins', 'PluginManager', array(2, 4)); |
99 $this->addAdminNode('adm_cat_appearance', 'adm_page_plugins', 'PluginManager', array(2, 4)); |
100 $this->addAdminNode('adm_cat_appearance', 'adm_page_db_backup', 'DBBackup', array(1, 2)); |
100 $this->addAdminNode('adm_cat_appearance', 'adm_page_db_backup', 'DBBackup', array(1, 2)); |
101 $this->addAdminNode('adm_cat_appearance', 'adm_page_lang_manager', 'LangManager', array(1, 3)); |
101 $this->addAdminNode('adm_cat_appearance', 'adm_page_lang_manager', 'LangManager', array(1, 3)); |
102 $this->addAdminNode('adm_cat_appearance', 'adm_page_cache_manager', 'CacheManager', array(3, 1)); |
102 $this->addAdminNode('adm_cat_appearance', 'adm_page_cache_manager', 'CacheManager', array(3, 1)); |
103 $this->addAdminNode('adm_cat_users', 'adm_page_users', 'UserManager', array(3, 5)); |
103 $this->addAdminNode('adm_cat_users', 'adm_page_users', 'UserManager', array(3, 5)); |
104 $this->addAdminNode('adm_cat_users', 'adm_page_user_groups', 'GroupManager', array(3, 2)); |
104 $this->addAdminNode('adm_cat_users', 'adm_page_user_groups', 'GroupManager', array(3, 2)); |
105 $this->addAdminNode('adm_cat_users', 'adm_page_coppa', 'COPPA', array(4, 1)); |
105 $this->addAdminNode('adm_cat_users', 'adm_page_coppa', 'COPPA', array(4, 1)); |
106 $this->addAdminNode('adm_cat_users', 'adm_page_mass_email', 'MassEmail', array(2, 3)); |
106 $this->addAdminNode('adm_cat_users', 'adm_page_mass_email', 'MassEmail', array(2, 3)); |
107 $this->addAdminNode('adm_cat_users', 'adm_page_user_ranks', 'UserRanks', array(4, 5)); |
107 $this->addAdminNode('adm_cat_users', 'adm_page_user_ranks', 'UserRanks', array(4, 5)); |
108 $this->addAdminNode('adm_cat_security', 'adm_page_security_log', 'SecurityLog', array(3, 4)); |
108 $this->addAdminNode('adm_cat_security', 'adm_page_security_log', 'SecurityLog', array(3, 4)); |
109 $this->addAdminNode('adm_cat_security', 'adm_page_ban_control', 'BanControl', array(2, 1)); |
109 $this->addAdminNode('adm_cat_security', 'adm_page_ban_control', 'BanControl', array(2, 1)); |
110 |
110 |
111 $code = $plugins->setHook('acl_rule_init'); |
111 $code = $plugins->setHook('acl_rule_init'); |
112 foreach ( $code as $cmd ) |
112 foreach ( $code as $cmd ) |
113 { |
113 { |
114 eval($cmd); |
114 eval($cmd); |
115 } |
115 } |
116 |
116 |
117 $this->wiki_mode = ( getConfig('wiki_mode') == '1' ) ? 1 : 0; |
117 $this->wiki_mode = ( getConfig('wiki_mode') == '1' ) ? 1 : 0; |
118 $this->template_cache = Array(); |
118 $this->template_cache = Array(); |
119 } |
119 } |
120 |
120 |
121 function init($title) |
121 function init($title) |
122 { |
122 { |
123 global $db, $session, $paths, $template, $plugins; // Common objects |
123 global $db, $session, $paths, $template, $plugins; // Common objects |
124 global $lang; |
124 global $lang; |
125 global $cache; |
125 global $cache; |
126 |
126 |
127 $code = $plugins->setHook('paths_init_before'); |
127 $code = $plugins->setHook('paths_init_before'); |
128 foreach ( $code as $cmd ) |
128 foreach ( $code as $cmd ) |
129 { |
129 { |
130 eval($cmd); |
130 eval($cmd); |
131 } |
131 } |
132 |
132 |
133 if ( defined('ENANO_INTERFACE_INDEX') || defined('ENANO_INTERFACE_AJAX') || defined('IN_ENANO_UPGRADE') ) |
133 if ( defined('ENANO_INTERFACE_INDEX') || defined('ENANO_INTERFACE_AJAX') || defined('IN_ENANO_UPGRADE') ) |
134 { |
134 { |
135 if ( empty($title) ) |
135 if ( empty($title) ) |
136 $title = get_title(); |
136 $title = get_title(); |
137 |
137 |
138 if ( empty($title) && !have_blank_urlname_page() ) |
138 if ( empty($title) && !have_blank_urlname_page() ) |
139 { |
139 { |
140 $this->main_page(); |
140 $this->main_page(); |
141 } |
141 } |
142 if ( strstr($title, ' ') || strstr($title, '+') || strstr($title, '%20') ) |
142 if ( strstr($title, ' ') || strstr($title, '+') || strstr($title, '%20') ) |
143 { |
143 { |
144 $title = sanitize_page_id($title); |
144 $title = sanitize_page_id($title); |
145 redirect(makeUrl($title), '', '', 0); |
145 redirect(makeUrl($title), '', '', 0); |
146 } |
146 } |
147 $title = sanitize_page_id($title); |
147 $title = sanitize_page_id($title); |
148 // We've got the title, pull the namespace from it |
148 // We've got the title, pull the namespace from it |
149 $namespace = 'Article'; |
149 $namespace = 'Article'; |
150 $page_id = $title; |
150 $page_id = $title; |
151 foreach ( $this->nslist as $ns => $prefix ) |
151 foreach ( $this->nslist as $ns => $prefix ) |
152 { |
152 { |
153 $prefix_len = strlen($prefix); |
153 $prefix_len = strlen($prefix); |
154 if ( substr($title, 0, $prefix_len) == $prefix ) |
154 if ( substr($title, 0, $prefix_len) == $prefix ) |
155 { |
155 { |
156 $page_id = substr($title, $prefix_len); |
156 $page_id = substr($title, $prefix_len); |
157 $namespace = $ns; |
157 $namespace = $ns; |
158 } |
158 } |
159 } |
159 } |
160 $this->namespace = $namespace; |
160 $this->namespace = $namespace; |
161 $this->fullpage = $title; |
161 $this->fullpage = $title; |
162 if ( $namespace == 'Special' || $namespace == 'Admin' ) |
162 if ( $namespace == 'Special' || $namespace == 'Admin' ) |
163 { |
163 { |
164 list($page_id) = explode('/', $page_id); |
164 list($page_id) = explode('/', $page_id); |
165 } |
165 } |
166 $this->page = $this->nslist[$namespace] . $page_id; |
166 $this->page = $this->nslist[$namespace] . $page_id; |
167 $this->page_id = $page_id; |
167 $this->page_id = $page_id; |
168 // die("All done setting parameters. What we've got:<br/>namespace: $namespace<br/>fullpage: $this->fullpage<br/>page: $this->page<br/>page_id: $this->page_id"); |
168 // die("All done setting parameters. What we've got:<br/>namespace: $namespace<br/>fullpage: $this->fullpage<br/>page: $this->page<br/>page_id: $this->page_id"); |
169 } |
169 } |
170 else |
170 else |
171 { |
171 { |
172 // Starting up Enano with the API from a page that wants to do its own thing. Generate |
172 // Starting up Enano with the API from a page that wants to do its own thing. Generate |
173 // metadata for an anonymous page and avoid redirection at all costs. |
173 // metadata for an anonymous page and avoid redirection at all costs. |
174 if ( isset($GLOBALS['title']) ) |
174 if ( isset($GLOBALS['title']) ) |
175 { |
175 { |
176 $title =& $GLOBALS['title']; |
176 $title =& $GLOBALS['title']; |
177 } |
177 } |
178 else |
178 else |
179 { |
179 { |
180 $title = basename($_SERVER['SCRIPT_NAME']); |
180 $title = basename($_SERVER['SCRIPT_NAME']); |
181 } |
181 } |
182 $base_uri = scriptPath == '' ? ltrim($_SERVER['SCRIPT_NAME'], '/') : str_replace( scriptPath . '/', '', $_SERVER['SCRIPT_NAME'] ); |
182 $base_uri = scriptPath == '' ? ltrim($_SERVER['SCRIPT_NAME'], '/') : str_replace( scriptPath . '/', '', $_SERVER['SCRIPT_NAME'] ); |
183 |
183 |
184 $this->page = $this->nslist['API'] . sanitize_page_id($base_uri); |
184 $this->page = $this->nslist['API'] . sanitize_page_id($base_uri); |
185 $this->fullpage = $this->nslist['API'] . sanitize_page_id($base_uri); |
185 $this->fullpage = $this->nslist['API'] . sanitize_page_id($base_uri); |
186 $this->namespace = 'API'; |
186 $this->namespace = 'API'; |
187 $this->cpage = array( |
187 $this->cpage = array( |
188 'name' => $title, |
188 'name' => $title, |
189 'urlname' => sanitize_page_id($base_uri), |
189 'urlname' => sanitize_page_id($base_uri), |
190 'namespace' => 'API', |
190 'namespace' => 'API', |
191 'special' => 1, |
191 'special' => 1, |
192 'visible' => 1, |
192 'visible' => 1, |
193 'comments_on' => 1, |
193 'comments_on' => 1, |
194 'protected' => 1, |
194 'protected' => 1, |
195 'delvotes' => 0, |
195 'delvotes' => 0, |
196 'delvote_ips' => '', |
196 'delvote_ips' => '', |
197 'page_format' => getConfig('default_page_format', 'wikitext') |
197 'page_format' => getConfig('default_page_format', 'wikitext') |
198 ); |
198 ); |
199 $this->external_api_page = true; |
199 $this->external_api_page = true; |
200 $code = $plugins->setHook('paths_external_api_page'); |
200 $code = $plugins->setHook('paths_external_api_page'); |
201 foreach ( $code as $cmd ) |
201 foreach ( $code as $cmd ) |
202 { |
202 { |
203 eval($cmd); |
203 eval($cmd); |
204 } |
204 } |
205 } |
205 } |
206 |
206 |
207 $this->page = sanitize_page_id($this->page); |
207 $this->page = sanitize_page_id($this->page); |
208 $this->fullpage = sanitize_page_id($this->fullpage); |
208 $this->fullpage = sanitize_page_id($this->fullpage); |
209 |
209 |
210 if(isset($this->pages[$this->page])) |
210 if(isset($this->pages[$this->page])) |
211 { |
211 { |
212 $this->page_exists = true; |
212 $this->page_exists = true; |
213 $this->cpage = $this->pages[$this->page]; |
213 $this->cpage = $this->pages[$this->page]; |
214 $this->page_id =& $this->cpage['urlname_nons']; |
214 $this->page_id =& $this->cpage['urlname_nons']; |
215 $this->namespace = $this->cpage['namespace']; |
215 $this->namespace = $this->cpage['namespace']; |
216 if(!isset($this->cpage['wiki_mode'])) $this->cpage['wiki_mode'] = 2; |
216 if(!isset($this->cpage['wiki_mode'])) $this->cpage['wiki_mode'] = 2; |
217 |
217 |
218 // Determine the wiki mode for this page, now that we have this->cpage established |
218 // Determine the wiki mode for this page, now that we have this->cpage established |
219 if($this->cpage['wiki_mode'] == 2) |
219 if($this->cpage['wiki_mode'] == 2) |
220 { |
220 { |
221 $this->wiki_mode = (int)getConfig('wiki_mode'); |
221 $this->wiki_mode = (int)getConfig('wiki_mode'); |
222 } |
222 } |
223 else |
223 else |
224 { |
224 { |
225 $this->wiki_mode = $this->cpage['wiki_mode']; |
225 $this->wiki_mode = $this->cpage['wiki_mode']; |
226 } |
226 } |
227 // Allow the user to create/modify his user page uncondtionally (admins can still protect the page) |
227 // Allow the user to create/modify his user page uncondtionally (admins can still protect the page) |
228 if($this->page == $this->nslist['User'].str_replace(' ', '_', $session->username)) |
228 if($this->page == $this->nslist['User'].str_replace(' ', '_', $session->username)) |
229 { |
229 { |
230 $this->wiki_mode = true; |
230 $this->wiki_mode = true; |
231 } |
231 } |
232 // And above all, if the site requires wiki mode to be off for non-logged-in users, disable it now |
232 // And above all, if the site requires wiki mode to be off for non-logged-in users, disable it now |
233 if(getConfig('wiki_mode_require_login')=='1' && !$session->user_logged_in) |
233 if(getConfig('wiki_mode_require_login')=='1' && !$session->user_logged_in) |
234 { |
234 { |
235 $this->wiki_mode = false; |
235 $this->wiki_mode = false; |
236 } |
236 } |
237 if($this->cpage['protected'] == 2) |
237 if($this->cpage['protected'] == 2) |
238 { |
238 { |
239 // The page is semi-protected, determine permissions |
239 // The page is semi-protected, determine permissions |
240 if($session->user_logged_in && $session->reg_time + 60*60*24*4 < time()) |
240 if($session->user_logged_in && $session->reg_time + 60*60*24*4 < time()) |
241 { |
241 { |
242 $this->page_protected = 0; |
242 $this->page_protected = 0; |
243 } |
243 } |
244 else |
244 else |
245 { |
245 { |
246 $this->page_protected = 1; |
246 $this->page_protected = 1; |
247 } |
247 } |
248 } |
248 } |
249 else |
249 else |
250 { |
250 { |
251 $this->page_protected = $this->cpage['protected']; |
251 $this->page_protected = $this->cpage['protected']; |
252 } |
252 } |
253 } |
253 } |
254 else |
254 else |
255 { |
255 { |
256 $this->page_exists = false; |
256 $this->page_exists = false; |
257 $page_name = dirtify_page_id($this->page); |
257 $page_name = dirtify_page_id($this->page); |
258 $page_name = str_replace('_', ' ', $page_name); |
258 $page_name = str_replace('_', ' ', $page_name); |
259 |
259 |
260 $pid_cleaned = sanitize_page_id($this->page); |
260 $pid_cleaned = sanitize_page_id($this->page); |
261 if ( $pid_cleaned != $this->page ) |
261 if ( $pid_cleaned != $this->page ) |
262 { |
262 { |
263 redirect(makeUrl($pid_cleaned), 'Sanitizer message', 'page id sanitized', 0); |
263 redirect(makeUrl($pid_cleaned), 'Sanitizer message', 'page id sanitized', 0); |
264 } |
264 } |
265 |
265 |
266 if ( !is_array($this->cpage) ) |
266 if ( !is_array($this->cpage) ) |
267 { |
267 { |
268 $this->cpage = Array( |
268 $this->cpage = Array( |
269 'name' => $page_name, |
269 'name' => $page_name, |
270 'urlname' => $this->page, |
270 'urlname' => $this->page, |
271 'namespace' => 'Article', |
271 'namespace' => 'Article', |
272 'special' => 0, |
272 'special' => 0, |
273 'visible' => 0, |
273 'visible' => 0, |
274 'comments_on' => 1, |
274 'comments_on' => 1, |
275 'protected' => 0, |
275 'protected' => 0, |
276 'delvotes' => 0, |
276 'delvotes' => 0, |
277 'delvote_ips' => '', |
277 'delvote_ips' => '', |
278 'wiki_mode' => 2, |
278 'wiki_mode' => 2, |
279 'page_format' => getConfig('default_page_format', 'wikitext') |
279 'page_format' => getConfig('default_page_format', 'wikitext') |
280 ); |
280 ); |
281 } |
281 } |
282 // Look for a namespace prefix in the urlname, and assign a different namespace, if necessary |
282 // Look for a namespace prefix in the urlname, and assign a different namespace, if necessary |
283 $k = array_keys($this->nslist); |
283 $k = array_keys($this->nslist); |
284 for($i=0;$i<sizeof($this->nslist);$i++) |
284 for($i=0;$i<sizeof($this->nslist);$i++) |
285 { |
285 { |
286 $ln = strlen($this->nslist[$k[$i]]); |
286 $ln = strlen($this->nslist[$k[$i]]); |
287 if( substr($this->page, 0, $ln) == $this->nslist[$k[$i]] ) |
287 if( substr($this->page, 0, $ln) == $this->nslist[$k[$i]] ) |
288 { |
288 { |
289 $this->cpage['namespace'] = $k[$i]; |
289 $this->cpage['namespace'] = $k[$i]; |
290 $this->cpage['urlname_nons'] = substr($this->page, strlen($this->nslist[$this->cpage['namespace']]), strlen($this->page)); |
290 $this->cpage['urlname_nons'] = substr($this->page, strlen($this->nslist[$this->cpage['namespace']]), strlen($this->page)); |
291 if(!isset($this->cpage['wiki_mode'])) |
291 if(!isset($this->cpage['wiki_mode'])) |
292 { |
292 { |
293 $this->cpage['wiki_mode'] = 2; |
293 $this->cpage['wiki_mode'] = 2; |
294 } |
294 } |
295 } |
295 } |
296 } |
296 } |
297 $this->namespace = $this->cpage['namespace']; |
297 $this->namespace = $this->cpage['namespace']; |
298 $this->page_id =& $this->cpage['urlname_nons']; |
298 $this->page_id =& $this->cpage['urlname_nons']; |
299 |
299 |
300 if($this->namespace=='System') |
300 if($this->namespace=='System') |
301 { |
301 { |
302 $this->cpage['protected'] = 1; |
302 $this->cpage['protected'] = 1; |
303 } |
303 } |
304 if($this->namespace == 'Special' && !$this->external_api_page) |
304 if($this->namespace == 'Special' && !$this->external_api_page) |
305 { |
305 { |
306 // Can't load nonexistent pages |
306 // Can't load nonexistent pages |
307 if( is_string(get_main_page()) ) |
307 if( is_string(get_main_page()) ) |
308 { |
308 { |
309 $main_page = makeUrl(get_main_page()); |
309 $main_page = makeUrl(get_main_page()); |
310 } |
310 } |
311 else |
311 else |
312 { |
312 { |
313 $main_page = makeUrl($this->pages[0]['urlname']); |
313 $main_page = makeUrl($this->pages[0]['urlname']); |
314 } |
314 } |
315 redirect($main_page, $lang->get('page_msg_special_404_title'), $lang->get('page_msg_special_404_body', array('sp_link' => makeUrlNS('Special', 'SpecialPages'))), 15); |
315 redirect($main_page, $lang->get('page_msg_special_404_title'), $lang->get('page_msg_special_404_body', array('sp_link' => makeUrlNS('Special', 'SpecialPages'))), 15); |
316 exit; |
316 exit; |
317 } |
317 } |
318 // Allow the user to create/modify his user page uncondtionally (admins can still protect the page) |
318 // Allow the user to create/modify his user page uncondtionally (admins can still protect the page) |
319 if($this->page == $this->nslist['User'].str_replace(' ', '_', $session->username)) |
319 if($this->page == $this->nslist['User'].str_replace(' ', '_', $session->username)) |
320 { |
320 { |
321 $this->wiki_mode = true; |
321 $this->wiki_mode = true; |
322 } |
322 } |
323 } |
323 } |
324 // This is used in the admin panel to keep track of form submission targets |
324 // This is used in the admin panel to keep track of form submission targets |
325 $this->cpage['module'] = $this->cpage['urlname']; |
325 $this->cpage['module'] = $this->cpage['urlname']; |
326 |
326 |
327 $this->cpage['require_admin'] = ( $this->cpage['namespace'] === 'Admin' ); |
327 $this->cpage['require_admin'] = ( $this->cpage['namespace'] === 'Admin' ); |
328 |
328 |
329 // Page is set up, call any hooks |
329 // Page is set up, call any hooks |
330 $code = $plugins->setHook('page_set'); |
330 $code = $plugins->setHook('page_set'); |
331 foreach ( $code as $cmd ) |
331 foreach ( $code as $cmd ) |
332 { |
332 { |
333 eval($cmd); |
333 eval($cmd); |
334 } |
334 } |
335 |
335 |
336 profiler_log('Paths and CMS core initted'); |
336 profiler_log('Paths and CMS core initted'); |
337 $session->init_permissions(); |
337 $session->init_permissions(); |
338 } |
338 } |
339 |
339 |
340 /** |
340 /** |
341 * Fetch cdata (metadata) for a page. |
341 * Fetch cdata (metadata) for a page. |
342 * @param string Page ID |
342 * @param string Page ID |
343 * @param string Namespace |
343 * @param string Namespace |
344 * @return array |
344 * @return array |
345 */ |
345 */ |
346 |
346 |
347 function get_cdata($page_id, $namespace) |
347 function get_cdata($page_id, $namespace) |
348 { |
348 { |
349 global $db, $session, $paths, $template, $plugins; // Common objects |
349 global $db, $session, $paths, $template, $plugins; // Common objects |
350 |
350 |
351 $pathskey = $this->get_pathskey($page_id, $namespace); |
351 $pathskey = $this->get_pathskey($page_id, $namespace); |
352 if ( isset($this->pages[$pathskey]) ) |
352 if ( isset($this->pages[$pathskey]) ) |
353 return $this->pages[$pathskey]; |
353 return $this->pages[$pathskey]; |
354 |
354 |
355 $page = namespace_factory($page_id, $namespace); |
355 $page = namespace_factory($page_id, $namespace); |
356 $cdata = $page->get_cdata(); |
356 $cdata = $page->get_cdata(); |
357 |
357 |
358 $this->pages[$pathskey] = $cdata; |
358 $this->pages[$pathskey] = $cdata; |
359 return $cdata; |
359 return $cdata; |
360 } |
360 } |
361 |
361 |
362 /** |
362 /** |
363 * For a given page ID and namespace, generate a flat string that can be used to access $paths->pages. |
363 * For a given page ID and namespace, generate a flat string that can be used to access $paths->pages. |
364 * @param string Page ID |
364 * @param string Page ID |
365 * @param string Namespace |
365 * @param string Namespace |
366 */ |
366 */ |
367 |
367 |
368 function get_pathskey($page_id, $namespace) |
368 function get_pathskey($page_id, $namespace) |
369 { |
369 { |
370 return ( isset($this->nslist[$namespace]) ) ? "{$this->nslist[$namespace]}{$page_id}" : "{$namespace}:{$page_id}"; |
370 return ( isset($this->nslist[$namespace]) ) ? "{$this->nslist[$namespace]}{$page_id}" : "{$namespace}:{$page_id}"; |
371 } |
371 } |
372 |
372 |
373 function add_page($flags) |
373 function add_page($flags) |
374 { |
374 { |
375 global $lang; |
375 global $lang; |
376 $flags['urlname_nons'] = $flags['urlname']; |
376 $flags['urlname_nons'] = $flags['urlname']; |
377 $flags['urlname'] = $this->nslist[$flags['namespace']] . $flags['urlname']; // Applies the User:/File:/etc prefixes to the URL names |
377 $flags['urlname'] = $this->nslist[$flags['namespace']] . $flags['urlname']; // Applies the User:/File:/etc prefixes to the URL names |
378 |
378 |
379 if ( is_object($lang) ) |
379 if ( is_object($lang) ) |
380 { |
380 { |
381 if ( preg_match('/^[a-z0-9]+_[a-z0-9_]+$/', $flags['name']) ) |
381 if ( preg_match('/^[a-z0-9]+_[a-z0-9_]+$/', $flags['name']) ) |
382 $flags['name'] = $lang->get($flags['name']); |
382 $flags['name'] = $lang->get($flags['name']); |
383 } |
383 } |
384 |
384 |
385 $flags['require_admin'] = ( $flags['namespace'] === 'Admin' ); |
385 $flags['require_admin'] = ( $flags['namespace'] === 'Admin' ); |
386 $flags['page_exists'] = true; |
386 $flags['page_exists'] = true; |
387 |
387 |
388 $this->pages[$flags['urlname']] = $flags; |
388 $this->pages[$flags['urlname']] = $flags; |
389 } |
389 } |
390 |
390 |
391 function main_page() |
391 function main_page() |
392 { |
392 { |
393 if( is_string(get_main_page()) ) |
393 if( is_string(get_main_page()) ) |
394 { |
394 { |
395 $main_page = makeUrl(get_main_page()); |
395 $main_page = makeUrl(get_main_page()); |
396 } |
396 } |
397 else |
397 else |
398 { |
398 { |
399 $main_page = makeUrl($this->pages[0]['urlname']); |
399 $main_page = makeUrl($this->pages[0]['urlname']); |
400 } |
400 } |
401 redirect($main_page, 'Redirecting...', 'Invalid request, redirecting to main page', 0); |
401 redirect($main_page, 'Redirecting...', 'Invalid request, redirecting to main page', 0); |
402 exit; |
402 exit; |
403 } |
403 } |
404 |
404 |
405 function sysmsg($n) |
405 function sysmsg($n) |
406 { |
406 { |
407 global $db, $session, $paths, $template, $plugins; // Common objects |
407 global $db, $session, $paths, $template, $plugins; // Common objects |
408 static $sm_cache = array(); |
408 static $sm_cache = array(); |
409 |
409 |
410 if ( isset($sm_cache[$n]) ) |
410 if ( isset($sm_cache[$n]) ) |
411 return $sm_cache[$n]; |
411 return $sm_cache[$n]; |
412 |
412 |
413 // sometimes this gets called during die_semicritical()... |
413 // sometimes this gets called during die_semicritical()... |
414 if ( !is_object($db) ) |
414 if ( !is_object($db) ) |
415 return false; |
415 return false; |
416 |
416 |
417 if ( !@$db->_conn ) |
417 if ( !@$db->_conn ) |
418 return false; |
418 return false; |
419 |
419 |
420 $q = $db->sql_query('SELECT page_text, char_tag FROM '.table_prefix.'page_text WHERE page_id=\''.$db->escape(sanitize_page_id($n)).'\' AND namespace=\'System\''); |
420 $q = $db->sql_query('SELECT page_text, char_tag FROM '.table_prefix.'page_text WHERE page_id=\''.$db->escape(sanitize_page_id($n)).'\' AND namespace=\'System\''); |
421 if( !$q ) |
421 if( !$q ) |
422 { |
422 { |
423 $db->_die('Error during generic selection of system page data.'); |
423 $db->_die('Error during generic selection of system page data.'); |
424 } |
424 } |
425 if($db->numrows() < 1) |
425 if($db->numrows() < 1) |
426 { |
426 { |
427 return false; |
427 return false; |
428 //$db->_die('Error during generic selection of system page data: there were no rows in the text table that matched the page text query.'); |
428 //$db->_die('Error during generic selection of system page data: there were no rows in the text table that matched the page text query.'); |
429 } |
429 } |
430 $r = $db->fetchrow(); |
430 $r = $db->fetchrow(); |
431 $db->free_result(); |
431 $db->free_result(); |
432 $message = $r['page_text']; |
432 $message = $r['page_text']; |
433 |
433 |
434 $message = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '', $message); |
434 $message = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '', $message); |
435 $message = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '\\1', $message); |
435 $message = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '\\1', $message); |
436 |
436 |
437 $sm_cache[$n] = $message; |
437 $sm_cache[$n] = $message; |
438 |
438 |
439 return $message; |
439 return $message; |
440 } |
440 } |
441 function get_pageid_from_url() |
441 function get_pageid_from_url() |
442 { |
442 { |
443 return get_title(true, true); |
443 return get_title(true, true); |
444 } |
444 } |
445 // Parses a (very carefully formed) array into Javascript code compatible with the Tigra Tree Menu used in the admin menu |
445 // Parses a (very carefully formed) array into Javascript code compatible with the Tigra Tree Menu used in the admin menu |
446 function parseAdminTree() |
446 function parseAdminTree() |
447 { |
447 { |
448 global $lang; |
448 global $lang; |
449 |
449 |
450 $k = array_keys($this->admin_tree); |
450 $k = array_keys($this->admin_tree); |
451 $i = 0; |
451 $i = 0; |
452 $ret = ''; |
452 $ret = ''; |
453 $icon = $this->make_sprite_icon(4, 2); |
453 $icon = $this->make_sprite_icon(4, 2); |
454 $ret .= "var TREE_ITEMS = "; |
454 $ret .= "var TREE_ITEMS = "; |
455 $tree = array( |
455 $tree = array( |
456 array($icon . $lang->get('adm_btn_home'), "javascript:ajaxPage('{$this->nslist['Admin']}Home');") |
456 array($icon . $lang->get('adm_btn_home'), "javascript:ajaxPage('{$this->nslist['Admin']}Home');") |
457 ); |
457 ); |
458 |
458 |
459 $root =& $tree[0]; |
459 $root =& $tree[0]; |
460 |
460 |
461 foreach($k as $key) |
461 foreach($k as $key) |
462 { |
462 { |
463 $i++; |
463 $i++; |
464 $name = $lang->get($key); |
464 $name = $lang->get($key); |
465 $group = array($name, "javascript:trees[0].toggle($i)"); |
465 $group = array($name, "javascript:trees[0].toggle($i)"); |
466 |
466 |
467 foreach($this->admin_tree[$key] as $nodeid => $c) |
467 foreach($this->admin_tree[$key] as $nodeid => $c) |
468 { |
468 { |
469 $i++; |
469 $i++; |
470 $name = $lang->get($c['name']); |
470 $name = $lang->get($c['name']); |
471 if ( $c['icon'] && $c['icon'] != cdnPath . '/images/spacer.gif' ) |
471 if ( $c['icon'] && $c['icon'] != cdnPath . '/images/spacer.gif' ) |
472 { |
472 { |
473 if ( is_array($c['icon']) ) |
473 if ( is_array($c['icon']) ) |
474 { |
474 { |
475 // this is a sprite reference |
475 // this is a sprite reference |
476 list($ix, $iy) = $c['icon']; |
476 list($ix, $iy) = $c['icon']; |
477 $icon = $this->make_sprite_icon($ix, $iy); |
477 $icon = $this->make_sprite_icon($ix, $iy); |
478 } |
478 } |
479 else |
479 else |
480 { |
480 { |
481 $icon = "<img alt=\"\" src=\"{$c['icon']}\" style=\"border-width: 0; margin-right: 3px;\" /> "; |
481 $icon = "<img alt=\"\" src=\"{$c['icon']}\" style=\"border-width: 0; margin-right: 3px;\" /> "; |
482 } |
482 } |
483 } |
483 } |
484 else |
484 else |
485 { |
485 { |
486 $icon = ''; |
486 $icon = ''; |
487 } |
487 } |
488 $group[] = array("$icon$name", "javascript:ajaxPage('{$this->nslist['Admin']}{$c['pageid']}');"); |
488 $group[] = array("$icon$name", "javascript:ajaxPage('{$this->nslist['Admin']}{$c['pageid']}');"); |
489 } |
489 } |
490 |
490 |
491 $root[] = $group; |
491 $root[] = $group; |
492 } |
492 } |
493 $icon = $this->make_sprite_icon(1, 1); |
493 $icon = $this->make_sprite_icon(1, 1); |
494 $root[] = array( |
494 $root[] = array( |
495 $icon . $lang->get('adm_btn_logout'), |
495 $icon . $lang->get('adm_btn_logout'), |
496 "javascript:ajaxPage('{$this->nslist['Admin']}AdminLogout');" |
496 "javascript:ajaxPage('{$this->nslist['Admin']}AdminLogout');" |
497 ); |
497 ); |
498 $root[] = array( |
498 $root[] = array( |
499 "<span id=\"keepalivestat\">" . $lang->get('adm_btn_keepalive_loading') . "</span>", |
499 "<span id=\"keepalivestat\">" . $lang->get('adm_btn_keepalive_loading') . "</span>", |
500 "javascript:ajaxToggleKeepalive();", |
500 "javascript:ajaxToggleKeepalive();", |
501 array( |
501 array( |
502 $lang->get('adm_btn_keepalive_about'), |
502 $lang->get('adm_btn_keepalive_about'), |
503 "javascript:aboutKeepAlive();" |
503 "javascript:aboutKeepAlive();" |
504 ) |
504 ) |
505 ); |
505 ); |
506 |
506 |
507 $ret .= enano_json_encode($tree) . ';'; |
507 $ret .= enano_json_encode($tree) . ';'; |
508 |
508 |
509 // 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* |
509 // 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* |
510 // $ret .= " ['(debug) Clear menu bitfield', 'javascript:createCookie(\\'admin_menu_state\\', \\'1\\', 365);'],\n"; |
510 // $ret .= " ['(debug) Clear menu bitfield', 'javascript:createCookie(\\'admin_menu_state\\', \\'1\\', 365);'],\n"; |
511 return $ret; |
511 return $ret; |
512 } |
512 } |
513 |
513 |
514 /** |
514 /** |
515 * Internal function to generate HTML code for an icon in the admin panel tree which is sprited. |
515 * Internal function to generate HTML code for an icon in the admin panel tree which is sprited. |
516 * @param int X index of icon |
516 * @param int X index of icon |
517 * @param int Y index of icon |
517 * @param int Y index of icon |
518 * @return string |
518 * @return string |
519 */ |
519 */ |
520 |
520 |
521 function make_sprite_icon($ix, $iy) |
521 function make_sprite_icon($ix, $iy) |
522 { |
522 { |
523 $xpos = 16 * ( $ix - 1 ); |
523 $xpos = 16 * ( $ix - 1 ); |
524 $ypos = 16 * ( $iy - 1 ); |
524 $ypos = 16 * ( $iy - 1 ); |
525 return "<img alt=\"\" src=\"" . cdnPath . "/images/spacer.gif\" class=\"adminiconsprite\" style=\"border-width: 0; margin-right: 3px; background-position: -{$xpos}px -{$ypos}px;\" /> "; |
525 return "<img alt=\"\" src=\"" . cdnPath . "/images/spacer.gif\" class=\"adminiconsprite\" style=\"border-width: 0; margin-right: 3px; background-position: -{$xpos}px -{$ypos}px;\" /> "; |
526 } |
526 } |
527 |
527 |
528 /** |
528 /** |
529 * Creates a new entry in the administration panel's navigation tree. |
529 * Creates a new entry in the administration panel's navigation tree. |
530 * @param string Section name - if this is a language string identifier, it will be sent through $lang->get() |
530 * @param string Section name - if this is a language string identifier, it will be sent through $lang->get() |
531 * @param string The title of the page, also may be a language string identifier |
531 * @param string The title of the page, also may be a language string identifier |
532 * @param string The page ID of the admin page, the namespace Admin is assumed |
532 * @param string The page ID of the admin page, the namespace Admin is assumed |
533 * @param string Optional. The path to a 16x16 image that will be displayed as the icon for this admin page |
533 * @param string Optional. The path to a 16x16 image that will be displayed as the icon for this admin page |
534 */ |
534 */ |
535 |
535 |
536 function addAdminNode($section, $page_title, $url, $icon = false) |
536 function addAdminNode($section, $page_title, $url, $icon = false) |
537 { |
537 { |
538 if ( !$icon ) |
538 if ( !$icon ) |
539 { |
539 { |
540 $icon = cdnPath . '/images/spacer.gif'; |
540 $icon = cdnPath . '/images/spacer.gif'; |
541 } |
541 } |
542 if(!isset($this->admin_tree[$section])) |
542 if(!isset($this->admin_tree[$section])) |
543 { |
543 { |
544 $this->admin_tree[$section] = Array(); |
544 $this->admin_tree[$section] = Array(); |
545 } |
545 } |
546 $this->admin_tree[$section][] = Array( |
546 $this->admin_tree[$section][] = Array( |
547 'name' => $page_title, |
547 'name' => $page_title, |
548 'pageid' => $url, |
548 'pageid' => $url, |
549 'icon' => $icon |
549 'icon' => $icon |
550 ); |
550 ); |
551 } |
551 } |
552 function getParam($id = 0) |
552 function getParam($id = 0) |
553 { |
553 { |
554 $title = $this->fullpage; |
554 $title = $this->fullpage; |
555 list(, $ns) = RenderMan::strToPageID($title); |
555 list(, $ns) = RenderMan::strToPageID($title); |
556 $title = substr($title, strlen($this->nslist[$ns])); |
556 $title = substr($title, strlen($this->nslist[$ns])); |
557 $regex = '/^' . str_replace('/', '\\/', preg_quote($this->nslist[$ns])) . '\\/?/'; |
557 $regex = '/^' . str_replace('/', '\\/', preg_quote($this->nslist[$ns])) . '\\/?/'; |
558 $title = preg_replace($regex, '', $title); |
558 $title = preg_replace($regex, '', $title); |
559 $title = explode('/', $title); |
559 $title = explode('/', $title); |
560 $id = $id + 1; |
560 $id = $id + 1; |
561 return ( isset($title[$id]) ) ? $title[$id] : false; |
561 return ( isset($title[$id]) ) ? $title[$id] : false; |
562 } |
562 } |
563 |
563 |
564 function getAllParams() |
564 function getAllParams() |
565 { |
565 { |
566 $title = $this->fullpage; |
566 $title = $this->fullpage; |
567 $regex = '/^' . str_replace('/', '\\/', preg_quote($this->nslist[$this->namespace])) . '\\/?/'; |
567 $regex = '/^' . str_replace('/', '\\/', preg_quote($this->nslist[$this->namespace])) . '\\/?/'; |
568 $title = preg_replace($regex, '', $title); |
568 $title = preg_replace($regex, '', $title); |
569 $title = explode('/', $title); |
569 $title = explode('/', $title); |
570 unset($title[0]); |
570 unset($title[0]); |
571 return implode('/', $title); |
571 return implode('/', $title); |
572 } |
572 } |
573 |
573 |
574 /** |
574 /** |
575 * Creates a new namespace in memory |
575 * Creates a new namespace in memory |
576 * @param string $id the namespace ID |
576 * @param string $id the namespace ID |
577 * @param string $prefix the URL prefix, must not be blank or already used |
577 * @param string $prefix the URL prefix, must not be blank or already used |
578 * @return bool true on success false on failure |
578 * @return bool true on success false on failure |
579 */ |
579 */ |
580 |
580 |
581 function create_namespace($id, $prefix) |
581 function create_namespace($id, $prefix) |
582 { |
582 { |
583 if(in_array($prefix, $this->nslist)) |
583 if(in_array($prefix, $this->nslist)) |
584 { |
584 { |
585 // echo '<b>Warning:</b> pathManager::create_namespace: Prefix "'.$prefix.'" is already taken<br />'; |
585 // echo '<b>Warning:</b> pathManager::create_namespace: Prefix "'.$prefix.'" is already taken<br />'; |
586 return false; |
586 return false; |
587 } |
587 } |
588 if( isset($this->nslist[$id]) ) |
588 if( isset($this->nslist[$id]) ) |
589 { |
589 { |
590 // echo '<b>Warning:</b> pathManager::create_namespace: Namespace ID "'.$prefix.'" is already taken<br />'; |
590 // echo '<b>Warning:</b> pathManager::create_namespace: Namespace ID "'.$prefix.'" is already taken<br />'; |
591 return false; |
591 return false; |
592 } |
592 } |
593 $this->nslist[$id] = $prefix; |
593 $this->nslist[$id] = $prefix; |
594 } |
594 } |
595 |
595 |
596 /** |
596 /** |
597 * Deprecated. |
597 * Deprecated. |
598 */ |
598 */ |
599 |
599 |
600 function update_metadata_cache() |
600 function update_metadata_cache() |
601 { |
601 { |
602 global $db, $session, $paths, $template, $plugins; // Common objects |
602 global $db, $session, $paths, $template, $plugins; // Common objects |
603 |
603 |
604 return false; |
604 return false; |
605 } |
605 } |
606 |
606 |
607 /** |
607 /** |
608 * Takes a result row from the pages table and calculates correct values for it. |
608 * Takes a result row from the pages table and calculates correct values for it. |
609 * @param array |
609 * @param array |
610 * @return array |
610 * @return array |
611 */ |
611 */ |
612 |
612 |
613 function calculate_metadata_from_row($r) |
613 function calculate_metadata_from_row($r) |
614 { |
614 { |
615 return Namespace_Default::bake_cdata($r); |
615 return Namespace_Default::bake_cdata($r); |
616 } |
616 } |
617 |
617 |
618 /** |
618 /** |
619 * Registers a handler to manually process a namespace instead of the default PageProcessor behavior. |
619 * Registers a handler to manually process a namespace instead of the default PageProcessor behavior. |
620 * The first and only parameter passed to the processing function will be the PageProcessor instance. |
620 * The first and only parameter passed to the processing function will be the PageProcessor instance. |
621 * @param string Namespace to process |
621 * @param string Namespace to process |
622 * @param mixed Function address. Either a function name or an array of the form array(0 => mixed (string:class name or object), 1 => string:method) |
622 * @param mixed Function address. Either a function name or an array of the form array(0 => mixed (string:class name or object), 1 => string:method) |
623 */ |
623 */ |
624 |
624 |
625 function register_namespace_processor($namespace, $function) |
625 function register_namespace_processor($namespace, $function) |
626 { |
626 { |
627 if ( isset($this->namespace_processors[$namespace]) ) |
627 if ( isset($this->namespace_processors[$namespace]) ) |
628 { |
628 { |
629 $processorname = ( is_string($this->namespace_processors[$namespace]) ) ? |
629 $processorname = ( is_string($this->namespace_processors[$namespace]) ) ? |
630 $this->namespace_processors[$namespace] : |
630 $this->namespace_processors[$namespace] : |
631 ( is_object($this->namespace_processors[$namespace][0]) ? get_class($this->namespace_processors[$namespace][0]) : $this->namespace_processors[$namespace][0] ) . '::' . |
631 ( is_object($this->namespace_processors[$namespace][0]) ? get_class($this->namespace_processors[$namespace][0]) : $this->namespace_processors[$namespace][0] ) . '::' . |
632 $this->namespace_processors[$namespace][1]; |
632 $this->namespace_processors[$namespace][1]; |
633 |
633 |
634 trigger_error("Namespace \"$namespace\" is already being processed by $processorname - replacing caller", E_USER_WARNING); |
634 trigger_error("Namespace \"$namespace\" is already being processed by $processorname - replacing caller", E_USER_WARNING); |
635 } |
635 } |
636 if ( !is_string($function) ) |
636 if ( !is_string($function) ) |
637 { |
637 { |
638 if ( !is_array($function) ) |
638 if ( !is_array($function) ) |
639 return false; |
639 return false; |
640 if ( count($function) != 2 ) |
640 if ( count($function) != 2 ) |
641 return false; |
641 return false; |
642 if ( !is_string($function[0]) && !is_object($function[0]) ) |
642 if ( !is_string($function[0]) && !is_object($function[0]) ) |
643 return false; |
643 return false; |
644 if ( !is_string($function[1]) ) |
644 if ( !is_string($function[1]) ) |
645 return false; |
645 return false; |
646 } |
646 } |
647 |
647 |
648 // security: don't allow Special or Admin namespaces to be overridden |
648 // security: don't allow Special or Admin namespaces to be overridden |
649 if ( $namespace == 'Special' || $namespace == 'Admin' ) |
649 if ( $namespace == 'Special' || $namespace == 'Admin' ) |
650 { |
650 { |
651 trigger_error("Security manager denied attempt to override processor for $namespace", E_USER_ERROR); |
651 trigger_error("Security manager denied attempt to override processor for $namespace", E_USER_ERROR); |
652 } |
652 } |
653 |
653 |
654 $this->namespace_processors[$namespace] = $function; |
654 $this->namespace_processors[$namespace] = $function; |
655 } |
655 } |
656 |
656 |
657 /** |
657 /** |
658 * Returns a namespace processor if one exists, otherwise returns false. |
658 * Returns a namespace processor if one exists, otherwise returns false. |
659 * @param string Namespace |
659 * @param string Namespace |
660 * @return mixed |
660 * @return mixed |
661 */ |
661 */ |
662 |
662 |
663 function get_namespace_processor($namespace) |
663 function get_namespace_processor($namespace) |
664 { |
664 { |
665 return ( isset($this->namespace_processors[$namespace]) ) ? $this->namespace_processors[$namespace] : false; |
665 return ( isset($this->namespace_processors[$namespace]) ) ? $this->namespace_processors[$namespace] : false; |
666 } |
666 } |
667 |
667 |
668 /** |
668 /** |
669 * Fetches the page texts for searching |
669 * Fetches the page texts for searching |
670 */ |
670 */ |
671 |
671 |
672 function fetch_page_search_texts() |
672 function fetch_page_search_texts() |
673 { |
673 { |
674 global $db, $session, $paths, $template, $plugins; // Common objects |
674 global $db, $session, $paths, $template, $plugins; // Common objects |
675 $texts = Array(); |
675 $texts = Array(); |
676 $q = $db->sql_query('SELECT t.page_id,t.namespace,t.page_text,t.char_tag FROM '.table_prefix.'page_text AS t |
676 $q = $db->sql_query('SELECT t.page_id,t.namespace,t.page_text,t.char_tag FROM '.table_prefix.'page_text AS t |
677 LEFT JOIN '.table_prefix.'pages AS p |
677 LEFT JOIN '.table_prefix.'pages AS p |
678 ON t.page_id=p.urlname |
678 ON t.page_id=p.urlname |
679 WHERE p.namespace=t.namespace |
679 WHERE p.namespace=t.namespace |
680 AND ( p.password=\'\' OR p.password=\'da39a3ee5e6b4b0d3255bfef95601890afd80709\' ) |
680 AND ( p.password=\'\' OR p.password=\'da39a3ee5e6b4b0d3255bfef95601890afd80709\' ) |
681 AND p.visible=1;'); // Only indexes "visible" pages |
681 AND p.visible=1;'); // Only indexes "visible" pages |
682 |
682 |
683 if( !$q ) |
683 if( !$q ) |
684 { |
684 { |
685 return false; |
685 return false; |
686 } |
686 } |
687 while($row = $db->fetchrow()) |
687 while($row = $db->fetchrow()) |
688 { |
688 { |
689 $pid = $this->nslist[$row['namespace']] . $row['page_id']; |
689 $pid = $this->nslist[$row['namespace']] . $row['page_id']; |
690 $texts[$pid] = $row['page_text']; |
690 $texts[$pid] = $row['page_text']; |
691 } |
691 } |
692 $db->free_result(); |
692 $db->free_result(); |
693 |
693 |
694 return $texts; |
694 return $texts; |
695 } |
695 } |
696 |
696 |
697 /** |
697 /** |
698 * Generates an SQL query to grab all of the text |
698 * Generates an SQL query to grab all of the text |
699 */ |
699 */ |
700 |
700 |
701 function fetch_page_search_resource() |
701 function fetch_page_search_resource() |
702 { |
702 { |
703 global $db, $session, $paths, $template, $plugins; // Common objects |
703 global $db, $session, $paths, $template, $plugins; // Common objects |
704 // sha1('') returns "da39a3ee5e6b4b0d3255bfef95601890afd80709" |
704 // sha1('') returns "da39a3ee5e6b4b0d3255bfef95601890afd80709" |
705 |
705 |
706 $concat_column = ( ENANO_DBLAYER == 'MYSQL' ) ? |
706 $concat_column = ( ENANO_DBLAYER == 'MYSQL' ) ? |
707 'CONCAT(\'ns=\',t.namespace,\';pid=\',t.page_id)' : |
707 'CONCAT(\'ns=\',t.namespace,\';pid=\',t.page_id)' : |
708 "'ns=' || t.namespace || ';pid=' || t.page_id"; |
708 "'ns=' || t.namespace || ';pid=' || t.page_id"; |
709 |
709 |
710 $texts = 'SELECT t.page_text, ' . $concat_column . ' AS page_idstring, t.page_id, t.namespace FROM '.table_prefix.'page_text AS t |
710 $texts = 'SELECT t.page_text, ' . $concat_column . ' AS page_idstring, t.page_id, t.namespace FROM '.table_prefix.'page_text AS t |
711 LEFT JOIN '.table_prefix.'pages AS p |
711 LEFT JOIN '.table_prefix.'pages AS p |
712 ON ( t.page_id=p.urlname AND t.namespace=p.namespace ) |
712 ON ( t.page_id=p.urlname AND t.namespace=p.namespace ) |
713 WHERE p.namespace=t.namespace |
713 WHERE p.namespace=t.namespace |
714 AND ( p.password=\'\' OR p.password=\'da39a3ee5e6b4b0d3255bfef95601890afd80709\' ) |
714 AND ( p.password=\'\' OR p.password=\'da39a3ee5e6b4b0d3255bfef95601890afd80709\' ) |
715 AND p.visible=1;'; // Only indexes "visible" pages |
715 AND p.visible=1;'; // Only indexes "visible" pages |
716 return $texts; |
716 return $texts; |
717 } |
717 } |
718 |
718 |
719 /** |
719 /** |
720 * Builds a word list for search indexing. |
720 * Builds a word list for search indexing. |
721 * @param string Text to index |
721 * @param string Text to index |
722 * @param string Page ID of the page being indexed |
722 * @param string Page ID of the page being indexed |
723 * @param string Title of the page being indexed |
723 * @param string Title of the page being indexed |
724 * @return array List of words |
724 * @return array List of words |
725 */ |
725 */ |
726 |
726 |
727 function calculate_word_list($text, $page_id, $page_name) |
727 function calculate_word_list($text, $page_id, $page_name) |
728 { |
728 { |
729 $page_id = dirtify_page_id($page_id); |
729 $page_id = dirtify_page_id($page_id); |
730 $text = preg_replace('/[^a-z0-9\']/i', ' ', $text); |
730 $text = preg_replace('/[^a-z0-9\']/i', ' ', $text); |
731 $page_id = preg_replace('/[^a-z0-9\']/i', ' ', $page_id); |
731 $page_id = preg_replace('/[^a-z0-9\']/i', ' ', $page_id); |
732 $page_name = preg_replace('/[^a-z0-9\']/i', ' ', $page_name); |
732 $page_name = preg_replace('/[^a-z0-9\']/i', ' ', $page_name); |
733 $text .= " $page_id $page_name"; |
733 $text .= " $page_id $page_name"; |
734 $text = explode(' ', $text); |
734 $text = explode(' ', $text); |
735 foreach ( $text as $i => &$word ) |
735 foreach ( $text as $i => &$word ) |
736 { |
736 { |
737 if ( strstr($word, "''") ) |
737 if ( strstr($word, "''") ) |
738 $word = preg_replace("/[']{2,}/", '', $word); |
738 $word = preg_replace("/[']{2,}/", '', $word); |
739 if ( strlen($word) < 2 ) |
739 if ( strlen($word) < 2 ) |
740 unset($text[$i]); |
740 unset($text[$i]); |
741 } |
741 } |
742 $text = array_unique(array_values($text)); |
742 $text = array_unique(array_values($text)); |
743 // for debugging purposes (usually XSS safe because of character stripping) |
743 // for debugging purposes (usually XSS safe because of character stripping) |
744 // echo ' ' . implode(' ', $text) . '<br />'; |
744 // echo ' ' . implode(' ', $text) . '<br />'; |
745 return $text; |
745 return $text; |
746 } |
746 } |
747 |
747 |
748 /** |
748 /** |
749 * Rebuilds the site's entire search index. Considerably more exciting if run from the command line. |
749 * Rebuilds the site's entire search index. Considerably more exciting if run from the command line. |
750 * @param bool If true, verbose output. |
750 * @param bool If true, verbose output. |
751 * @param bool If true, verbose + debugging output. |
751 * @param bool If true, verbose + debugging output. |
752 */ |
752 */ |
753 |
753 |
754 function rebuild_search_index($verbose = false, $debug = false) |
754 function rebuild_search_index($verbose = false, $debug = false) |
755 { |
755 { |
756 global $db, $session, $paths, $template, $plugins; // Common objects |
756 global $db, $session, $paths, $template, $plugins; // Common objects |
757 require_once(ENANO_ROOT . '/includes/search.php'); |
757 require_once(ENANO_ROOT . '/includes/search.php'); |
758 |
758 |
759 $progress = false; |
759 $progress = false; |
760 if ( class_exists('ProgressBar') ) |
760 if ( class_exists('ProgressBar') ) |
761 { |
761 { |
762 // CLI only. |
762 // CLI only. |
763 $progress = new ProgressBar('Rebuilding search index: [', ']', 'Initializing...', 'green', 'blue', 'white', 'yellow'); |
763 $progress = new ProgressBar('Rebuilding search index: [', ']', 'Initializing...', 'green', 'blue', 'white', 'yellow'); |
764 $verbose = false; |
764 $verbose = false; |
765 $debug = false; |
765 $debug = false; |
766 $progress->start(); |
766 $progress->start(); |
767 } |
767 } |
768 |
768 |
769 @set_time_limit(0); |
769 @set_time_limit(0); |
770 |
770 |
771 $q = $db->sql_query('DELETE FROM ' . table_prefix . 'search_index;'); |
771 $q = $db->sql_query('DELETE FROM ' . table_prefix . 'search_index;'); |
772 if ( !$q ) |
772 if ( !$q ) |
773 $db->_die(); |
773 $db->_die(); |
774 |
774 |
775 $sha1_blank = sha1(''); |
775 $sha1_blank = sha1(''); |
776 |
776 |
777 // |
777 // |
778 // Index $pages_in_batch pages at a time |
778 // Index $pages_in_batch pages at a time |
779 // |
779 // |
780 $pages_in_batch = 15; |
780 $pages_in_batch = 15; |
781 |
781 |
782 // First find out how many pages there are |
782 // First find out how many pages there are |
783 $q = $db->sql_query('SELECT COUNT(p.urlname) AS num_pages FROM ' . table_prefix . "page_text AS t\n" |
783 $q = $db->sql_query('SELECT COUNT(p.urlname) AS num_pages FROM ' . table_prefix . "page_text AS t\n" |
784 . " LEFT JOIN " . table_prefix . "pages AS p\n" |
784 . " LEFT JOIN " . table_prefix . "pages AS p\n" |
785 . " ON ( p.urlname = t.page_id AND p.namespace = t.namespace )\n" |
785 . " ON ( p.urlname = t.page_id AND p.namespace = t.namespace )\n" |
786 . " WHERE ( p.password = '' OR p.password = '$sha1_blank' )\n" |
786 . " WHERE ( p.password = '' OR p.password = '$sha1_blank' )\n" |
787 . " AND ( p.visible = 1 );"); |
787 . " AND ( p.visible = 1 );"); |
788 if ( !$q ) |
788 if ( !$q ) |
789 $db->_die(); |
789 $db->_die(); |
790 |
790 |
791 list($num_pages) = $db->fetchrow_num(); |
791 list($num_pages) = $db->fetchrow_num(); |
792 $num_pages = intval($num_pages); |
792 $num_pages = intval($num_pages); |
793 $loops = ceil($num_pages / $pages_in_batch); |
793 $loops = ceil($num_pages / $pages_in_batch); |
794 $master_word_list = array(); |
794 $master_word_list = array(); |
795 $stopwords = get_stopwords(); |
795 $stopwords = get_stopwords(); |
796 |
796 |
797 for ( $j = 0; $j < $loops; ) |
797 for ( $j = 0; $j < $loops; ) |
798 { |
798 { |
799 $offset = $j * $pages_in_batch; |
799 $offset = $j * $pages_in_batch; |
800 |
800 |
801 $j++; |
801 $j++; |
802 |
802 |
803 if ( $verbose && $debug ) |
803 if ( $verbose && $debug ) |
804 { |
804 { |
805 echo "Running indexing round $j of $loops (offset $offset)\n" . ( isset($_SERVER['REQUEST_URI']) ? '<br />' : '' ); |
805 echo "Running indexing round $j of $loops (offset $offset)\n" . ( isset($_SERVER['REQUEST_URI']) ? '<br />' : '' ); |
806 } |
806 } |
807 |
807 |
808 // this is friendly to both MySQL and PostgreSQL. |
808 // this is friendly to both MySQL and PostgreSQL. |
809 $texts = $db->sql_query('SELECT p.name, p.visible, t.page_id, t.namespace, t.page_text FROM ' . table_prefix . "page_text AS t\n" |
809 $texts = $db->sql_query('SELECT p.name, p.visible, t.page_id, t.namespace, t.page_text FROM ' . table_prefix . "page_text AS t\n" |
810 . " LEFT JOIN " . table_prefix . "pages AS p\n" |
810 . " LEFT JOIN " . table_prefix . "pages AS p\n" |
811 . " ON ( p.urlname = t.page_id AND p.namespace = t.namespace )\n" |
811 . " ON ( p.urlname = t.page_id AND p.namespace = t.namespace )\n" |
812 . " WHERE ( p.password = '' OR p.password = '$sha1_blank' )\n" |
812 . " WHERE ( p.password = '' OR p.password = '$sha1_blank' )\n" |
813 . " AND ( p.visible = 1 )\n" |
813 . " AND ( p.visible = 1 )\n" |
814 . " LIMIT $pages_in_batch OFFSET $offset;", false); |
814 . " LIMIT $pages_in_batch OFFSET $offset;", false); |
815 if ( !$texts ) |
815 if ( !$texts ) |
816 $db->_die(); |
816 $db->_die(); |
817 |
817 |
818 $k = $offset; |
818 $k = $offset; |
819 |
819 |
820 if ( $row = $db->fetchrow($texts) ) |
820 if ( $row = $db->fetchrow($texts) ) |
821 { |
821 { |
822 do |
822 do |
823 { |
823 { |
824 $k++; |
824 $k++; |
825 if ( $verbose ) |
825 if ( $verbose ) |
826 { |
826 { |
827 $mu = memory_get_usage(); |
827 $mu = memory_get_usage(); |
828 echo " Indexing page $k of $num_pages: {$row['namespace']}:{$row['page_id']}"; |
828 echo " Indexing page $k of $num_pages: {$row['namespace']}:{$row['page_id']}"; |
829 if ( $debug ) |
829 if ( $debug ) |
830 echo ", mem = $mu..."; |
830 echo ", mem = $mu..."; |
831 flush(); |
831 flush(); |
832 } |
832 } |
833 else if ( is_object($progress) ) |
833 else if ( is_object($progress) ) |
834 { |
834 { |
835 $progress->update_text_quiet("$k/$num_pages {$row['namespace']}:{$row['page_id']}"); |
835 $progress->update_text_quiet("$k/$num_pages {$row['namespace']}:{$row['page_id']}"); |
836 $progress->set($k, $num_pages); |
836 $progress->set($k, $num_pages); |
837 } |
837 } |
838 |
838 |
839 // skip this page if it's not supposed to be indexed |
839 // skip this page if it's not supposed to be indexed |
840 if ( $row['visible'] == 0 ) |
840 if ( $row['visible'] == 0 ) |
841 { |
841 { |
842 if ( $verbose ) |
842 if ( $verbose ) |
843 { |
843 { |
844 echo "skipped"; |
844 echo "skipped"; |
845 if ( isset($_SERVER['REQUEST_URI']) ) |
845 if ( isset($_SERVER['REQUEST_URI']) ) |
846 echo '<br />'; |
846 echo '<br />'; |
847 echo "\n"; |
847 echo "\n"; |
848 } |
848 } |
849 continue; |
849 continue; |
850 } |
850 } |
851 |
851 |
852 // Indexing identifier for the page in the DB |
852 // Indexing identifier for the page in the DB |
853 $page_uniqid = "ns={$row['namespace']};pid=" . sanitize_page_id($row['page_id']); |
853 $page_uniqid = "ns={$row['namespace']};pid=" . sanitize_page_id($row['page_id']); |
854 $page_uniqid = $db->escape($page_uniqid); |
854 $page_uniqid = $db->escape($page_uniqid); |
855 |
855 |
856 // List of words on the page |
856 // List of words on the page |
857 $wordlist = $this->calculate_word_list($row['page_text'], $row['page_id'], $row['name']); |
857 $wordlist = $this->calculate_word_list($row['page_text'], $row['page_id'], $row['name']); |
858 |
858 |
859 // Index calculation complete -- run inserts |
859 // Index calculation complete -- run inserts |
860 $inserts = array(); |
860 $inserts = array(); |
861 foreach ( $wordlist as $word ) |
861 foreach ( $wordlist as $word ) |
862 { |
862 { |
863 if ( in_array($word, $stopwords) || strval(intval($word)) === $word || strlen($word) < 3 ) |
863 if ( in_array($word, $stopwords) || strval(intval($word)) === $word || strlen($word) < 3 ) |
864 continue; |
864 continue; |
865 $word_db = $db->escape($word); |
865 $word_db = $db->escape($word); |
866 $word_db_lc = $db->escape(strtolower($word)); |
866 $word_db_lc = $db->escape(strtolower($word)); |
867 if ( !in_array($word, $master_word_list) ) |
867 if ( !in_array($word, $master_word_list) ) |
868 { |
868 { |
869 $inserts[] = "( '$word_db', '$word_db_lc', '$page_uniqid' )"; |
869 $inserts[] = "( '$word_db', '$word_db_lc', '$page_uniqid' )"; |
870 } |
870 } |
871 else |
871 else |
872 { |
872 { |
873 if ( $verbose && $debug ) |
873 if ( $verbose && $debug ) |
874 echo '.'; |
874 echo '.'; |
875 $pid_col = ( ENANO_DBLAYER == 'MYSQL' ) ? |
875 $pid_col = ( ENANO_DBLAYER == 'MYSQL' ) ? |
876 "CONCAT( page_names, ',$page_uniqid' )": |
876 "CONCAT( page_names, ',$page_uniqid' )": |
877 "page_names || ',$page_uniqid'"; |
877 "page_names || ',$page_uniqid'"; |
878 $q = $db->sql_query('UPDATE ' . table_prefix . "search_index SET page_names = $pid_col WHERE word = '$word_db';", false); |
878 $q = $db->sql_query('UPDATE ' . table_prefix . "search_index SET page_names = $pid_col WHERE word = '$word_db';", false); |
879 if ( !$q ) |
879 if ( !$q ) |
880 $db->_die(); |
880 $db->_die(); |
881 } |
881 } |
882 } |
882 } |
883 if ( count($inserts) > 0 ) |
883 if ( count($inserts) > 0 ) |
884 { |
884 { |
885 if ( $verbose && $debug ) |
885 if ( $verbose && $debug ) |
886 echo 'i'; |
886 echo 'i'; |
887 $inserts = implode(",\n ", $inserts); |
887 $inserts = implode(",\n ", $inserts); |
888 $q = $db->sql_query('INSERT INTO ' . table_prefix . "search_index(word, word_lcase, page_names) VALUES\n $inserts;", false); |
888 $q = $db->sql_query('INSERT INTO ' . table_prefix . "search_index(word, word_lcase, page_names) VALUES\n $inserts;", false); |
889 if ( !$q ) |
889 if ( !$q ) |
890 $db->_die(); |
890 $db->_die(); |
891 } |
891 } |
892 |
892 |
893 $master_word_list = array_unique(array_merge($master_word_list, $wordlist)); |
893 $master_word_list = array_unique(array_merge($master_word_list, $wordlist)); |
894 if ( $verbose ) |
894 if ( $verbose ) |
895 { |
895 { |
896 if ( isset($_SERVER['REQUEST_URI']) ) |
896 if ( isset($_SERVER['REQUEST_URI']) ) |
897 echo '<br />'; |
897 echo '<br />'; |
898 echo "\n"; |
898 echo "\n"; |
899 } |
899 } |
900 unset($inserts, $wordlist, $page_uniqid, $word_db, $q, $word, $row); |
900 unset($inserts, $wordlist, $page_uniqid, $word_db, $q, $word, $row); |
901 } |
901 } |
902 while ( $row = $db->fetchrow($texts) ); |
902 while ( $row = $db->fetchrow($texts) ); |
903 } |
903 } |
904 $db->free_result($texts); |
904 $db->free_result($texts); |
905 } |
905 } |
906 if ( $verbose ) |
906 if ( $verbose ) |
907 { |
907 { |
908 echo "Indexing complete."; |
908 echo "Indexing complete."; |
909 if ( isset($_SERVER['REQUEST_URI']) ) |
909 if ( isset($_SERVER['REQUEST_URI']) ) |
910 echo '<br />'; |
910 echo '<br />'; |
911 echo "\n"; |
911 echo "\n"; |
912 } |
912 } |
913 else if ( is_object($progress) ) |
913 else if ( is_object($progress) ) |
914 { |
914 { |
915 $progress->update_text('Complete.'); |
915 $progress->update_text('Complete.'); |
916 $progress->end(); |
916 $progress->end(); |
917 } |
917 } |
918 return true; |
918 return true; |
919 } |
919 } |
920 |
920 |
921 /** |
921 /** |
922 * Partially rebuilds the search index, removing/inserting entries only for the current page |
922 * Partially rebuilds the search index, removing/inserting entries only for the current page |
923 * @param string $page_id |
923 * @param string $page_id |
924 * @param string $namespace |
924 * @param string $namespace |
925 */ |
925 */ |
926 |
926 |
927 function rebuild_page_index($page_id, $namespace) |
927 function rebuild_page_index($page_id, $namespace) |
928 { |
928 { |
929 global $db, $session, $paths, $template, $plugins; // Common objects |
929 global $db, $session, $paths, $template, $plugins; // Common objects |
930 require_once(ENANO_ROOT . '/includes/search.php'); |
930 require_once(ENANO_ROOT . '/includes/search.php'); |
931 |
931 |
932 if(!$db->sql_query('SELECT page_text FROM '.table_prefix.'page_text |
932 if(!$db->sql_query('SELECT page_text FROM '.table_prefix.'page_text |
933 WHERE page_id=\''.$db->escape($page_id).'\' AND namespace=\''.$db->escape($namespace).'\';')) |
933 WHERE page_id=\''.$db->escape($page_id).'\' AND namespace=\''.$db->escape($namespace).'\';')) |
934 { |
934 { |
935 return $db->get_error(); |
935 return $db->get_error(); |
936 } |
936 } |
937 if ( $db->numrows() < 1 ) |
937 if ( $db->numrows() < 1 ) |
938 return 'E: No rows'; |
938 return 'E: No rows'; |
939 $idstring = $this->nslist[$namespace] . sanitize_page_id($page_id); |
939 $idstring = $this->nslist[$namespace] . sanitize_page_id($page_id); |
940 if ( !isset($this->pages[$idstring]) ) |
940 if ( !isset($this->pages[$idstring]) ) |
941 { |
941 { |
942 return 'E: Can\'t find page metadata'; |
942 return 'E: Can\'t find page metadata'; |
943 } |
943 } |
944 $row = $db->fetchrow(); |
944 $row = $db->fetchrow(); |
945 $db->free_result(); |
945 $db->free_result(); |
946 $search = new Searcher(); |
946 $search = new Searcher(); |
947 |
947 |
948 // if the page shouldn't be indexed, send a blank set of strings to the indexing engine |
948 // if the page shouldn't be indexed, send a blank set of strings to the indexing engine |
949 if ( $this->pages[$idstring]['visible'] == 0 ) |
949 if ( $this->pages[$idstring]['visible'] == 0 ) |
950 { |
950 { |
951 $search->buildIndex(Array("ns={$namespace};pid={$page_id}"=>'')); |
951 $search->buildIndex(Array("ns={$namespace};pid={$page_id}"=>'')); |
952 } |
952 } |
953 else |
953 else |
954 { |
954 { |
955 $search->buildIndex(Array("ns={$namespace};pid={$page_id}"=>$row['page_text'] . ' ' . $this->pages[$idstring]['name'])); |
955 $search->buildIndex(Array("ns={$namespace};pid={$page_id}"=>$row['page_text'] . ' ' . $this->pages[$idstring]['name'])); |
956 } |
956 } |
957 |
957 |
958 $new_index = $search->index; |
958 $new_index = $search->index; |
959 |
959 |
960 if ( count($search->index) == 0 ) |
960 if ( count($search->index) == 0 ) |
961 // o_O |
961 // o_O |
962 // nothing indexed. |
962 // nothing indexed. |
963 return true; |
963 return true; |
964 |
964 |
965 if ( ENANO_DBLAYER == 'MYSQL' ) |
965 if ( ENANO_DBLAYER == 'MYSQL' ) |
966 { |
966 { |
967 $keys = array_keys($search->index); |
967 $keys = array_keys($search->index); |
968 foreach($keys as $i => $k) |
968 foreach($keys as $i => $k) |
969 { |
969 { |
970 $c =& $keys[$i]; |
970 $c =& $keys[$i]; |
971 $c = hexencode($c, '', ''); |
971 $c = hexencode($c, '', ''); |
972 } |
972 } |
973 $keys = "word=0x" . implode ( " OR word=0x", $keys ) . ""; |
973 $keys = "word=0x" . implode ( " OR word=0x", $keys ) . ""; |
974 } |
974 } |
975 else |
975 else |
976 { |
976 { |
977 $keys = array_keys($search->index); |
977 $keys = array_keys($search->index); |
978 foreach($keys as $i => $k) |
978 foreach($keys as $i => $k) |
979 { |
979 { |
980 $c =& $keys[$i]; |
980 $c =& $keys[$i]; |
981 $c = $db->escape($c); |
981 $c = $db->escape($c); |
982 } |
982 } |
983 $keys = "word='" . implode ( "' OR word='", $keys ) . "'"; |
983 $keys = "word='" . implode ( "' OR word='", $keys ) . "'"; |
984 } |
984 } |
985 |
985 |
986 $query = $db->sql_query('SELECT word,page_names FROM '.table_prefix.'search_index WHERE '.$keys.';'); |
986 $query = $db->sql_query('SELECT word,page_names FROM '.table_prefix.'search_index WHERE '.$keys.';'); |
987 |
987 |
988 while($row = $db->fetchrow()) |
988 while($row = $db->fetchrow()) |
989 { |
989 { |
990 $row['word'] = rtrim($row['word'], "\0"); |
990 $row['word'] = rtrim($row['word'], "\0"); |
991 $new_index[ $row['word'] ] = $row['page_names'] . ',' . $search->index[ $row['word'] ]; |
991 $new_index[ $row['word'] ] = $row['page_names'] . ',' . $search->index[ $row['word'] ]; |
992 } |
992 } |
993 $db->free_result(); |
993 $db->free_result(); |
994 |
994 |
995 $db->sql_query('DELETE FROM '.table_prefix.'search_index WHERE '.$keys.';'); |
995 $db->sql_query('DELETE FROM '.table_prefix.'search_index WHERE '.$keys.';'); |
996 |
996 |
997 $secs = Array(); |
997 $secs = Array(); |
998 $q = 'INSERT INTO '.table_prefix.'search_index(word,word_lcase,page_names) VALUES'; |
998 $q = 'INSERT INTO '.table_prefix.'search_index(word,word_lcase,page_names) VALUES'; |
999 foreach($new_index as $word => $pages) |
999 foreach($new_index as $word => $pages) |
1000 { |
1000 { |
1001 $secs[] = '(\''.$db->escape($word).'\', \'' . $db->escape(strtolower($word)) . '\', \''.$db->escape($pages).'\')'; |
1001 $secs[] = '(\''.$db->escape($word).'\', \'' . $db->escape(strtolower($word)) . '\', \''.$db->escape($pages).'\')'; |
1002 } |
1002 } |
1003 $q .= implode(',', $secs); |
1003 $q .= implode(',', $secs); |
1004 unset($secs); |
1004 unset($secs); |
1005 $q .= ';'; |
1005 $q .= ';'; |
1006 if(!$db->check_query($q)) |
1006 if(!$db->check_query($q)) |
1007 { |
1007 { |
1008 die('BUG: PathManager::rebuild_page_index: Query rejected by SQL parser:<pre>'.$q.'</pre>'); |
1008 die('BUG: PathManager::rebuild_page_index: Query rejected by SQL parser:<pre>'.$q.'</pre>'); |
1009 } |
1009 } |
1010 $result = $db->sql_query($q); |
1010 $result = $db->sql_query($q); |
1011 if($result) |
1011 if($result) |
1012 return true; |
1012 return true; |
1013 else |
1013 else |
1014 $db->_die('The search index was trying to rebuild itself when the error occured.'); |
1014 $db->_die('The search index was trying to rebuild itself when the error occured.'); |
1015 |
1015 |
1016 } |
1016 } |
1017 |
1017 |
1018 /** |
1018 /** |
1019 * Returns a list of groups that a given page is a member of. |
1019 * Returns a list of groups that a given page is a member of. |
1020 * @param string Page ID |
1020 * @param string Page ID |
1021 * @param string Namespace |
1021 * @param string Namespace |
1022 * @return array |
1022 * @return array |
1023 */ |
1023 */ |
1024 |
1024 |
1025 function get_page_groups($page_id, $namespace) |
1025 function get_page_groups($page_id, $namespace) |
1026 { |
1026 { |
1027 global $db, $session, $paths, $template, $plugins; // Common objects |
1027 global $db, $session, $paths, $template, $plugins; // Common objects |
1028 |
1028 |
1029 static $cache = array(); |
1029 static $cache = array(); |
1030 |
1030 |
1031 if ( count($cache) == 0 ) |
1031 if ( count($cache) == 0 ) |
1032 { |
1032 { |
1033 foreach ( $this->nslist as $key => $_ ) |
1033 foreach ( $this->nslist as $key => $_ ) |
1034 { |
1034 { |
1035 $cache[$key] = array(); |
1035 $cache[$key] = array(); |
1036 } |
1036 } |
1037 } |
1037 } |
1038 |
1038 |
1039 if ( !isset($this->nslist[$namespace]) ) |
1039 if ( !isset($this->nslist[$namespace]) ) |
1040 die('$paths->get_page_groups(): HACKING ATTEMPT: namespace "'. htmlspecialchars($namespace) .'" doesn\'t exist'); |
1040 die('$paths->get_page_groups(): HACKING ATTEMPT: namespace "'. htmlspecialchars($namespace) .'" doesn\'t exist'); |
1041 |
1041 |
1042 $page_id_unescaped = $paths->nslist[$namespace] . |
1042 $page_id_unescaped = $paths->nslist[$namespace] . |
1043 dirtify_page_id($page_id); |
1043 dirtify_page_id($page_id); |
1044 $page_id_str = $paths->nslist[$namespace] . |
1044 $page_id_str = $paths->nslist[$namespace] . |
1045 sanitize_page_id($page_id); |
1045 sanitize_page_id($page_id); |
1046 |
1046 |
1047 $page_id = $db->escape(sanitize_page_id($page_id)); |
1047 $page_id = $db->escape(sanitize_page_id($page_id)); |
1048 |
1048 |
1049 if ( isset($cache[$namespace][$page_id]) ) |
1049 if ( isset($cache[$namespace][$page_id]) ) |
1050 { |
1050 { |
1051 return $cache[$namespace][$page_id]; |
1051 return $cache[$namespace][$page_id]; |
1052 } |
1052 } |
1053 |
1053 |
1054 $group_list = array(); |
1054 $group_list = array(); |
1055 |
1055 |
1056 // What linked categories have this page? |
1056 // What linked categories have this page? |
1057 $q = $db->sql_unbuffered_query('SELECT g.pg_id, g.pg_type, g.pg_target FROM '.table_prefix.'page_groups AS g |
1057 $q = $db->sql_unbuffered_query('SELECT g.pg_id, g.pg_type, g.pg_target FROM '.table_prefix.'page_groups AS g |
1058 LEFT JOIN '.table_prefix.'categories AS c |
1058 LEFT JOIN '.table_prefix.'categories AS c |
1059 ON ( ( c.category_id = g.pg_target AND g.pg_type = ' . PAGE_GRP_CATLINK . ' ) OR c.category_id IS NULL ) |
1059 ON ( ( c.category_id = g.pg_target AND g.pg_type = ' . PAGE_GRP_CATLINK . ' ) OR c.category_id IS NULL ) |
1060 LEFT JOIN '.table_prefix.'page_group_members AS m |
1060 LEFT JOIN '.table_prefix.'page_group_members AS m |
1061 ON ( ( g.pg_id = m.pg_id AND g.pg_type = ' . PAGE_GRP_NORMAL . ' ) OR ( m.pg_id IS NULL ) ) |
1061 ON ( ( g.pg_id = m.pg_id AND g.pg_type = ' . PAGE_GRP_NORMAL . ' ) OR ( m.pg_id IS NULL ) ) |
1062 LEFT JOIN '.table_prefix.'tags AS t |
1062 LEFT JOIN '.table_prefix.'tags AS t |
1063 ON ( ( t.tag_name = g.pg_target AND pg_type = ' . PAGE_GRP_TAGGED . ' ) OR t.tag_name IS NULL ) |
1063 ON ( ( t.tag_name = g.pg_target AND pg_type = ' . PAGE_GRP_TAGGED . ' ) OR t.tag_name IS NULL ) |
1064 WHERE |
1064 WHERE |
1065 ( c.page_id=\'' . $page_id . '\' AND c.namespace=\'' . $namespace . '\' ) OR |
1065 ( c.page_id=\'' . $page_id . '\' AND c.namespace=\'' . $namespace . '\' ) OR |
1066 ( t.page_id=\'' . $page_id . '\' AND t.namespace=\'' . $namespace . '\' ) OR |
1066 ( t.page_id=\'' . $page_id . '\' AND t.namespace=\'' . $namespace . '\' ) OR |
1067 ( m.page_id=\'' . $page_id . '\' AND m.namespace=\'' . $namespace . '\' ) OR |
1067 ( m.page_id=\'' . $page_id . '\' AND m.namespace=\'' . $namespace . '\' ) OR |
1068 ( g.pg_type = ' . PAGE_GRP_REGEX . ' );'); |
1068 ( g.pg_type = ' . PAGE_GRP_REGEX . ' );'); |
1069 if ( !$q ) |
1069 if ( !$q ) |
1070 $db->_die(); |
1070 $db->_die(); |
1071 |
1071 |
1072 while ( $row = $db->fetchrow() ) |
1072 while ( $row = $db->fetchrow() ) |
1073 { |
1073 { |
1074 if ( $row['pg_type'] == PAGE_GRP_REGEX ) |
1074 if ( $row['pg_type'] == PAGE_GRP_REGEX ) |
1075 { |
1075 { |
1076 //echo "<debug> matching page " . htmlspecialchars($page_id_unescaped) . " against regex <tt>" . htmlspecialchars($row['pg_target']) . "</tt>."; |
1076 //echo "<debug> matching page " . htmlspecialchars($page_id_unescaped) . " against regex <tt>" . htmlspecialchars($row['pg_target']) . "</tt>."; |
1077 if ( @preg_match($row['pg_target'], $page_id_unescaped) || @preg_match($row['pg_target'], $page_id_str) ) |
1077 if ( @preg_match($row['pg_target'], $page_id_unescaped) || @preg_match($row['pg_target'], $page_id_str) ) |
1078 { |
1078 { |
1079 //echo "..matched"; |
1079 //echo "..matched"; |
1080 $group_list[] = $row['pg_id']; |
1080 $group_list[] = $row['pg_id']; |
1081 } |
1081 } |
1082 //echo "<br />"; |
1082 //echo "<br />"; |
1083 } |
1083 } |
1084 else |
1084 else |
1085 { |
1085 { |
1086 $group_list[] = $row['pg_id']; |
1086 $group_list[] = $row['pg_id']; |
1087 } |
1087 } |
1088 } |
1088 } |
1089 |
1089 |
1090 $db->free_result(); |
1090 $db->free_result(); |
1091 |
1091 |
1092 $cache[$namespace][$page_id] = $group_list; |
1092 $cache[$namespace][$page_id] = $group_list; |
1093 |
1093 |
1094 return $group_list; |
1094 return $group_list; |
1095 |
1095 |
1096 } |
1096 } |
1097 |
1097 |
1098 } |
1098 } |
1099 |
1099 |
1100 /** |
1100 /** |
1101 * Register a special page. |
1101 * Register a special page. |
1102 * @param string urlname of the page ("Administration" in "Special:Administration") |
1102 * @param string urlname of the page ("Administration" in "Special:Administration") |