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 |
*
|
|
8 |
* This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
|
|
9 |
* as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
|
|
10 |
*
|
|
11 |
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
12 |
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
|
|
13 |
*/
|
|
14 |
|
|
15 |
function getConfig($n) {
|
|
16 |
global $enano_config;
|
|
17 |
if(isset($enano_config[$n])) return $enano_config[$n];
|
|
18 |
else return false;
|
|
19 |
}
|
|
20 |
|
|
21 |
function setConfig($n, $v) {
|
|
22 |
global $enano_config, $db;
|
|
23 |
$enano_config[$n] = $v;
|
|
24 |
$v = $db->escape($v);
|
|
25 |
$e=$db->sql_query('DELETE FROM '.table_prefix.'config WHERE config_name=\''.$n.'\';');
|
|
26 |
if(!$e) $db->_die('Error during generic setConfig() call row deletion.');
|
|
27 |
$e=$db->sql_query('INSERT INTO '.table_prefix.'config(config_name, config_value) VALUES(\''.$n.'\', \''.$v.'\')');
|
|
28 |
if(!$e) $db->_die('Error during generic setConfig() call row insertion.');
|
|
29 |
}
|
|
30 |
|
|
31 |
function makeUrl($t, $query = false, $escape = false)
|
|
32 |
{
|
|
33 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
34 |
$flags = '';
|
|
35 |
$sep = urlSeparator;
|
|
36 |
if(isset($_GET['printable'])) { $flags .= $sep.'printable'; $sep = '&'; }
|
|
37 |
if(isset($_GET['theme'])) { $flags .= $sep.'theme='.$session->theme; $sep = '&'; }
|
|
38 |
if(isset($_GET['style'])) { $flags .= $sep.'style='.$session->style; $sep = '&'; }
|
|
39 |
$url = $session->append_sid(contentPath.$t.$flags);
|
|
40 |
if($query)
|
|
41 |
{
|
|
42 |
$sep = strstr($url, '?') ? '&' : '?';
|
|
43 |
$url = $url . $sep . $query;
|
|
44 |
}
|
|
45 |
return ($escape) ? htmlspecialchars($url) : $url;
|
|
46 |
}
|
|
47 |
|
|
48 |
function makeUrlNS($n, $t, $query = false, $escape = false)
|
|
49 |
{
|
|
50 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
51 |
$flags = '';
|
|
52 |
if(defined('ENANO_BASE_CLASSES_INITIALIZED')) $sep = urlSeparator;
|
|
53 |
else $sep = (strstr($_SERVER['REQUEST_URI'], '?')) ? '&' : '?';
|
|
54 |
if(isset($_GET['printable'])) { $flags .= $sep.'printable'; $sep = '&'; }
|
|
55 |
if(isset($_GET['theme'])) { $flags .= $sep.'theme='.$session->theme; $sep = '&'; }
|
|
56 |
if(isset($_GET['style'])) { $flags .= $sep.'style='.$session->style; $sep = '&'; }
|
|
57 |
|
|
58 |
if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
|
|
59 |
{
|
|
60 |
$url = contentPath.$paths->nslist[$n].$t.$flags;
|
|
61 |
}
|
|
62 |
else
|
|
63 |
{
|
|
64 |
$url = contentPath.$n.':'.$t.$flags;
|
|
65 |
}
|
|
66 |
|
|
67 |
if($query)
|
|
68 |
{
|
|
69 |
if(strstr($url, '?')) $sep = '&';
|
|
70 |
else $sep = '?';
|
|
71 |
$url = $url . $sep . $query . $flags;
|
|
72 |
}
|
|
73 |
|
|
74 |
if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
|
|
75 |
{
|
|
76 |
$url = $session->append_sid($url);
|
|
77 |
}
|
|
78 |
|
|
79 |
return ($escape) ? htmlspecialchars($url) : $url;
|
|
80 |
}
|
|
81 |
|
|
82 |
function makeUrlComplete($n, $t, $query = false, $escape = false)
|
|
83 |
{
|
|
84 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
85 |
$flags = '';
|
|
86 |
if(defined('ENANO_BASE_CLASSES_INITIALIZED')) $sep = urlSeparator;
|
|
87 |
else $sep = (strstr($_SERVER['REQUEST_URI'], '?')) ? '&' : '?';
|
|
88 |
if(isset($_GET['printable'])) { $flags .= $sep.'printable'; $sep = '&'; }
|
|
89 |
if(isset($_GET['theme'])) { $flags .= $sep.'theme='.$session->theme; $sep = '&'; }
|
|
90 |
if(isset($_GET['style'])) { $flags .= $sep.'style='.$session->style; $sep = '&'; }
|
|
91 |
if(defined('ENANO_BASE_CLASSES_INITIALIZED')) $url = $session->append_sid(contentPath.$paths->nslist[$n].$t.$flags);
|
|
92 |
else $url = contentPath.$n.':'.$t.$flags;
|
|
93 |
if($query)
|
|
94 |
{
|
|
95 |
if(strstr($url, '?')) $sep = '&';
|
|
96 |
else $sep = '?';
|
|
97 |
$url = $url . $sep . $query . $flags;
|
|
98 |
}
|
|
99 |
$baseprot = 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://' . $_SERVER['HTTP_HOST'];
|
|
100 |
$url = $baseprot . $url;
|
|
101 |
return ($escape) ? htmlspecialchars($url) : $url;
|
|
102 |
}
|
|
103 |
|
|
104 |
/**
|
|
105 |
* Redirect the user to the specified URL.
|
|
106 |
* @param string $url The URL, either relative or absolute.
|
|
107 |
* @param string $title The title of the message
|
|
108 |
* @param string $message A short message to show to the user
|
|
109 |
* @param string $timeout Timeout, in seconds, to delay the redirect. Defaults to 3.
|
|
110 |
*/
|
|
111 |
|
|
112 |
function redirect($url, $title = 'Redirecting...', $message = 'Please wait while you are redirected.', $timeout = 3)
|
|
113 |
{
|
|
114 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
115 |
|
|
116 |
if ( $timeout == 0 )
|
|
117 |
{
|
|
118 |
header('Location: ' . $url);
|
|
119 |
header('HTTP/1.1 307 Temporary Redirect');
|
|
120 |
}
|
|
121 |
|
|
122 |
$template->add_header('<meta http-equiv="refresh" content="' . $timeout . '; url=' . str_replace('"', '\\"', $url) . '" />');
|
|
123 |
$template->add_header('<script type="text/javascript">
|
|
124 |
function __r() {
|
|
125 |
// FUNCTION AUTOMATICALLY GENERATED
|
|
126 |
window.location="' . str_replace('"', '\\"', $url) . '";
|
|
127 |
}
|
|
128 |
setTimeout(\'__r();\', ' . $timeout . '000);
|
|
129 |
</script>
|
|
130 |
');
|
|
131 |
|
|
132 |
$template->tpl_strings['PAGE_NAME'] = $title;
|
|
133 |
$template->header(true);
|
|
134 |
echo '<p>' . $message . '</p><p>If you are not redirected within ' . ( $timeout + 1 ) . ' seconds, <a href="' . str_replace('"', '\\"', $url) . '">please click here</a>.</p>';
|
|
135 |
$template->footer(true);
|
|
136 |
|
|
137 |
$db->close();
|
|
138 |
exit(0);
|
|
139 |
|
|
140 |
}
|
|
141 |
|
|
142 |
// Removed wikiFormat() from here, replaced with RenderMan::render
|
|
143 |
|
|
144 |
function isPage($p) {
|
|
145 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
146 |
if(isset($paths->pages[$p])) return true;
|
|
147 |
$d = RenderMan::strToPageID($p);
|
|
148 |
if($d[1] != 'Special' && $d[1] != 'Template' && $d[1] != 'Admin') return false;
|
|
149 |
$a = explode('/', $p);
|
|
150 |
if(isset($paths->pages[$a[0]])) return true;
|
|
151 |
else return false;
|
|
152 |
}
|
|
153 |
|
|
154 |
function arrayItemUp($arr, $keyname) {
|
|
155 |
$keylist = array_keys($arr);
|
|
156 |
$keyflop = array_flip($keylist);
|
|
157 |
$idx = $keyflop[$keyname];
|
|
158 |
$idxm = $idx - 1;
|
|
159 |
$temp = $arr[$keylist[$idxm]];
|
|
160 |
if($arr[$keylist[0]] == $arr[$keyname]) return $arr;
|
|
161 |
$arr[$keylist[$idxm]] = $arr[$keylist[$idx]];
|
|
162 |
$arr[$keylist[$idx]] = $temp;
|
|
163 |
return $arr;
|
|
164 |
}
|
|
165 |
|
|
166 |
function arrayItemDown($arr, $keyname) {
|
|
167 |
$keylist = array_keys($arr);
|
|
168 |
$keyflop = array_flip($keylist);
|
|
169 |
$idx = $keyflop[$keyname];
|
|
170 |
$idxm = $idx + 1;
|
|
171 |
$temp = $arr[$keylist[$idxm]];
|
|
172 |
$sz = sizeof($arr); $sz--;
|
|
173 |
if($arr[$keylist[$sz]] == $arr[$keyname]) return $arr;
|
|
174 |
$arr[$keylist[$idxm]] = $arr[$keylist[$idx]];
|
|
175 |
$arr[$keylist[$idx]] = $temp;
|
|
176 |
return $arr;
|
|
177 |
}
|
|
178 |
|
|
179 |
function arrayItemTop($arr, $keyname) {
|
|
180 |
$keylist = array_keys($arr);
|
|
181 |
$keyflop = array_flip($keylist);
|
|
182 |
$idx = $keyflop[$keyname];
|
|
183 |
while( $orig != $arr[$keylist[0]] ) {
|
|
184 |
// echo 'Keyname: '.$keylist[$idx] . '<br />'; flush(); ob_flush(); // Debugger
|
|
185 |
if($idx < 0) return $arr;
|
|
186 |
if($keylist[$idx] == '' || $keylist[$idx] < 0 || !$keylist[$idx]) {
|
|
187 |
/* echo 'Infinite loop caught in arrayItemTop(<br /><pre>';
|
|
188 |
print_r($arr);
|
|
189 |
echo '</pre><br />, '.$keyname.');<br /><br />EnanoCMS: Critical error during function call, exiting to prevent excessive server load.';
|
|
190 |
exit; */
|
|
191 |
return $arr;
|
|
192 |
}
|
|
193 |
$arr = arrayItemUp($arr, $keylist[$idx]);
|
|
194 |
$idx--;
|
|
195 |
}
|
|
196 |
return $arr;
|
|
197 |
}
|
|
198 |
|
|
199 |
function arrayItemBottom($arr, $keyname) {
|
|
200 |
$keylist = array_keys($arr);
|
|
201 |
$keyflop = array_flip($keylist);
|
|
202 |
$idx = $keyflop[$keyname];
|
|
203 |
$sz = sizeof($arr); $sz--;
|
|
204 |
while( $orig != $arr[$keylist[$sz]] ) {
|
|
205 |
// echo 'Keyname: '.$keylist[$idx] . '<br />'; flush(); ob_flush(); // Debugger
|
|
206 |
if($idx > $sz) return $arr;
|
|
207 |
if($keylist[$idx] == '' || $keylist[$idx] < 0 || !$keylist[$idx]) {
|
|
208 |
echo 'Infinite loop caught in arrayItemBottom(<br /><pre>';
|
|
209 |
print_r($arr);
|
|
210 |
echo '</pre><br />, '.$keyname.');<br /><br />EnanoCMS: Critical error during function call, exiting to prevent excessive server load.';
|
|
211 |
exit;
|
|
212 |
}
|
|
213 |
$arr = arrayItemDown($arr, $keylist[$idx]);
|
|
214 |
$idx++;
|
|
215 |
}
|
|
216 |
return $arr;
|
|
217 |
}
|
|
218 |
|
|
219 |
// Convert IP address to hex string
|
|
220 |
// Input: 127.0.0.1 (string)
|
|
221 |
// Output: 0x7f000001 (string)
|
|
222 |
// Updated 12/8/06 to work with PHP4 and not use eval() (blech)
|
|
223 |
function ip2hex($ip) {
|
|
224 |
if ( preg_match('/^([0-9a-f:]+)$/', $ip) )
|
|
225 |
{
|
|
226 |
// this is an ipv6 address
|
|
227 |
return str_replace(':', '', $ip);
|
|
228 |
}
|
|
229 |
$nums = explode('.', $ip);
|
|
230 |
if(sizeof($nums) != 4) return false;
|
|
231 |
$str = '0x';
|
|
232 |
foreach($nums as $n)
|
|
233 |
{
|
|
234 |
$str .= (string)dechex($n);
|
|
235 |
}
|
|
236 |
return $str;
|
|
237 |
}
|
|
238 |
|
|
239 |
// Convert DWord to IP address
|
|
240 |
// Input: 0x7f000001
|
|
241 |
// Output: 127.0.0.1
|
|
242 |
// Updated 12/8/06 to work with PHP4 and not use eval() (blech)
|
|
243 |
function hex2ip($in) {
|
|
244 |
if(substr($in, 0, 2) == '0x') $ip = substr($in, 2, 8);
|
|
245 |
else $ip = substr($in, 0, 8);
|
|
246 |
$octets = enano_str_split($ip, 2);
|
|
247 |
$str = '';
|
|
248 |
$newoct = Array();
|
|
249 |
foreach($octets as $o)
|
|
250 |
{
|
|
251 |
$o = (int)hexdec($o);
|
|
252 |
$newoct[] = $o;
|
|
253 |
}
|
|
254 |
return implode('.', $newoct);
|
|
255 |
}
|
|
256 |
|
|
257 |
// Function strip_php moved to RenderMan class
|
|
258 |
|
|
259 |
function die_semicritical($t, $p)
|
|
260 |
{
|
|
261 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
262 |
$db->close();
|
|
263 |
|
|
264 |
if ( ob_get_status() )
|
|
265 |
ob_end_clean();
|
|
266 |
|
|
267 |
dc_here('functions: <span style="color: red">calling die_semicritical</span>');
|
|
268 |
|
|
269 |
$tpl = new template_nodb();
|
|
270 |
$tpl->load_theme('oxygen', 'bleu');
|
|
271 |
$tpl->tpl_strings['SITE_NAME'] = getConfig('site_name');
|
|
272 |
$tpl->tpl_strings['SITE_DESC'] = getConfig('site_desc');
|
|
273 |
$tpl->tpl_strings['COPYRIGHT'] = getConfig('copyright_notice');
|
|
274 |
$tpl->tpl_strings['PAGE_NAME'] = $t;
|
|
275 |
$tpl->header();
|
|
276 |
echo $p;
|
|
277 |
$tpl->footer();
|
|
278 |
|
|
279 |
exit;
|
|
280 |
}
|
|
281 |
|
|
282 |
function die_friendly($t, $p)
|
|
283 |
{
|
|
284 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
285 |
|
|
286 |
if ( ob_get_status() )
|
|
287 |
ob_end_clean();
|
|
288 |
|
|
289 |
dc_here('functions: <span style="color: red">calling die_friendly</span>');
|
|
290 |
$paths->cpage['name'] = $t;
|
|
291 |
$template->tpl_strings['PAGE_NAME'] = $t;
|
|
292 |
$template->header();
|
|
293 |
echo $p;
|
|
294 |
$template->footer();
|
|
295 |
$db->close();
|
|
296 |
|
|
297 |
exit;
|
|
298 |
}
|
|
299 |
|
|
300 |
function grinding_halt($t, $p)
|
|
301 |
{
|
|
302 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
303 |
|
|
304 |
$db->close();
|
|
305 |
|
|
306 |
if ( ob_get_status() )
|
|
307 |
ob_end_clean();
|
|
308 |
|
|
309 |
dc_here('functions: <span style="color: red">calling grinding_halt</span>');
|
|
310 |
$tpl = new template_nodb();
|
|
311 |
$tpl->load_theme('oxygen', 'bleu');
|
|
312 |
$tpl->tpl_strings['SITE_NAME'] = 'Critical error';
|
|
313 |
$tpl->tpl_strings['SITE_DESC'] = 'This website is experiencing a serious error and cannot load.';
|
|
314 |
$tpl->tpl_strings['COPYRIGHT'] = 'Unable to retrieve copyright information';
|
|
315 |
$tpl->tpl_strings['PAGE_NAME'] = $t;
|
|
316 |
$tpl->header();
|
|
317 |
echo $p;
|
|
318 |
$tpl->footer();
|
|
319 |
exit;
|
|
320 |
}
|
|
321 |
|
|
322 |
function show_category_info() {
|
|
323 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
324 |
dc_here('functions: showing category info');
|
|
325 |
if($template->no_headers && !strpos($_SERVER['REQUEST_URI'], 'ajax.php')) return '';
|
|
326 |
if($paths->namespace=='Category')
|
|
327 |
{
|
|
328 |
$q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\'Category\' ORDER BY page_id;');
|
|
329 |
if(!$q) $db->_die('The category information could not be selected.');
|
|
330 |
$ticker = -1;
|
|
331 |
echo '<h3>Subcategories</h3>';
|
|
332 |
if($db->numrows() < 1) echo '<p>There are no subcategories in this category.</p>';
|
|
333 |
echo '<table border="0" cellspacing="1" cellpadding="4">';
|
|
334 |
while($row = $db->fetchrow())
|
|
335 |
{
|
|
336 |
$ticker++;if($ticker==3) $ticker=0;
|
|
337 |
if($ticker==0) echo '<tr>';
|
|
338 |
echo '<td style="width: 200px;"><a href="'.makeUrlNS($row['namespace'], $row['page_id']).'">'.$paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]['name'].'</a></td>';
|
|
339 |
if($ticker==2) echo '</tr>';
|
|
340 |
}
|
|
341 |
$db->free_result();
|
|
342 |
if($ticker) echo '</tr>';
|
|
343 |
echo '</table>';
|
|
344 |
|
|
345 |
$q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace!=\'Category\' ORDER BY page_id;');
|
|
346 |
if(!$q) $db->_die('The category information could not be selected.');
|
|
347 |
$ticker = -1;
|
|
348 |
echo '<h3>Pages</h3>';
|
|
349 |
if($db->numrows() < 1) echo '<p>There are no pages in this category.</p>';
|
|
350 |
echo '<table border="0" cellspacing="1" cellpadding="4">';
|
|
351 |
while($row = $db->fetchrow())
|
|
352 |
{
|
|
353 |
$ticker++;if($ticker==3) $ticker=0;
|
|
354 |
if($ticker==0) echo '<tr>';
|
|
355 |
echo '<td style="width: 200px;"><a href="'.makeUrlNS($row['namespace'], $row['page_id']).'">'.$paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]['name'].'</a></td>';
|
|
356 |
if($ticker==2) echo '</tr>';
|
|
357 |
}
|
|
358 |
$db->free_result();
|
|
359 |
if($ticker) echo '</tr>';
|
|
360 |
echo '</table><br /><br />';
|
|
361 |
}
|
|
362 |
$q = $db->sql_query('SELECT category_id FROM '.table_prefix.'categories WHERE page_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\''.$paths->namespace.'\'');
|
|
363 |
if(!$q) $db->_die('The error seems to have occurred during selection of category data.');
|
|
364 |
if($db->numrows() > 0) {
|
|
365 |
echo '<div class="mdg-comment" style="margin-left: 0;">Categories: ';
|
|
366 |
$i=0;
|
|
367 |
while($r = $db->fetchrow())
|
|
368 |
{
|
|
369 |
if($i>0) echo ', ';
|
|
370 |
$i++;
|
|
371 |
echo '<a href="'.makeUrlNS('Category', $r['category_id']).'">'.$paths->pages[$paths->nslist['Category'].$r['category_id']]['name'].'</a>';
|
|
372 |
}
|
|
373 |
if( ( $paths->wiki_mode && !$paths->page_protected ) || ( $session->get_permissions('edit_cat') && $session->get_permissions('even_when_protected') ) ) echo ' [ <a href="'.makeUrl($paths->page, 'do=catedit', true).'" onclick="ajaxCatEdit(); return false;">edit categorization</a> ]</div>';
|
|
374 |
} else {
|
|
375 |
echo '<div class="mdg-comment" style="margin-left: 0;">Categories: ';
|
|
376 |
echo '(Uncategorized)';
|
|
377 |
if( ( $paths->wiki_mode && !$paths->page_protected ) || ( $session->get_permissions('edit_cat') && $session->get_permissions('even_when_protected') ) ) echo ' [ <a href="'.makeUrl($paths->page, 'do=catedit', true).'" onclick="ajaxCatEdit(); return false;">edit categorization</a> ]</div>';
|
|
378 |
else echo '</div>';
|
|
379 |
}
|
|
380 |
$db->free_result();
|
|
381 |
}
|
|
382 |
|
|
383 |
function show_file_info()
|
|
384 |
{
|
|
385 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
386 |
if($paths->namespace != 'File') return null; // Prevent unnecessary work
|
|
387 |
$selfn = $paths->cpage['urlname_nons']; // substr($paths->page, strlen($paths->nslist['File']), strlen($paths->cpage));
|
|
388 |
if(substr($paths->cpage['name'], 0, strlen($paths->nslist['File']))==$paths->nslist['File']) $selfn = substr($paths->cpage['urlname_nons'], strlen($paths->nslist['File']), strlen($paths->cpage['urlname_nons']));
|
|
389 |
$q = $db->sql_query('SELECT mimetype,time_id,size FROM '.table_prefix.'files WHERE page_id=\''.$selfn.'\' ORDER BY time_id DESC;');
|
|
390 |
if(!$q) $db->_die('The file type could not be fetched.');
|
|
391 |
if($db->numrows() < 1) { echo '<div class="mdg-comment" style="margin-left: 0;"><h3>Uploaded file</h3><p>There are no files uploaded with this name yet. <a href="'.makeUrlNS('Special', 'UploadFile/'.$paths->cpage['urlname_nons']).'">Upload a file...</a></p></div><br />'; return; }
|
|
392 |
$r = $db->fetchrow();
|
|
393 |
$mimetype = $r['mimetype'];
|
|
394 |
$datestring = date('F d, Y h:i a', (int)$r['time_id']);
|
|
395 |
echo '<div class="mdg-comment" style="margin-left: 0;"><p><h3>Uploaded file</h3></p><p>Type: '.$r['mimetype'].'<br />Size: ';
|
|
396 |
$fs = $r['size'];
|
|
397 |
echo $fs.' bytes';
|
|
398 |
$fs = (int)$fs;
|
|
399 |
if($fs >= 1048576)
|
|
400 |
{
|
|
401 |
$fs = round($fs / 1048576, 1);
|
|
402 |
echo ' ('.$fs.' MB)';
|
|
403 |
} elseif($fs >= 1024) {
|
|
404 |
$fs = round($fs / 1024, 1);
|
|
405 |
echo ' ('.$fs.' KB)';
|
|
406 |
}
|
|
407 |
echo '<br />Uploaded: '.$datestring.'</p>';
|
|
408 |
if(substr($mimetype, 0, 6)!='image/' && ( substr($mimetype, 0, 5) != 'text/' || $mimetype == 'text/html' || $mimetype == 'text/javascript' ))
|
|
409 |
{
|
|
410 |
echo '<div class="warning-box">This file type may contain viruses or other code that could harm your computer. You should exercise caution if you download it.</div>';
|
|
411 |
}
|
|
412 |
if(substr($mimetype, 0, 6)=='image/')
|
|
413 |
{
|
|
414 |
echo '<p><a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn).'"><img style="border: 0;" alt="'.$paths->page.'" src="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.htmlspecialchars(urlSeparator).'preview').'" /></a></p>';
|
|
415 |
}
|
|
416 |
echo '<p><a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'">Download this file</a>';
|
|
417 |
if(!$paths->page_protected && ( $paths->wiki_mode || $session->get_permissions('upload_new_version') ))
|
|
418 |
{
|
|
419 |
echo ' | <a href="'.makeUrlNS('Special', 'UploadFile'.'/'.$selfn).'">Upload new version</a>';
|
|
420 |
}
|
|
421 |
echo '</p>';
|
|
422 |
if($db->numrows() > 1)
|
|
423 |
{
|
|
424 |
echo '<h3>File history</h3><p>';
|
|
425 |
while($r = $db->fetchrow())
|
|
426 |
{
|
|
427 |
echo '(<a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'">this ver</a>) ';
|
|
428 |
if($session->get_permissions('history_rollback'))
|
|
429 |
echo ' (<a href="#" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;">revert</a>) ';
|
|
430 |
$mimetype = $r['mimetype'];
|
|
431 |
$datestring = date('F d, Y h:i a', (int)$r['time_id']);
|
|
432 |
echo $datestring.': '.$r['mimetype'].', ';
|
|
433 |
$fs = $r['size'];
|
|
434 |
$fs = (int)$fs;
|
|
435 |
if($fs >= 1048576)
|
|
436 |
{
|
|
437 |
$fs = round($fs / 1048576, 1);
|
|
438 |
echo ' '.$fs.' MB';
|
|
439 |
} elseif($fs >= 1024) {
|
|
440 |
$fs = round($fs / 1024, 1);
|
|
441 |
echo ' '.$fs.' KB';
|
|
442 |
} else {
|
|
443 |
echo ' '.$fs.' bytes';
|
|
444 |
}
|
|
445 |
echo '<br />';
|
|
446 |
}
|
|
447 |
echo '</p>';
|
|
448 |
}
|
|
449 |
$db->free_result();
|
|
450 |
echo '</div><br />';
|
|
451 |
}
|
|
452 |
|
|
453 |
function display_page_headers()
|
|
454 |
{
|
|
455 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
456 |
if($session->get_permissions('vote_reset') && $paths->cpage['delvotes'] > 0)
|
|
457 |
{
|
|
458 |
$hr = implode(', ', explode('|', $paths->cpage['delvote_ips']));
|
|
459 |
$is = 'is';
|
|
460 |
$s = '';
|
|
461 |
$s2 = 's';
|
|
462 |
if ( $paths->cpage['delvotes'] > 1)
|
|
463 |
{
|
|
464 |
$is = 'are';
|
|
465 |
$s = 's';
|
|
466 |
$s2 = '';
|
|
467 |
}
|
|
468 |
echo '<div class="info-box" style="margin-left: 0; margin-top: 5px;" id="mdgDeleteVoteNoticeBox">
|
|
469 |
<b>Notice:</b> There '.$is.' '.$paths->cpage['delvotes'].' user'.$s.' that think'.$s2.' this page should be deleted.<br />
|
|
470 |
<b>Users that voted:</b> ' . $hr . '<br />
|
|
471 |
<a href="'.makeUrl($paths->page, 'do=deletepage').'" onclick="ajaxDeletePage(); return false;">Delete page</a> | <a href="'.makeUrl($paths->page, 'do=resetvotes').'" onclick="ajaxResetDelVotes(); return false;">Reset votes</a>
|
|
472 |
</div>';
|
|
473 |
}
|
|
474 |
}
|
|
475 |
|
|
476 |
function display_page_footers()
|
|
477 |
{
|
|
478 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
479 |
if(isset($_GET['nofooters'])) return;
|
|
480 |
$code = $plugins->setHook('send_page_footers');
|
|
481 |
foreach ( $code as $cmd )
|
|
482 |
{
|
|
483 |
eval($cmd);
|
|
484 |
}
|
|
485 |
show_file_info();
|
|
486 |
show_category_info();
|
|
487 |
}
|
|
488 |
|
|
489 |
function password_prompt($id = false)
|
|
490 |
{
|
|
491 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
492 |
if(!$id) $id = $paths->page;
|
|
493 |
if(isset($paths->pages[$id]['password']) && strlen($paths->pages[$id]['password']) == 40 && !isset($_REQUEST['pagepass']))
|
|
494 |
{
|
|
495 |
die_friendly('Password required', '<p>You must supply a password to access this page.</p><form action="'.makeUrl($paths->pages[$id]['urlname']).'" method="post"><p>Password: <input name="pagepass" type="password" /></p><p><input type="submit" value="Submit" /></p>');
|
|
496 |
} elseif(isset($_REQUEST['pagepass'])) {
|
|
497 |
$p = (preg_match('#^([a-f0-9]*){40}$#', $_REQUEST['pagepass'])) ? $_REQUEST['pagepass'] : sha1($_REQUEST['pagepass']);
|
|
498 |
if($p != $paths->pages[$id]['password']) die_friendly('Password required', '<p style="color: red;">The password you entered is incorrect.</p><form action="'.makeUrl($paths->page).'" method="post"><p>Password: <input name="pagepass" type="password" /></p><p><input type="submit" value="Submit" /></p>');
|
|
499 |
}
|
|
500 |
}
|
|
501 |
|
|
502 |
function str_hex($string){
|
|
503 |
$hex='';
|
|
504 |
for ($i=0; $i < strlen($string); $i++){
|
|
505 |
$hex .= ' '.dechex(ord($string[$i]));
|
|
506 |
}
|
|
507 |
return substr($hex, 1, strlen($hex));
|
|
508 |
}
|
|
509 |
|
|
510 |
// Function pulled from phpBB's smtp.php
|
|
511 |
function smtp_get_response($socket, $response, $line = __LINE__)
|
|
512 |
{
|
|
513 |
$server_response = '';
|
|
514 |
while (substr($server_response, 3, 1) != ' ')
|
|
515 |
{
|
|
516 |
if (!($server_response = fgets($socket, 256)))
|
|
517 |
{
|
|
518 |
die_friendly('SMTP Error', "<p>Couldn't get mail server response codes</p>");
|
|
519 |
}
|
|
520 |
}
|
|
521 |
|
|
522 |
if (!(substr($server_response, 0, 3) == $response))
|
|
523 |
{
|
|
524 |
die_friendly('SMTP Error', "<p>Ran into problems sending mail. Response: $server_response</p>");
|
|
525 |
}
|
|
526 |
}
|
|
527 |
|
|
528 |
function smtp_send_email($to, $subject, $message, $from)
|
|
529 |
{
|
|
530 |
return smtp_send_email_core($to, $subject, $message, "From: <$from>\n");
|
|
531 |
}
|
|
532 |
|
|
533 |
// Replacement or substitute for PHP's mail command
|
|
534 |
// Ported from phpBB - copyright (C) phpBB group, GPL.
|
|
535 |
function smtp_send_email_core($mail_to, $subject, $message, $headers = '')
|
|
536 |
{
|
|
537 |
global $board_config;
|
|
538 |
|
|
539 |
// Fix any bare linefeeds in the message to make it RFC821 Compliant.
|
|
540 |
$message = preg_replace("#(?<!\r)\n#si", "\r\n", $message);
|
|
541 |
|
|
542 |
if ($headers != '')
|
|
543 |
{
|
|
544 |
if (is_array($headers))
|
|
545 |
{
|
|
546 |
if (sizeof($headers) > 1)
|
|
547 |
{
|
|
548 |
$headers = join("\n", $headers);
|
|
549 |
}
|
|
550 |
else
|
|
551 |
{
|
|
552 |
$headers = $headers[0];
|
|
553 |
}
|
|
554 |
}
|
|
555 |
$headers = chop($headers);
|
|
556 |
|
|
557 |
// Make sure there are no bare linefeeds in the headers
|
|
558 |
$headers = preg_replace('#(?<!\r)\n#si', "\r\n", $headers);
|
|
559 |
|
|
560 |
// Ok this is rather confusing all things considered,
|
|
561 |
// but we have to grab bcc and cc headers and treat them differently
|
|
562 |
// Something we really didn't take into consideration originally
|
|
563 |
$header_array = explode("\r\n", $headers);
|
|
564 |
@reset($header_array);
|
|
565 |
|
|
566 |
$headers = '';
|
|
567 |
while(list(, $header) = each($header_array))
|
|
568 |
{
|
|
569 |
if (preg_match('#^cc:#si', $header))
|
|
570 |
{
|
|
571 |
$cc = preg_replace('#^cc:(.*)#si', '\1', $header);
|
|
572 |
}
|
|
573 |
else if (preg_match('#^bcc:#si', $header))
|
|
574 |
{
|
|
575 |
$bcc = preg_replace('#^bcc:(.*)#si', '\1', $header);
|
|
576 |
$header = '';
|
|
577 |
}
|
|
578 |
$headers .= ($header != '') ? $header . "\r\n" : '';
|
|
579 |
}
|
|
580 |
|
|
581 |
$headers = chop($headers);
|
|
582 |
$cc = explode(', ', $cc);
|
|
583 |
$bcc = explode(', ', $bcc);
|
|
584 |
}
|
|
585 |
|
|
586 |
if (trim($subject) == '')
|
|
587 |
{
|
|
588 |
die_friendly(GENERAL_ERROR, "No email Subject specified");
|
|
589 |
}
|
|
590 |
|
|
591 |
if (trim($message) == '')
|
|
592 |
{
|
|
593 |
die_friendly(GENERAL_ERROR, "Email message was blank");
|
|
594 |
}
|
|
595 |
|
|
596 |
// setup SMTP
|
|
597 |
$host = getConfig('smtp_server');
|
|
598 |
if ( empty($host) )
|
|
599 |
return 'No smtp_host in config';
|
|
600 |
if ( strstr($host, ':' ) )
|
|
601 |
{
|
|
602 |
$n = explode(':', $host);
|
|
603 |
$smtp_host = $n[0];
|
|
604 |
$port = intval($n[1]);
|
|
605 |
}
|
|
606 |
else
|
|
607 |
{
|
|
608 |
$smtp_host = $host;
|
|
609 |
$port = 25;
|
|
610 |
}
|
|
611 |
|
|
612 |
$smtp_user = getConfig('smtp_user');
|
|
613 |
$smtp_pass = getConfig('smtp_password');
|
|
614 |
|
|
615 |
// Ok we have error checked as much as we can to this point let's get on
|
|
616 |
// it already.
|
|
617 |
if( !$socket = @fsockopen($smtp_host, $port, $errno, $errstr, 20) )
|
|
618 |
{
|
|
619 |
die_friendly(GENERAL_ERROR, "Could not connect to smtp host : $errno : $errstr");
|
|
620 |
}
|
|
621 |
|
|
622 |
// Wait for reply
|
|
623 |
smtp_get_response($socket, "220", __LINE__);
|
|
624 |
|
|
625 |
// Do we want to use AUTH?, send RFC2554 EHLO, else send RFC821 HELO
|
|
626 |
// This improved as provided by SirSir to accomodate
|
|
627 |
if( !empty($smtp_user) && !empty($smtp_pass) )
|
|
628 |
{
|
|
629 |
enano_fputs($socket, "EHLO " . $smtp_host . "\r\n");
|
|
630 |
smtp_get_response($socket, "250", __LINE__);
|
|
631 |
|
|
632 |
enano_fputs($socket, "AUTH LOGIN\r\n");
|
|
633 |
smtp_get_response($socket, "334", __LINE__);
|
|
634 |
|
|
635 |
enano_fputs($socket, base64_encode($smtp_user) . "\r\n");
|
|
636 |
smtp_get_response($socket, "334", __LINE__);
|
|
637 |
|
|
638 |
enano_fputs($socket, base64_encode($smtp_pass) . "\r\n");
|
|
639 |
smtp_get_response($socket, "235", __LINE__);
|
|
640 |
}
|
|
641 |
else
|
|
642 |
{
|
|
643 |
enano_fputs($socket, "HELO " . $smtp_host . "\r\n");
|
|
644 |
smtp_get_response($socket, "250", __LINE__);
|
|
645 |
}
|
|
646 |
|
|
647 |
// From this point onward most server response codes should be 250
|
|
648 |
// Specify who the mail is from....
|
|
649 |
enano_fputs($socket, "MAIL FROM: <" . getConfig('contact_email') . ">\r\n");
|
|
650 |
smtp_get_response($socket, "250", __LINE__);
|
|
651 |
|
|
652 |
// Specify each user to send to and build to header.
|
|
653 |
$to_header = '';
|
|
654 |
|
|
655 |
// Add an additional bit of error checking to the To field.
|
|
656 |
$mail_to = (trim($mail_to) == '') ? 'Undisclosed-recipients:;' : trim($mail_to);
|
|
657 |
if (preg_match('#[^ ]+\@[^ ]+#', $mail_to))
|
|
658 |
{
|
|
659 |
enano_fputs($socket, "RCPT TO: <$mail_to>\r\n");
|
|
660 |
smtp_get_response($socket, "250", __LINE__);
|
|
661 |
}
|
|
662 |
|
|
663 |
// Ok now do the CC and BCC fields...
|
|
664 |
@reset($bcc);
|
|
665 |
while(list(, $bcc_address) = each($bcc))
|
|
666 |
{
|
|
667 |
// Add an additional bit of error checking to bcc header...
|
|
668 |
$bcc_address = trim($bcc_address);
|
|
669 |
if (preg_match('#[^ ]+\@[^ ]+#', $bcc_address))
|
|
670 |
{
|
|
671 |
enano_fputs($socket, "RCPT TO: <$bcc_address>\r\n");
|
|
672 |
smtp_get_response($socket, "250", __LINE__);
|
|
673 |
}
|
|
674 |
}
|
|
675 |
|
|
676 |
@reset($cc);
|
|
677 |
while(list(, $cc_address) = each($cc))
|
|
678 |
{
|
|
679 |
// Add an additional bit of error checking to cc header
|
|
680 |
$cc_address = trim($cc_address);
|
|
681 |
if (preg_match('#[^ ]+\@[^ ]+#', $cc_address))
|
|
682 |
{
|
|
683 |
enano_fputs($socket, "RCPT TO: <$cc_address>\r\n");
|
|
684 |
smtp_get_response($socket, "250", __LINE__);
|
|
685 |
}
|
|
686 |
}
|
|
687 |
|
|
688 |
// Ok now we tell the server we are ready to start sending data
|
|
689 |
enano_fputs($socket, "DATA\r\n");
|
|
690 |
|
|
691 |
// This is the last response code we look for until the end of the message.
|
|
692 |
smtp_get_response($socket, "354", __LINE__);
|
|
693 |
|
|
694 |
// Send the Subject Line...
|
|
695 |
enano_fputs($socket, "Subject: $subject\r\n");
|
|
696 |
|
|
697 |
// Now the To Header.
|
|
698 |
enano_fputs($socket, "To: $mail_to\r\n");
|
|
699 |
|
|
700 |
// Now any custom headers....
|
|
701 |
enano_fputs($socket, "$headers\r\n\r\n");
|
|
702 |
|
|
703 |
// Ok now we are ready for the message...
|
|
704 |
enano_fputs($socket, "$message\r\n");
|
|
705 |
|
|
706 |
// Ok the all the ingredients are mixed in let's cook this puppy...
|
|
707 |
enano_fputs($socket, ".\r\n");
|
|
708 |
smtp_get_response($socket, "250", __LINE__);
|
|
709 |
|
|
710 |
// Now tell the server we are done and close the socket...
|
|
711 |
enano_fputs($socket, "QUIT\r\n");
|
|
712 |
fclose($socket);
|
|
713 |
|
|
714 |
return TRUE;
|
|
715 |
}
|
|
716 |
|
|
717 |
/**
|
|
718 |
* Tell which version of Enano we're running.
|
|
719 |
* @param bool $long if true, uses English version names (e.g. alpha, beta, release candidate). If false (default) uses abbreviations (1.0a1, 1.0b3, 1.0RC2, etc.)
|
|
720 |
* @return string
|
|
721 |
*/
|
|
722 |
|
|
723 |
function enano_version($long = false, $no_nightly = false)
|
|
724 |
{
|
|
725 |
$r = getConfig('enano_version');
|
|
726 |
$rc = ( $long ) ? ' release candidate ' : 'RC';
|
|
727 |
$b = ( $long ) ? ' beta ' : 'b';
|
|
728 |
$a = ( $long ) ? ' alpha ' : 'a';
|
|
729 |
if($v = getConfig('enano_rc_version')) $r .= $rc.$v;
|
|
730 |
if($v = getConfig('enano_beta_version')) $r .= $b.$v;
|
|
731 |
if($v = getConfig('enano_alpha_version')) $r .= $a.$v;
|
|
732 |
if ( defined('ENANO_NIGHTLY') && !$no_nightly )
|
|
733 |
{
|
|
734 |
$nightlytag = ENANO_NIGHTLY_MONTH . '-' . ENANO_NIGHTLY_DAY . '-' . ENANO_NIGHTLY_YEAR;
|
|
735 |
$nightlylong = ' nightly; build date: ' . ENANO_NIGHTLY_MONTH . '-' . ENANO_NIGHTLY_DAY . '-' . ENANO_NIGHTLY_YEAR;
|
|
736 |
$r = ( $long ) ? $r . $nightlylong : $r . '-nightly-' . $nightlytag;
|
|
737 |
}
|
|
738 |
return $r;
|
|
739 |
}
|
|
740 |
|
|
741 |
function _dualurlenc($t) {
|
|
742 |
return rawurlencode(rawurlencode($t));
|
|
743 |
}
|
|
744 |
|
|
745 |
function _die($t) {
|
|
746 |
$_ob = 'document.getElementById("ajaxEditContainer").innerHTML = unescape(\'' . rawurlencode('' . $t . '') . '\')';
|
|
747 |
die($_ob);
|
|
748 |
}
|
|
749 |
|
|
750 |
function jsdie($text) {
|
|
751 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
752 |
$text = rawurlencode($text . "\n\nSQL Backtrace:\n" . $db->sql_backtrace());
|
|
753 |
echo 'document.getElementById("ajaxEditContainer").innerHTML = unescape(\''.$text.'\');';
|
|
754 |
}
|
|
755 |
|
|
756 |
// HTML sanitizing function - written by Kallahar
|
|
757 |
// Original function at: http://quickwired.com/kallahar/smallprojects/php_xss_filter_function.php
|
|
758 |
|
|
759 |
// UNUSED - todo: remove this in gold or put it to use
|
|
760 |
|
|
761 |
function RemoveXSS($val) {
|
|
762 |
// remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
|
|
763 |
// this prevents some character re-spacing such as <java\0script>
|
|
764 |
// note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
|
|
765 |
$val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);
|
|
766 |
|
|
767 |
// straight replacements, the user should never need these since they're normal characters
|
|
768 |
// this prevents like <IMG SRC=@avascript:alert('XSS')>
|
|
769 |
$search = 'abcdefghijklmnopqrstuvwxyz';
|
|
770 |
$search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
771 |
$search .= '1234567890!@#$%^&*()';
|
|
772 |
$search .= '~`";:?+/={}[]-_|\'\\';
|
|
773 |
for ($i = 0; $i < strlen($search); $i++) {
|
|
774 |
// ;? matches the ;, which is optional
|
|
775 |
// 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
|
|
776 |
|
|
777 |
// @ @ search for the hex values
|
|
778 |
$val = preg_replace('/(&#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
|
|
779 |
// @ @ 0{0,7} matches '0' zero to seven times
|
|
780 |
$val = preg_replace('/(�{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
|
|
781 |
}
|
|
782 |
|
|
783 |
// now the only remaining whitespace attacks are \t, \n, and \r
|
|
784 |
$ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
|
|
785 |
$ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
|
|
786 |
$ra = array_merge($ra1, $ra2);
|
|
787 |
|
|
788 |
$found = true; // keep replacing as long as the previous round replaced something
|
|
789 |
while ($found == true) {
|
|
790 |
$val_before = $val;
|
|
791 |
for ($i = 0; $i < sizeof($ra); $i++) {
|
|
792 |
$pattern = '/';
|
|
793 |
for ($j = 0; $j < strlen($ra[$i]); $j++) {
|
|
794 |
if ($j > 0) {
|
|
795 |
$pattern .= '(';
|
|
796 |
$pattern .= '(&#[x|X]0{0,8}([9][a][b]);?)?';
|
|
797 |
$pattern .= '|(�{0,8}([9][10][13]);?)?';
|
|
798 |
$pattern .= ')?';
|
|
799 |
}
|
|
800 |
$pattern .= $ra[$i][$j];
|
|
801 |
}
|
|
802 |
$pattern .= '/i';
|
|
803 |
$replacement = substr($ra[$i], 0, 2).'<b></b>'.substr($ra[$i], 2); // add in <> to nerf the tag
|
|
804 |
$val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
|
|
805 |
if ($val_before == $val) {
|
|
806 |
// no replacements were made, so exit the loop
|
|
807 |
$found = false;
|
|
808 |
}
|
|
809 |
}
|
|
810 |
}
|
|
811 |
return $val;
|
|
812 |
}
|
|
813 |
|
|
814 |
/**
|
|
815 |
* Capitalizes the first letter of a string
|
|
816 |
* @param $text string the text to be transformed
|
|
817 |
* @return string
|
|
818 |
*/
|
|
819 |
|
|
820 |
function capitalize_first_letter($text)
|
|
821 |
{
|
|
822 |
return strtoupper(substr($text, 0, 1)) . substr($text, 1);
|
|
823 |
}
|
|
824 |
|
|
825 |
/**
|
|
826 |
* Checks if a value in a bitfield is on or off
|
|
827 |
* @param $bitfield int the bit-field value
|
|
828 |
* @param $value int the value to switch off
|
|
829 |
* @return bool
|
|
830 |
*/
|
|
831 |
|
|
832 |
function is_bit($bitfield, $value)
|
|
833 |
{
|
|
834 |
return ( $bitfield & $value ) ? true : false;
|
|
835 |
}
|
|
836 |
|
|
837 |
/**
|
|
838 |
* Trims spaces/newlines from the beginning and end of a string
|
|
839 |
* @param $text the text to process
|
|
840 |
* @return string
|
|
841 |
*/
|
|
842 |
|
|
843 |
function trim_spaces($text)
|
|
844 |
{
|
|
845 |
$d = true;
|
|
846 |
while($d)
|
|
847 |
{
|
|
848 |
$c = substr($text, 0, 1);
|
|
849 |
$a = substr($text, strlen($text)-1, strlen($text));
|
|
850 |
if($c == "\n" || $c == "\r" || $c == "\t" || $c == ' ') $text = substr($text, 1, strlen($text));
|
|
851 |
elseif($a == "\n" || $a == "\r" || $a == "\t" || $a == ' ') $text = substr($text, 0, strlen($text)-1);
|
|
852 |
else $d = false;
|
|
853 |
}
|
|
854 |
return $text;
|
|
855 |
}
|
|
856 |
|
|
857 |
/**
|
|
858 |
* Enano-ese equivalent of str_split() which is only found in PHP5
|
|
859 |
* @param $text string the text to split
|
|
860 |
* @param $inc int size of each block
|
|
861 |
* @return array
|
|
862 |
*/
|
|
863 |
|
|
864 |
function enano_str_split($text, $inc = 1)
|
|
865 |
{
|
|
866 |
if($inc < 1) return false;
|
|
867 |
if($inc >= strlen($text)) return Array($text);
|
|
868 |
$len = ceil(strlen($text) / $inc);
|
|
869 |
$ret = Array();
|
|
870 |
for($i=0;$i<strlen($text);$i=$i+$inc)
|
|
871 |
{
|
|
872 |
$ret[] = substr($text, $i, $inc);
|
|
873 |
}
|
|
874 |
return $ret;
|
|
875 |
}
|
|
876 |
|
|
877 |
/**
|
|
878 |
* Converts a hexadecimal number to a binary string.
|
|
879 |
* @param text string hexadecimal number
|
|
880 |
* @return string
|
|
881 |
*/
|
|
882 |
function hex2bin($text)
|
|
883 |
{
|
|
884 |
$arr = enano_str_split($text, 2);
|
|
885 |
$ret = '';
|
|
886 |
for ($i=0; $i<sizeof($arr); $i++)
|
|
887 |
{
|
|
888 |
$ret .= chr(hexdec($arr[$i]));
|
|
889 |
}
|
|
890 |
return $ret;
|
|
891 |
}
|
|
892 |
|
|
893 |
/**
|
|
894 |
* Generates and/or prints a human-readable backtrace
|
|
895 |
* @param bool $return - if true, this function returns a string, otherwise returns null
|
|
896 |
* @return mixed
|
|
897 |
*/
|
|
898 |
|
|
899 |
function enano_debug_print_backtrace($return = false)
|
|
900 |
{
|
|
901 |
ob_start();
|
|
902 |
echo '<pre>';
|
|
903 |
debug_print_backtrace();
|
|
904 |
echo '</pre>';
|
|
905 |
$c = ob_get_contents();
|
|
906 |
ob_end_clean();
|
|
907 |
if($return) return $c;
|
|
908 |
else echo $c;
|
|
909 |
return null;
|
|
910 |
}
|
|
911 |
|
|
912 |
/**
|
|
913 |
* Like rawurlencode(), but encodes all characters
|
|
914 |
* @param string $text the text to encode
|
|
915 |
* @param optional string $prefix text before each hex character
|
|
916 |
* @param optional string $suffix text after each hex character
|
|
917 |
* @return string
|
|
918 |
*/
|
|
919 |
|
|
920 |
function hexencode($text, $prefix = '%', $suffix = '')
|
|
921 |
{
|
|
922 |
$arr = enano_str_split($text);
|
|
923 |
$r = '';
|
|
924 |
foreach($arr as $a)
|
|
925 |
{
|
|
926 |
$nibble = (string)dechex(ord($a));
|
|
927 |
if(strlen($nibble) == 1) $nibble = '0' . $nibble;
|
|
928 |
$r .= $prefix . $nibble . $suffix;
|
|
929 |
}
|
|
930 |
return $r;
|
|
931 |
}
|
|
932 |
|
|
933 |
/**
|
|
934 |
* Enano-ese equivalent of get_magic_quotes_gpc()
|
|
935 |
* @return bool
|
|
936 |
*/
|
|
937 |
|
|
938 |
function enano_get_magic_quotes_gpc()
|
|
939 |
{
|
|
940 |
if(function_exists('get_magic_quotes_gpc'))
|
|
941 |
{
|
|
942 |
return ( get_magic_quotes_gpc() == 1 );
|
|
943 |
}
|
|
944 |
else
|
|
945 |
{
|
|
946 |
return ( strtolower(@ini_get('magic_quotes_gpc')) == '1' );
|
|
947 |
}
|
|
948 |
}
|
|
949 |
|
|
950 |
/**
|
|
951 |
* Recursive stripslashes()
|
|
952 |
* @param array
|
|
953 |
* @return array
|
|
954 |
*/
|
|
955 |
|
|
956 |
function stripslashes_recurse($arr)
|
|
957 |
{
|
|
958 |
foreach($arr as $k => $xxxx)
|
|
959 |
{
|
|
960 |
$val =& $arr[$k];
|
|
961 |
if(is_string($val))
|
|
962 |
$val = stripslashes($val);
|
|
963 |
elseif(is_array($val))
|
|
964 |
$val = stripslashes_recurse($val);
|
|
965 |
}
|
|
966 |
return $arr;
|
|
967 |
}
|
|
968 |
|
|
969 |
/**
|
|
970 |
* If magic_quotes_gpc is on, calls stripslashes() on everything in $_GET/$_POST/$_COOKIE
|
|
971 |
* @ignore - this doesn't work
|
|
972 |
* @todo port version from the PHP manual
|
|
973 |
* @return void
|
|
974 |
*/
|
|
975 |
function strip_magic_quotes_gpc()
|
|
976 |
{
|
|
977 |
if(enano_get_magic_quotes_gpc())
|
|
978 |
{
|
|
979 |
$_POST = stripslashes_recurse($_POST);
|
|
980 |
$_GET = stripslashes_recurse($_GET);
|
|
981 |
$_COOKIE = stripslashes_recurse($_COOKIE);
|
|
982 |
}
|
|
983 |
}
|
|
984 |
|
|
985 |
/**
|
|
986 |
* A very basic single-character compression algorithm for binary strings/bitfields
|
|
987 |
* @param string $bits the text to compress
|
|
988 |
* @return string
|
|
989 |
*/
|
|
990 |
|
|
991 |
function compress_bitfield($bits)
|
|
992 |
{
|
|
993 |
$crc32 = crc32($bits);
|
|
994 |
$bits .= '0';
|
|
995 |
$start_pos = 0;
|
|
996 |
$current = substr($bits, 1, 1);
|
|
997 |
$last = substr($bits, 0, 1);
|
|
998 |
$chunk_size = 1;
|
|
999 |
$len = strlen($bits);
|
|
1000 |
$crc = $len;
|
|
1001 |
$crcval = 0;
|
|
1002 |
for ( $i = 1; $i < $len; $i++ )
|
|
1003 |
{
|
|
1004 |
$current = substr($bits, $i, 1);
|
|
1005 |
$last = substr($bits, $i - 1, 1);
|
|
1006 |
$next = substr($bits, $i + 1, 1);
|
|
1007 |
// Are we on the last character?
|
|
1008 |
if($current == $last && $i+1 < $len)
|
|
1009 |
$chunk_size++;
|
|
1010 |
else
|
|
1011 |
{
|
|
1012 |
if($i+1 == $len && $current == $next)
|
|
1013 |
{
|
|
1014 |
// This character completes a chunk
|
|
1015 |
$chunk_size++;
|
|
1016 |
$i++;
|
|
1017 |
$chunk = substr($bits, $start_pos, $chunk_size);
|
|
1018 |
$chunklen = strlen($chunk);
|
|
1019 |
$newchunk = $last . '[' . $chunklen . ']';
|
|
1020 |
$newlen = strlen($newchunk);
|
|
1021 |
$bits = substr($bits, 0, $start_pos) . $newchunk . substr($bits, $i, $len);
|
|
1022 |
$chunk_size = 1;
|
|
1023 |
$i = $start_pos + $newlen;
|
|
1024 |
$start_pos = $i;
|
|
1025 |
$len = strlen($bits);
|
|
1026 |
$crcval = $crcval + $chunklen;
|
|
1027 |
}
|
|
1028 |
else
|
|
1029 |
{
|
|
1030 |
// Last character completed a chunk
|
|
1031 |
$chunk = substr($bits, $start_pos, $chunk_size);
|
|
1032 |
$chunklen = strlen($chunk);
|
|
1033 |
$newchunk = $last . '[' . $chunklen . '],';
|
|
1034 |
$newlen = strlen($newchunk);
|
|
1035 |
$bits = substr($bits, 0, $start_pos) . $newchunk . substr($bits, $i, $len);
|
|
1036 |
$chunk_size = 1;
|
|
1037 |
$i = $start_pos + $newlen;
|
|
1038 |
$start_pos = $i;
|
|
1039 |
$len = strlen($bits);
|
|
1040 |
$crcval = $crcval + $chunklen;
|
|
1041 |
}
|
|
1042 |
}
|
|
1043 |
}
|
|
1044 |
if($crc != $crcval)
|
|
1045 |
{
|
|
1046 |
echo __FUNCTION__.'(): ERROR: length check failed, this is a bug in the algorithm<br />Debug info: aiming for a CRC val of '.$crc.', got '.$crcval;
|
|
1047 |
return false;
|
|
1048 |
}
|
|
1049 |
$compressed = 'cbf:len='.$crc.';crc='.dechex($crc32).';data='.$bits.'|end';
|
|
1050 |
return $compressed;
|
|
1051 |
}
|
|
1052 |
|
|
1053 |
/**
|
|
1054 |
* Uncompresses a bitfield compressed with compress_bitfield()
|
|
1055 |
* @param string $bits the compressed bitfield
|
|
1056 |
* @return string the uncompressed, original (we hope) bitfield OR bool false on error
|
|
1057 |
*/
|
|
1058 |
|
|
1059 |
function uncompress_bitfield($bits)
|
|
1060 |
{
|
|
1061 |
if(substr($bits, 0, 4) != 'cbf:')
|
|
1062 |
{
|
|
1063 |
echo __FUNCTION__.'(): ERROR: Invalid stream';
|
|
1064 |
return false;
|
|
1065 |
}
|
|
1066 |
$len = intval(substr($bits, strpos($bits, 'len=')+4, strpos($bits, ';')-strpos($bits, 'len=')-4));
|
|
1067 |
$crc = substr($bits, strpos($bits, 'crc=')+4, 8);
|
|
1068 |
$data = substr($bits, strpos($bits, 'data=')+5, strpos($bits, '|end')-strpos($bits, 'data=')-5);
|
|
1069 |
$data = explode(',', $data);
|
|
1070 |
foreach($data as $a => $b)
|
|
1071 |
{
|
|
1072 |
$d =& $data[$a];
|
|
1073 |
$char = substr($d, 0, 1);
|
|
1074 |
$dlen = intval(substr($d, 2, strlen($d)-1));
|
|
1075 |
$s = '';
|
|
1076 |
for($i=0;$i<$dlen;$i++,$s.=$char);
|
|
1077 |
$d = $s;
|
|
1078 |
unset($s, $dlen, $char);
|
|
1079 |
}
|
|
1080 |
$decompressed = implode('', $data);
|
|
1081 |
$decompressed = substr($decompressed, 0, -1);
|
|
1082 |
$dcrc = (string)dechex(crc32($decompressed));
|
|
1083 |
if($dcrc != $crc)
|
|
1084 |
{
|
|
1085 |
echo __FUNCTION__.'(): ERROR: CRC check failed<br />debug info:<br />original crc: '.$crc.'<br />decomp\'ed crc: '.$dcrc.'<br />';
|
|
1086 |
return false;
|
|
1087 |
}
|
|
1088 |
return $decompressed;
|
|
1089 |
}
|
|
1090 |
|
|
1091 |
/**
|
|
1092 |
* Exports a MySQL table into a SQL string.
|
|
1093 |
* @param string $table The name of the table to export
|
|
1094 |
* @param bool $structure If true, include a CREATE TABLE command
|
|
1095 |
* @param bool $data If true, include the contents of the table
|
|
1096 |
* @param bool $compact If true, omits newlines between parts of SQL statements, use in Enano database exporter
|
|
1097 |
* @return string
|
|
1098 |
*/
|
|
1099 |
|
|
1100 |
function export_table($table, $structure = true, $data = true, $compact = false)
|
|
1101 |
{
|
|
1102 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
1103 |
$struct_keys = '';
|
|
1104 |
$divider = (!$compact) ? "\n" : "\n";
|
|
1105 |
$spacer1 = (!$compact) ? "\n" : " ";
|
|
1106 |
$spacer2 = (!$compact) ? " " : " ";
|
|
1107 |
$rowspacer = (!$compact) ? "\n " : " ";
|
|
1108 |
$index_list = Array();
|
|
1109 |
$cols = $db->sql_query('SHOW COLUMNS IN '.$table.';');
|
|
1110 |
if(!$cols)
|
|
1111 |
{
|
|
1112 |
echo 'export_table(): Error getting column list: '.$db->get_error_text().'<br />';
|
|
1113 |
return false;
|
|
1114 |
}
|
|
1115 |
$col = Array();
|
|
1116 |
$sqlcol = Array();
|
|
1117 |
$collist = Array();
|
|
1118 |
$pri_keys = Array();
|
|
1119 |
// Using fetchrow_num() here to compensate for MySQL l10n
|
|
1120 |
while( $row = $db->fetchrow_num() )
|
|
1121 |
{
|
|
1122 |
$field =& $row[0];
|
|
1123 |
$type =& $row[1];
|
|
1124 |
$null =& $row[2];
|
|
1125 |
$key =& $row[3];
|
|
1126 |
$def =& $row[4];
|
|
1127 |
$extra =& $row[5];
|
|
1128 |
$col[] = Array(
|
|
1129 |
'name'=>$field,
|
|
1130 |
'type'=>$type,
|
|
1131 |
'null'=>$null,
|
|
1132 |
'key'=>$key,
|
|
1133 |
'default'=>$def,
|
|
1134 |
'extra'=>$extra,
|
|
1135 |
);
|
|
1136 |
$collist[] = $field;
|
|
1137 |
}
|
|
1138 |
|
|
1139 |
if ( $structure )
|
|
1140 |
{
|
|
1141 |
$db->sql_query('SET SQL_QUOTE_SHOW_CREATE = 0;');
|
|
1142 |
$struct = $db->sql_query('SHOW CREATE TABLE '.$table.';');
|
|
1143 |
if ( !$struct )
|
|
1144 |
$db->_die();
|
|
1145 |
$row = $db->fetchrow_num();
|
|
1146 |
$db->free_result();
|
|
1147 |
$struct = $row[1];
|
|
1148 |
$struct = preg_replace("/\n\) ENGINE=(.+)$/", "\n);", $struct);
|
|
1149 |
unset($row);
|
|
1150 |
if ( $compact )
|
|
1151 |
{
|
|
1152 |
$struct_arr = explode("\n", $struct);
|
|
1153 |
foreach ( $struct_arr as $i => $leg )
|
|
1154 |
{
|
|
1155 |
if ( $i == 0 )
|
|
1156 |
continue;
|
|
1157 |
$test = trim($leg);
|
|
1158 |
if ( empty($test) )
|
|
1159 |
{
|
|
1160 |
unset($struct_arr[$i]);
|
|
1161 |
continue;
|
|
1162 |
}
|
|
1163 |
$struct_arr[$i] = preg_replace('/^([\s]*)/', ' ', $leg);
|
|
1164 |
}
|
|
1165 |
$struct = implode("", $struct_arr);
|
|
1166 |
}
|
|
1167 |
}
|
|
1168 |
|
|
1169 |
// Structuring complete
|
|
1170 |
if($data)
|
|
1171 |
{
|
|
1172 |
$datq = $db->sql_query('SELECT * FROM '.$table.';');
|
|
1173 |
if(!$datq)
|
|
1174 |
{
|
|
1175 |
echo 'export_table(): Error getting column list: '.$db->get_error_text().'<br />';
|
|
1176 |
return false;
|
|
1177 |
}
|
|
1178 |
if($db->numrows() < 1)
|
|
1179 |
{
|
|
1180 |
if($structure) return $struct;
|
|
1181 |
else return '';
|
|
1182 |
}
|
|
1183 |
$rowdata = Array();
|
|
1184 |
$dataqs = Array();
|
|
1185 |
$insert_strings = Array();
|
|
1186 |
$z = false;
|
|
1187 |
while($row = $db->fetchrow_num())
|
|
1188 |
{
|
|
1189 |
$z = false;
|
|
1190 |
foreach($row as $i => $cell)
|
|
1191 |
{
|
|
1192 |
$str = mysql_encode_column($cell, $col[$i]['type']);
|
|
1193 |
$rowdata[] = $str;
|
|
1194 |
}
|
|
1195 |
$dataqs2 = implode(",$rowspacer", $dataqs) . ",$rowspacer" . '( ' . implode(', ', $rowdata) . ' )';
|
|
1196 |
$ins = 'INSERT INTO '.$table.'( '.implode(',', $collist).' ) VALUES' . $dataqs2 . ";";
|
|
1197 |
if ( strlen( $ins ) > MYSQL_MAX_PACKET_SIZE )
|
|
1198 |
{
|
|
1199 |
// We've exceeded the maximum allowed packet size for MySQL - separate this into a different query
|
|
1200 |
$insert_strings[] = 'INSERT INTO '.$table.'( '.implode(',', $collist).' ) VALUES' . implode(",$rowspacer", $dataqs) . ";";;
|
|
1201 |
$dataqs = Array('( ' . implode(', ', $rowdata) . ' )');
|
|
1202 |
$z = true;
|
|
1203 |
}
|
|
1204 |
else
|
|
1205 |
{
|
|
1206 |
$dataqs[] = '( ' . implode(', ', $rowdata) . ' )';
|
|
1207 |
}
|
|
1208 |
$rowdata = Array();
|
|
1209 |
}
|
|
1210 |
if ( !$z )
|
|
1211 |
{
|
|
1212 |
$insert_strings[] = 'INSERT INTO '.$table.'( '.implode(',', $collist).' ) VALUES' . implode(",$rowspacer", $dataqs) . ";";;
|
|
1213 |
$dataqs = Array();
|
|
1214 |
}
|
|
1215 |
$datstring = implode($divider, $insert_strings);
|
|
1216 |
}
|
|
1217 |
if($structure && !$data) return $struct;
|
|
1218 |
elseif(!$structure && $data) return $datstring;
|
|
1219 |
elseif($structure && $data) return $struct . $divider . $datstring;
|
|
1220 |
elseif(!$structure && !$data) return '';
|
|
1221 |
}
|
|
1222 |
|
|
1223 |
/**
|
|
1224 |
* Encodes a string value for use in an INSERT statement for given column type $type.
|
|
1225 |
* @access private
|
|
1226 |
*/
|
|
1227 |
|
|
1228 |
function mysql_encode_column($input, $type)
|
|
1229 |
{
|
|
1230 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
1231 |
// Decide whether to quote the string or not
|
|
1232 |
if(substr($type, 0, 7) == 'varchar' || $type == 'datetime' || $type == 'text' || $type == 'tinytext' || $type == 'smalltext' || $type == 'longtext' || substr($type, 0, 4) == 'char')
|
|
1233 |
{
|
|
1234 |
$str = "'" . $db->escape($input) . "'";
|
|
1235 |
}
|
|
1236 |
elseif(in_array($type, Array('blob', 'longblob', 'mediumblob', 'smallblob')) || substr($type, 0, 6) == 'binary' || substr($type, 0, 9) == 'varbinary')
|
|
1237 |
{
|
|
1238 |
$str = '0x' . hexencode($input, '', '');
|
|
1239 |
}
|
|
1240 |
elseif(is_null($input))
|
|
1241 |
{
|
|
1242 |
$str = 'NULL';
|
|
1243 |
}
|
|
1244 |
else
|
|
1245 |
{
|
|
1246 |
$str = (string)$input;
|
|
1247 |
}
|
|
1248 |
return $str;
|
|
1249 |
}
|
|
1250 |
|
|
1251 |
/**
|
|
1252 |
* Creates an associative array defining which file extensions are allowed and which ones aren't
|
|
1253 |
* @return array keyname will be a file extension, value will be true or false
|
|
1254 |
*/
|
|
1255 |
|
|
1256 |
function fetch_allowed_extensions()
|
|
1257 |
{
|
|
1258 |
global $mime_types;
|
|
1259 |
$bits = getConfig('allowed_mime_types');
|
|
1260 |
if(!$bits) return Array(false);
|
|
1261 |
$bits = uncompress_bitfield($bits);
|
|
1262 |
if(!$bits) return Array(false);
|
|
1263 |
$bits = enano_str_split($bits, 1);
|
|
1264 |
$ret = Array();
|
|
1265 |
$mt = array_keys($mime_types);
|
|
1266 |
foreach($bits as $i => $b)
|
|
1267 |
{
|
|
1268 |
$ret[$mt[$i]] = ( $b == '1' ) ? true : false;
|
|
1269 |
}
|
|
1270 |
return $ret;
|
|
1271 |
}
|
|
1272 |
|
|
1273 |
/**
|
|
1274 |
* Generates a random key suitable for encryption
|
|
1275 |
* @param int $len the length of the key
|
|
1276 |
* @return string a BINARY key
|
|
1277 |
*/
|
|
1278 |
|
|
1279 |
function randkey($len = 32)
|
|
1280 |
{
|
|
1281 |
$key = '';
|
|
1282 |
for($i=0;$i<$len;$i++)
|
|
1283 |
{
|
|
1284 |
$key .= chr(mt_rand(0, 255));
|
|
1285 |
}
|
|
1286 |
return $key;
|
|
1287 |
}
|
|
1288 |
|
|
1289 |
/**
|
|
1290 |
* Decodes a hex string.
|
|
1291 |
* @param string $hex The hex code to decode
|
|
1292 |
* @return string
|
|
1293 |
*/
|
|
1294 |
|
|
1295 |
function hexdecode($hex)
|
|
1296 |
{
|
|
1297 |
$hex = enano_str_split($hex, 2);
|
|
1298 |
$bin_key = '';
|
|
1299 |
foreach($hex as $nibble)
|
|
1300 |
{
|
|
1301 |
$byte = chr(hexdec($nibble));
|
|
1302 |
$bin_key .= $byte;
|
|
1303 |
}
|
|
1304 |
return $bin_key;
|
|
1305 |
}
|
|
1306 |
|
|
1307 |
/**
|
|
1308 |
* Enano's own (almost) bulletproof HTML sanitizer.
|
|
1309 |
* @param string $html The input HTML
|
|
1310 |
* @return string cleaned HTML
|
|
1311 |
*/
|
|
1312 |
|
|
1313 |
function sanitize_html($html, $filter_php = true)
|
|
1314 |
{
|
|
1315 |
|
|
1316 |
$html = preg_replace('#<([a-z]+)([\s]+)([^>]+?)'.htmlalternatives('javascript:').'(.+?)>(.*?)</\\1>#is', '<\\1\\2\\3javascript:\\59>\\60</\\1>', $html);
|
|
1317 |
$html = preg_replace('#<([a-z]+)([\s]+)([^>]+?)'.htmlalternatives('javascript:').'(.+?)>#is', '<\\1\\2\\3javascript:\\59>', $html);
|
|
1318 |
|
|
1319 |
if($filter_php)
|
|
1320 |
$html = str_replace(
|
|
1321 |
Array('<?php', '<?', '<%', '?>', '%>'),
|
|
1322 |
Array('<?php', '<?', '<%', '?>', '%>'),
|
|
1323 |
$html);
|
|
1324 |
|
|
1325 |
$tag_whitelist = array_keys ( setupAttributeWhitelist() );
|
|
1326 |
if ( !$filter_php )
|
|
1327 |
$tag_whitelist[] = '?php';
|
|
1328 |
$len = strlen($html);
|
|
1329 |
$in_quote = false;
|
|
1330 |
$quote_char = '';
|
|
1331 |
$tag_start = 0;
|
|
1332 |
$tag_name = '';
|
|
1333 |
$in_tag = false;
|
|
1334 |
$trk_name = false;
|
|
1335 |
for ( $i = 0; $i < $len; $i++ )
|
|
1336 |
{
|
|
1337 |
$chr = $html{$i};
|
|
1338 |
$prev = ( $i == 0 ) ? '' : $html{ $i - 1 };
|
|
1339 |
$next = ( ( $i + 1 ) == $len ) ? '' : $html { $i + 1 };
|
|
1340 |
if ( $in_quote && $in_tag )
|
|
1341 |
{
|
|
1342 |
if ( $quote_char == $chr && $prev != '\\' )
|
|
1343 |
$in_quote = false;
|
|
1344 |
}
|
|
1345 |
elseif ( ( $chr == '"' || $chr == "'" ) && $prev != '\\' && $in_tag )
|
|
1346 |
{
|
|
1347 |
$in_quote = true;
|
|
1348 |
$quote_char = $chr;
|
|
1349 |
}
|
|
1350 |
if ( $chr == '<' && !$in_tag && $next != '/' )
|
|
1351 |
{
|
|
1352 |
// start of a tag
|
|
1353 |
$tag_start = $i;
|
|
1354 |
$in_tag = true;
|
|
1355 |
$trk_name = true;
|
|
1356 |
}
|
|
1357 |
elseif ( !$in_quote && $in_tag && $chr == '>' )
|
|
1358 |
{
|
|
1359 |
$full_tag = substr($html, $tag_start, ( $i - $tag_start ) + 1 );
|
|
1360 |
$l = strlen($tag_name) + 2;
|
|
1361 |
$attribs_only = trim( substr($full_tag, $l, ( strlen($full_tag) - $l - 1 ) ) );
|
|
1362 |
|
|
1363 |
// Debugging message
|
|
1364 |
// echo htmlspecialchars($full_tag) . '<br />';
|
|
1365 |
|
|
1366 |
if ( !in_array($tag_name, $tag_whitelist) )
|
|
1367 |
{
|
|
1368 |
// Illegal tag
|
|
1369 |
//echo $tag_name . ' ';
|
|
1370 |
|
|
1371 |
$s = ( empty($attribs_only) ) ? '' : ' ';
|
|
1372 |
|
|
1373 |
$sanitized = '<' . $tag_name . $s . $attribs_only . '>';
|
|
1374 |
|
|
1375 |
$html = substr($html, 0, $tag_start) . $sanitized . substr($html, $i + 1);
|
|
1376 |
$html = str_replace('</' . $tag_name . '>', '</' . $tag_name . '>', $html);
|
|
1377 |
$new_i = $tag_start + strlen($sanitized);
|
|
1378 |
|
|
1379 |
$len = strlen($html);
|
|
1380 |
$i = $new_i;
|
|
1381 |
|
|
1382 |
$in_tag = false;
|
|
1383 |
$tag_name = '';
|
|
1384 |
continue;
|
|
1385 |
}
|
|
1386 |
else
|
|
1387 |
{
|
|
1388 |
if ( $tag_name == '?php' && !$filter_php )
|
|
1389 |
continue;
|
|
1390 |
$f = fixTagAttributes( $attribs_only, $tag_name );
|
|
1391 |
$s = ( empty($f) ) ? '' : ' ';
|
|
1392 |
|
|
1393 |
$sanitized = '<' . $tag_name . $f . '>';
|
|
1394 |
$new_i = $tag_start + strlen($sanitized);
|
|
1395 |
|
|
1396 |
$html = substr($html, 0, $tag_start) . $sanitized . substr($html, $i + 1);
|
|
1397 |
$len = strlen($html);
|
|
1398 |
$i = $new_i;
|
|
1399 |
|
|
1400 |
$in_tag = false;
|
|
1401 |
$tag_name = '';
|
|
1402 |
continue;
|
|
1403 |
}
|
|
1404 |
}
|
|
1405 |
elseif ( $in_tag && $trk_name )
|
|
1406 |
{
|
|
1407 |
$is_alphabetical = ( strtolower($chr) != strtoupper($chr) || in_array($chr, array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) || $chr == '?' );
|
|
1408 |
if ( $is_alphabetical )
|
|
1409 |
$tag_name .= $chr;
|
|
1410 |
else
|
|
1411 |
{
|
|
1412 |
$trk_name = false;
|
|
1413 |
}
|
|
1414 |
}
|
|
1415 |
|
|
1416 |
}
|
|
1417 |
|
|
1418 |
return $html;
|
|
1419 |
|
|
1420 |
}
|
|
1421 |
|
|
1422 |
function htmlalternatives($string)
|
|
1423 |
{
|
|
1424 |
$ret = '';
|
|
1425 |
for ( $i = 0; $i < strlen($string); $i++ )
|
|
1426 |
{
|
|
1427 |
$chr = $string{$i};
|
|
1428 |
$ch1 = ord($chr);
|
|
1429 |
$ch2 = dechex($ch1);
|
|
1430 |
$byte = '(&\\#([0]*){0,7}' . $ch1 . ';|\\\\([0]*){0,7}' . $ch1 . ';|\\\\([0]*){0,7}' . $ch2 . ';|&\\#x([0]*){0,7}' . $ch2 . ';|%([0]*){0,7}' . $ch2 . '|' . preg_quote($chr) . ')';
|
|
1431 |
$ret .= $byte;
|
|
1432 |
$ret .= '([\s]){0,2}';
|
|
1433 |
}
|
|
1434 |
return $ret;
|
|
1435 |
}
|
|
1436 |
|
|
1437 |
/**
|
|
1438 |
* Paginates (breaks into multiple pages) a MySQL result resource, which is treated as unbuffered.
|
|
1439 |
* @param resource The MySQL result resource. This should preferably be an unbuffered query.
|
|
1440 |
* @param string A template, with variables being named after the column name
|
|
1441 |
* @param int The number of total results. This should be determined by a second query.
|
|
1442 |
* @param string sprintf-style formatting string for URLs for result pages. First parameter will be start offset.
|
|
1443 |
* @param int Optional. Start offset in individual results. Defaults to 0.
|
|
1444 |
* @param int Optional. The number of results per page. Defualts to 10.
|
|
1445 |
* @param int Optional. An associative array of functions to call, with key names being column names, and values being function names. Values can also be an array with key 0 being either an object or a string(class name) and key 1 being a [static] method.
|
|
1446 |
* @param string Optional. The text to be sent before the result list, only if there are any results. Possibly the start of a table.
|
|
1447 |
* @param string Optional. The text to be sent after the result list, only if there are any results. Possibly the end of a table.
|
|
1448 |
* @return string
|
|
1449 |
*/
|
|
1450 |
|
|
1451 |
function paginate($q, $tpl_text, $num_results, $result_url, $start = 0, $perpage = 10, $callers = Array(), $header = '', $footer = '')
|
|
1452 |
{
|
|
1453 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
1454 |
$parser = $template->makeParserText($tpl_text);
|
|
1455 |
$num_pages = ceil ( $num_results / $perpage );
|
|
1456 |
$out = '';
|
|
1457 |
$i = 0;
|
|
1458 |
$this_page = ceil ( $start / $perpage );
|
|
1459 |
|
|
1460 |
// Build paginator
|
|
1461 |
$begin = '<div class="tblholder" style="display: table; margin: 10px 0 0 auto;">
|
|
1462 |
<table border="0" cellspacing="1" cellpadding="4">
|
|
1463 |
<tr><th>Page:</th>';
|
|
1464 |
$block = '<td class="row1" style="text-align: center;">{LINK}</td>';
|
|
1465 |
$end = '</tr></table></div>';
|
|
1466 |
$blk = $template->makeParserText($block);
|
|
1467 |
$inner = '';
|
|
1468 |
$cls = 'row2';
|
|
1469 |
if ( $num_pages < 5 )
|
|
1470 |
{
|
|
1471 |
for ( $i = 0; $i < $num_pages; $i++ )
|
|
1472 |
{
|
|
1473 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1474 |
$offset = strval($i * $perpage);
|
|
1475 |
$url = sprintf($result_url, $offset);
|
|
1476 |
$j = $i + 1;
|
|
1477 |
$link = ( $offset == strval($start) ) ? "<b>$j</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>$j</a>";
|
|
1478 |
$blk->assign_vars(array(
|
|
1479 |
'CLASS'=>$cls,
|
|
1480 |
'LINK'=>$link
|
|
1481 |
));
|
|
1482 |
$inner .= $blk->run();
|
|
1483 |
}
|
|
1484 |
}
|
|
1485 |
else
|
|
1486 |
{
|
|
1487 |
if ( $this_page + 5 > $num_pages )
|
|
1488 |
{
|
|
1489 |
$list = Array();
|
|
1490 |
$tp = $this_page;
|
|
1491 |
if ( $this_page + 0 == $num_pages ) $tp = $tp - 3;
|
|
1492 |
if ( $this_page + 1 == $num_pages ) $tp = $tp - 2;
|
|
1493 |
if ( $this_page + 2 == $num_pages ) $tp = $tp - 1;
|
|
1494 |
for ( $i = $tp - 1; $i <= $tp + 1; $i++ )
|
|
1495 |
{
|
|
1496 |
$list[] = $i;
|
|
1497 |
}
|
|
1498 |
}
|
|
1499 |
else
|
|
1500 |
{
|
|
1501 |
$list = Array();
|
|
1502 |
$current = $this_page;
|
|
1503 |
$lower = ( $current < 3 ) ? 1 : $current - 1;
|
|
1504 |
for ( $i = 0; $i < 3; $i++ )
|
|
1505 |
{
|
|
1506 |
$list[] = $lower + $i;
|
|
1507 |
}
|
|
1508 |
}
|
|
1509 |
$url = sprintf($result_url, '0');
|
|
1510 |
$link = ( 0 == $start ) ? "<b>First</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>« First</a>";
|
|
1511 |
$blk->assign_vars(array(
|
|
1512 |
'CLASS'=>$cls,
|
|
1513 |
'LINK'=>$link
|
|
1514 |
));
|
|
1515 |
$inner .= $blk->run();
|
|
1516 |
|
|
1517 |
// if ( !in_array(1, $list) )
|
|
1518 |
// {
|
|
1519 |
// $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1520 |
// $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
|
|
1521 |
// $inner .= $blk->run();
|
|
1522 |
// }
|
|
1523 |
|
|
1524 |
foreach ( $list as $i )
|
|
1525 |
{
|
|
1526 |
if ( $i == $num_pages )
|
|
1527 |
break;
|
|
1528 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1529 |
$offset = strval($i * $perpage);
|
|
1530 |
$url = sprintf($result_url, $offset);
|
|
1531 |
$j = $i + 1;
|
|
1532 |
$link = ( $offset == strval($start) ) ? "<b>$j</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>$j</a>";
|
|
1533 |
$blk->assign_vars(array(
|
|
1534 |
'CLASS'=>$cls,
|
|
1535 |
'LINK'=>$link
|
|
1536 |
));
|
|
1537 |
$inner .= $blk->run();
|
|
1538 |
}
|
|
1539 |
|
|
1540 |
$total = $num_pages * $perpage - $perpage;
|
|
1541 |
|
|
1542 |
if ( $this_page < $num_pages )
|
|
1543 |
{
|
|
1544 |
// $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1545 |
// $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
|
|
1546 |
// $inner .= $blk->run();
|
|
1547 |
|
|
1548 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1549 |
$offset = strval($total);
|
|
1550 |
$url = sprintf($result_url, $offset);
|
|
1551 |
$j = $i + 1;
|
|
1552 |
$link = ( $offset == strval($start) ) ? "<b>Last</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Last »</a>";
|
|
1553 |
$blk->assign_vars(array(
|
|
1554 |
'CLASS'=>$cls,
|
|
1555 |
'LINK'=>$link
|
|
1556 |
));
|
|
1557 |
$inner .= $blk->run();
|
|
1558 |
}
|
|
1559 |
|
|
1560 |
}
|
|
1561 |
|
|
1562 |
$inner .= '<td class="row2" style="cursor: pointer;" onclick="paginator_goto(this, '.$this_page.', '.$num_pages.', '.$perpage.', unescape(\'' . rawurlencode($result_url) . '\'));">↓</td>';
|
|
1563 |
|
|
1564 |
$paginator = "\n$begin$inner$end\n";
|
|
1565 |
$out .= $paginator;
|
|
1566 |
|
|
1567 |
$cls = 'row2';
|
|
1568 |
|
|
1569 |
if ( $row = $db->fetchrow($q) )
|
|
1570 |
{
|
|
1571 |
$i = 0;
|
|
1572 |
$out .= $header;
|
|
1573 |
do {
|
|
1574 |
$i++;
|
|
1575 |
if ( $i <= $start )
|
|
1576 |
{
|
|
1577 |
continue;
|
|
1578 |
}
|
|
1579 |
if ( ( $i - $start ) > $perpage )
|
|
1580 |
{
|
|
1581 |
break;
|
|
1582 |
}
|
|
1583 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1584 |
foreach ( $row as $j => $val )
|
|
1585 |
{
|
|
1586 |
if ( isset($callers[$j]) )
|
|
1587 |
{
|
|
1588 |
$tmp = ( is_callable($callers[$j]) ) ? @call_user_func($callers[$j], $val, $row) : $v;
|
|
1589 |
|
|
1590 |
if ( $tmp )
|
|
1591 |
{
|
|
1592 |
$row[$j] = $tmp;
|
|
1593 |
}
|
|
1594 |
}
|
|
1595 |
}
|
|
1596 |
$parser->assign_vars($row);
|
|
1597 |
$parser->assign_vars(array('_css_class' => $cls));
|
|
1598 |
$out .= $parser->run();
|
|
1599 |
} while ( $row = $db->fetchrow($q) );
|
|
1600 |
$out .= $footer;
|
|
1601 |
}
|
|
1602 |
|
|
1603 |
$out .= $paginator;
|
|
1604 |
|
|
1605 |
return $out;
|
|
1606 |
}
|
|
1607 |
|
|
1608 |
/**
|
|
1609 |
* This is the same as paginate(), but it processes an array instead of a MySQL result resource.
|
|
1610 |
* @param array The results. Each value is simply echoed.
|
|
1611 |
* @param int The number of total results. This should be determined by a second query.
|
|
1612 |
* @param string sprintf-style formatting string for URLs for result pages. First parameter will be start offset.
|
|
1613 |
* @param int Optional. Start offset in individual results. Defaults to 0.
|
|
1614 |
* @param int Optional. The number of results per page. Defualts to 10.
|
|
1615 |
* @param string Optional. The text to be sent before the result list, only if there are any results. Possibly the start of a table.
|
|
1616 |
* @param string Optional. The text to be sent after the result list, only if there are any results. Possibly the end of a table.
|
|
1617 |
* @return string
|
|
1618 |
*/
|
|
1619 |
|
|
1620 |
function paginate_array($q, $num_results, $result_url, $start = 0, $perpage = 10, $header = '', $footer = '')
|
|
1621 |
{
|
|
1622 |
global $db, $session, $paths, $template, $plugins; // Common objects
|
|
1623 |
$parser = $template->makeParserText($tpl_text);
|
|
1624 |
$num_pages = ceil ( $num_results / $perpage );
|
|
1625 |
$out = '';
|
|
1626 |
$i = 0;
|
|
1627 |
$this_page = ceil ( $start / $perpage );
|
|
1628 |
|
|
1629 |
// Build paginator
|
|
1630 |
$begin = '<div class="tblholder" style="display: table; margin: 10px 0 0 auto;">
|
|
1631 |
<table border="0" cellspacing="1" cellpadding="4">
|
|
1632 |
<tr><th>Page:</th>';
|
|
1633 |
$block = '<td class="row1" style="text-align: center;">{LINK}</td>';
|
|
1634 |
$end = '</tr></table></div>';
|
|
1635 |
$blk = $template->makeParserText($block);
|
|
1636 |
$inner = '';
|
|
1637 |
$cls = 'row2';
|
|
1638 |
if ( $start > 0 )
|
|
1639 |
{
|
|
1640 |
$url = sprintf($result_url, abs($start - $perpage));
|
|
1641 |
$link = "<a href=".'"'."$url".'"'." style='text-decoration: none;'>« Prev</a>";
|
|
1642 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1643 |
$blk->assign_vars(array(
|
|
1644 |
'CLASS'=>$cls,
|
|
1645 |
'LINK'=>$link
|
|
1646 |
));
|
|
1647 |
$inner .= $blk->run();
|
|
1648 |
}
|
|
1649 |
if ( $num_pages < 5 )
|
|
1650 |
{
|
|
1651 |
for ( $i = 0; $i < $num_pages; $i++ )
|
|
1652 |
{
|
|
1653 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1654 |
$offset = strval($i * $perpage);
|
|
1655 |
$url = sprintf($result_url, $offset);
|
|
1656 |
$j = $i + 1;
|
|
1657 |
$link = ( $offset == strval($start) ) ? "<b>$j</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>$j</a>";
|
|
1658 |
$blk->assign_vars(array(
|
|
1659 |
'CLASS'=>$cls,
|
|
1660 |
'LINK'=>$link
|
|
1661 |
));
|
|
1662 |
$inner .= $blk->run();
|
|
1663 |
}
|
|
1664 |
}
|
|
1665 |
else
|
|
1666 |
{
|
|
1667 |
if ( $this_page + 5 > $num_pages )
|
|
1668 |
{
|
|
1669 |
$list = Array();
|
|
1670 |
$tp = $this_page;
|
|
1671 |
if ( $this_page + 0 == $num_pages ) $tp = $tp - 3;
|
|
1672 |
if ( $this_page + 1 == $num_pages ) $tp = $tp - 2;
|
|
1673 |
if ( $this_page + 2 == $num_pages ) $tp = $tp - 1;
|
|
1674 |
for ( $i = $tp - 1; $i <= $tp + 1; $i++ )
|
|
1675 |
{
|
|
1676 |
$list[] = $i;
|
|
1677 |
}
|
|
1678 |
}
|
|
1679 |
else
|
|
1680 |
{
|
|
1681 |
$list = Array();
|
|
1682 |
$current = $this_page;
|
|
1683 |
$lower = ( $current < 3 ) ? 1 : $current - 1;
|
|
1684 |
for ( $i = 0; $i < 3; $i++ )
|
|
1685 |
{
|
|
1686 |
$list[] = $lower + $i;
|
|
1687 |
}
|
|
1688 |
}
|
|
1689 |
$url = sprintf($result_url, '0');
|
|
1690 |
$link = ( 0 == $start ) ? "<b>First</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>« First</a>";
|
|
1691 |
$blk->assign_vars(array(
|
|
1692 |
'CLASS'=>$cls,
|
|
1693 |
'LINK'=>$link
|
|
1694 |
));
|
|
1695 |
$inner .= $blk->run();
|
|
1696 |
|
|
1697 |
// if ( !in_array(1, $list) )
|
|
1698 |
// {
|
|
1699 |
// $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1700 |
// $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
|
|
1701 |
// $inner .= $blk->run();
|
|
1702 |
// }
|
|
1703 |
|
|
1704 |
foreach ( $list as $i )
|
|
1705 |
{
|
|
1706 |
if ( $i == $num_pages )
|
|
1707 |
break;
|
|
1708 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1709 |
$offset = strval($i * $perpage);
|
|
1710 |
$url = sprintf($result_url, $offset);
|
|
1711 |
$j = $i + 1;
|
|
1712 |
$link = ( $offset == strval($start) ) ? "<b>$j</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>$j</a>";
|
|
1713 |
$blk->assign_vars(array(
|
|
1714 |
'CLASS'=>$cls,
|
|
1715 |
'LINK'=>$link
|
|
1716 |
));
|
|
1717 |
$inner .= $blk->run();
|
|
1718 |
}
|
|
1719 |
|
|
1720 |
$total = $num_pages * $perpage - $perpage;
|
|
1721 |
|
|
1722 |
if ( $this_page < $num_pages )
|
|
1723 |
{
|
|
1724 |
// $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1725 |
// $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
|
|
1726 |
// $inner .= $blk->run();
|
|
1727 |
|
|
1728 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1729 |
$offset = strval($total);
|
|
1730 |
$url = sprintf($result_url, $offset);
|
|
1731 |
$j = $i + 1;
|
|
1732 |
$link = ( $offset == strval($start) ) ? "<b>Last</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Last »</a>";
|
|
1733 |
$blk->assign_vars(array(
|
|
1734 |
'CLASS'=>$cls,
|
|
1735 |
'LINK'=>$link
|
|
1736 |
));
|
|
1737 |
$inner .= $blk->run();
|
|
1738 |
}
|
|
1739 |
|
|
1740 |
}
|
|
1741 |
|
|
1742 |
if ( $start < $total )
|
|
1743 |
{
|
|
1744 |
$url = sprintf($result_url, abs($start + $perpage));
|
|
1745 |
$link = "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Next »</a>";
|
|
1746 |
$cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
|
|
1747 |
$blk->assign_vars(array(
|
|
1748 |
'CLASS'=>$cls,
|
|
1749 |
'LINK'=>$link
|
|
1750 |
));
|
|
1751 |
$inner .= $blk->run();
|
|
1752 |
}
|
|
1753 |
|
|
1754 |
$inner .= '<td class="row2" style="cursor: pointer;" onclick="paginator_goto(this, '.$this_page.', '.$num_pages.', '.$perpage.', unescape(\'' . rawurlencode($result_url) . '\'));">↓</td>';
|
|
1755 |
|
|
1756 |
$paginator = "\n$begin$inner$end\n";
|
|
1757 |
if ( $total > 1 )
|
|
1758 |
$out .= $paginator;
|
|
1759 |
|
|
1760 |
$cls = 'row2';
|
|
1761 |
|
|
1762 |
if ( sizeof($q) > 0 )
|
|
1763 |
{
|
|
1764 |
$i = 0;
|
|
1765 |
$out .= $header;
|
|
1766 |
foreach ( $q as $val ) {
|
|
1767 |
$i++;
|
|
1768 |
if ( $i <= $start )
|
|
1769 |
{
|
|
1770 |
continue;
|
|
1771 |
}
|
|
1772 |
if ( ( $i - $start ) > $perpage )
|
|
1773 |
{
|
|
1774 |
break;
|
|
1775 |
}
|
|
1776 |
$out .= $val;
|
|
1777 |
}
|
|
1778 |
$out .= $footer;
|
|
1779 |
}
|
|
1780 |
|
|
1781 |
if ( $total > 1 )
|
|
1782 |
$out .= $paginator;
|
|
1783 |
|
|
1784 |
return $out;
|
|
1785 |
}
|
|
1786 |
|
|
1787 |
/**
|
|
1788 |
* Enano version of fputs for debugging
|
|
1789 |
*/
|
|
1790 |
|
|
1791 |
function enano_fputs($socket, $data)
|
|
1792 |
{
|
|
1793 |
// echo '<pre>' . htmlspecialchars($data) . '</pre>';
|
|
1794 |
// flush();
|
|
1795 |
// ob_flush();
|
|
1796 |
// ob_end_flush();
|
|
1797 |
return fputs($socket, $data);
|
|
1798 |
}
|
|
1799 |
|
|
1800 |
/**
|
|
1801 |
* Sanitizes a page URL string so that it can safely be stored in the database.
|
|
1802 |
* @param string Page ID to sanitize
|
|
1803 |
* @return string Cleaned text
|
|
1804 |
*/
|
|
1805 |
|
|
1806 |
function sanitize_page_id($page_id)
|
|
1807 |
{
|
|
1808 |
|
|
1809 |
// First, replace spaces with underscores
|
|
1810 |
$page_id = str_replace(' ', '_', $page_id);
|
|
1811 |
|
|
1812 |
preg_match_all('/\.[A-Fa-f0-9][A-Fa-f0-9]/', $page_id, $matches);
|
|
1813 |
|
|
1814 |
foreach ( $matches[0] as $id => $char )
|
|
1815 |
{
|
|
1816 |
$char = substr($char, 1);
|
|
1817 |
$char = strtolower($char);
|
|
1818 |
$char = intval(hexdec($char));
|
|
1819 |
$char = chr($char);
|
|
1820 |
$page_id = str_replace($matches[0][$id], $char, $page_id);
|
|
1821 |
}
|
|
1822 |
|
|
1823 |
$pid_clean = preg_replace('/[\w\/:;\(\)@\[\]_-]/', 'X', $page_id);
|
|
1824 |
$pid_dirty = enano_str_split($pid_clean, 1);
|
|
1825 |
|
|
1826 |
foreach ( $pid_dirty as $id => $char )
|
|
1827 |
{
|
|
1828 |
if ( $char == 'X' )
|
|
1829 |
continue;
|
|
1830 |
$cid = ord($char);
|
|
1831 |
$cid = dechex($cid);
|
|
1832 |
$cid = strval($cid);
|
|
1833 |
if ( strlen($cid) < 2 )
|
|
1834 |
{
|
|
1835 |
$cid = strtoupper("0$cid");
|
|
1836 |
}
|
|
1837 |
$pid_dirty[$id] = ".$cid";
|
|
1838 |
}
|
|
1839 |
|
|
1840 |
$pid_chars = enano_str_split($page_id, 1);
|
|
1841 |
$page_id_cleaned = '';
|
|
1842 |
|
|
1843 |
foreach ( $pid_chars as $id => $char )
|
|
1844 |
{
|
|
1845 |
if ( $pid_dirty[$id] == 'X' )
|
|
1846 |
$page_id_cleaned .= $char;
|
|
1847 |
else
|
|
1848 |
$page_id_cleaned .= $pid_dirty[$id];
|
|
1849 |
}
|
|
1850 |
|
|
1851 |
global $mime_types;
|
|
1852 |
|
|
1853 |
$exts = array_keys($mime_types);
|
|
1854 |
$exts = '(' . implode('|', $exts) . ')';
|
|
1855 |
|
|
1856 |
$page_id_cleaned = preg_replace('/\.2e' . $exts . '$/', '.\\1', $page_id_cleaned);
|
|
1857 |
|
|
1858 |
return $page_id_cleaned;
|
|
1859 |
}
|
|
1860 |
|
|
1861 |
/**
|
|
1862 |
* Inserts commas into a number to make it more human-readable. Floating point-safe.
|
|
1863 |
* @param int The number to process
|
|
1864 |
* @return string Input number with commas added
|
|
1865 |
*/
|
|
1866 |
|
|
1867 |
function commatize($num)
|
|
1868 |
{
|
|
1869 |
$num = (string)$num;
|
|
1870 |
if ( strpos($num, '.') )
|
|
1871 |
{
|
|
1872 |
$whole = explode('.', $num);
|
|
1873 |
$num = $whole[0];
|
|
1874 |
$dec = $whole[1];
|
|
1875 |
}
|
|
1876 |
else
|
|
1877 |
{
|
|
1878 |
$whole = $num;
|
|
1879 |
}
|
|
1880 |
$offset = ( strlen($num) ) % 3;
|
|
1881 |
$len = strlen($num);
|
|
1882 |
$offset = ( $offset == 0 )
|
|
1883 |
? 3
|
|
1884 |
: $offset;
|
|
1885 |
for ( $i = $offset; $i < $len; $i=$i+3 )
|
|
1886 |
{
|
|
1887 |
$num = substr($num, 0, $i) . ',' . substr($num, $i, $len);
|
|
1888 |
$len = strlen($num);
|
|
1889 |
$i++;
|
|
1890 |
}
|
|
1891 |
if ( isset($dec) )
|
|
1892 |
{
|
|
1893 |
return $num . '.' . $dec;
|
|
1894 |
}
|
|
1895 |
else
|
|
1896 |
{
|
|
1897 |
return $num;
|
|
1898 |
}
|
|
1899 |
}
|
|
1900 |
|
|
1901 |
//die('<pre>Original: 01010101010100101010100101010101011010'."\nProcessed: ".uncompress_bitfield(compress_bitfield('01010101010100101010100101010101011010')).'</pre>');
|
|
1902 |
|
|
1903 |
?>
|