| [ Index ] | [ Index ] [ Classes ] [ Functions ] [ Variables ] [ Constants ] |
PHP Cross Reference of TXP stable 4.0.6 |
||
[Summary view] [Print] [Text view]
1 <?php 2 3 /* 4 $HeadURL: http://svn.textpattern.com/releases/4.0.6/source/textpattern/lib/txplib_misc.php $ 5 $LastChangedRevision: 2788 $ 6 */ 7 8 // ------------------------------------------------------------- 9 function doArray($in,$function) 10 { 11 return is_array($in) ? array_map($function,$in) : $function($in); 12 } 13 14 // ------------------------------------------------------------- 15 function doStrip($in) 16 { 17 return doArray($in,'stripslashes'); 18 } 19 20 // ------------------------------------------------------------- 21 function doStripTags($in) 22 { 23 return doArray($in,'strip_tags'); 24 } 25 26 // ------------------------------------------------------------- 27 function doDeEnt($in) 28 { 29 return doArray($in,'deEntBrackets'); 30 } 31 32 // ------------------------------------------------------------- 33 function deEntBrackets($in) 34 { 35 $array = array( 36 '<' => '<', 37 '<' => '<', 38 '<' => '<', 39 '>' => '>', 40 '>' => '>', 41 '>' => '>' 42 ); 43 44 foreach($array as $k=>$v){ 45 $in = preg_replace("/".preg_quote($k)."/i",$v, $in); 46 } 47 return $in; 48 } 49 50 // ------------------------------------------------------------- 51 function doSlash($in) 52 { 53 if(phpversion() >= "4.3.0") { 54 return doArray($in,'mysql_real_escape_string'); 55 } else { 56 return doArray($in,'mysql_escape_string'); 57 } 58 } 59 60 // ------------------------------------------------------------- 61 function doSpecial($in) 62 { 63 return doArray($in,'htmlspecialchars'); 64 } 65 66 // ------------------------------------------------------------- 67 function _null($a) 68 { 69 return NULL; 70 } 71 // ------------------------------------------------------------- 72 function array_null($in) 73 { 74 return array_map('_null', $in); 75 } 76 77 // ------------------------------------------------------------- 78 function escape_title($title) 79 { 80 return strtr($title, 81 array( 82 '<' => '<', 83 '>' => '>', 84 "'" => ''', 85 '"' => '"', 86 ) 87 ); 88 } 89 90 // ------------------------------------------------------------- 91 // deprecated, use htmlspecialchars instead. Remove in crockery 92 function escape_output($str) 93 { 94 return htmlspecialchars($str); 95 } 96 97 // ------------------------------------------------------------- 98 function escape_tags($str) 99 { 100 return strtr($str, 101 array( 102 '<' => '<', 103 '>' => '>', 104 ) 105 ); 106 } 107 108 // ------------------------------------------------------------- 109 function escape_cdata($str) 110 { 111 return '<![CDATA['.str_replace(']]>', ']]]><![CDATA[]>', $str).']]>'; 112 } 113 114 //------------------------------------------------------------- 115 function gTxt($var, $atts=array()) 116 { 117 global $textarray; 118 if(isset($textarray[strtolower($var)])) { 119 $out = $textarray[strtolower($var)]; 120 return strtr($out, $atts); 121 } 122 123 if ($atts) 124 return $var.': '.join(', ', $atts); 125 return $var; 126 } 127 128 //------------------------------------------------------------- 129 function gTime($timestamp) 130 { 131 return safe_strftime('%d %b %Y %X', $timestamp); 132 } 133 134 // ------------------------------------------------------------- 135 function dmp() 136 { 137 static $f = FALSE; 138 139 if(defined('txpdmpfile')) 140 { 141 global $prefs; 142 143 if(!$f) $f = fopen($prefs['tempdir'].'/'.txpdmpfile, 'a'); 144 145 fwrite($f, "\n[".safe_strftime('iso8601')."]\n"); 146 } 147 148 $a = func_get_args(); 149 150 if(!$f) echo "<pre>".n; 151 152 foreach ($a as $thing) 153 { 154 $out = is_scalar($thing) ? strval($thing) : var_export($thing, true); 155 156 if ($f) 157 { 158 fwrite($f, $out."\n"); 159 } 160 else 161 { 162 echo htmlspecialchars($out), n; 163 } 164 } 165 166 if(!$f) echo "</pre>".n; 167 } 168 169 // ------------------------------------------------------------- 170 function load_lang($lang) 171 { 172 global $txpcfg; 173 174 foreach(array($lang, 'en-gb') as $lang_code) 175 { 176 $rs = (txpinterface == 'admin') 177 ? safe_rows_start('name, data','txp_lang',"lang='".doSlash($lang_code)."'") 178 : safe_rows_start('name, data','txp_lang',"lang='".doSlash($lang_code)."' AND ( event='public' OR event='common')"); 179 180 if (mysql_num_rows($rs)) break; 181 } 182 183 $out = array(); 184 185 if ($rs && mysql_num_rows($rs) > 0) 186 { 187 while ($a = nextRow($rs)) 188 { 189 $out[$a['name']] = $a['data']; 190 } 191 }else{ 192 #backward compatibility stuff. Remove when necessary. 193 $filename = is_file(txpath.'/lang/'.$lang.'.txt') 194 ? txpath.'/lang/'.$lang.'.txt' 195 : txpath.'/lang/en-gb.txt'; 196 197 $file = @fopen($filename, "r"); 198 if ($file) { 199 while (!feof($file)) { 200 $line = fgets($file, 4096); 201 if($line[0]=='#') continue; 202 @list($name,$val) = explode(' => ',trim($line)); 203 $out[$name] = $val; 204 } 205 @fclose($filename); 206 } 207 } 208 209 return $out; 210 } 211 212 // ------------------------------------------------------------- 213 function load_lang_dates($lang) 214 { 215 global $txpcfg; 216 $filename = is_file(txpath.'/lang/'.$lang.'_dates.txt')? 217 txpath.'/lang/'.$lang.'_dates.txt': 218 txpath.'/lang/en-gb_dates.txt'; 219 $file = @file(txpath.'/lang/'.$lang.'_dates.txt','r'); 220 if(is_array($file)) { 221 foreach($file as $line) { 222 if($line[0]=='#' || strlen($line) < 2) continue; 223 list($name,$val) = explode('=>',$line,2); 224 $out[trim($name)] = trim($val); 225 } 226 return $out; 227 } 228 return false; 229 } 230 // ------------------------------------------------------------- 231 232 function load_lang_event($event) 233 { 234 global $txpcfg; 235 $lang = LANG; 236 237 $installed = safe_field('name', 'txp_lang',"lang='".doSlash($lang)."' limit 1"); 238 239 $lang_code = ($installed)? $lang : 'en-gb'; 240 241 $rs = safe_rows_start('name, data','txp_lang',"lang='".doSlash($lang_code)."' AND event='".doSlash($event)."'"); 242 243 $out = array(); 244 245 if ($rs && !empty($rs)) 246 { 247 while ($a = nextRow($rs)) 248 { 249 $out[$a['name']] = $a['data']; 250 } 251 } 252 return ($out) ? $out : ''; 253 } 254 255 // ------------------------------------------------------------- 256 function check_privs() 257 { 258 global $txp_user; 259 $privs = safe_field("privs", "txp_users", "name='".doSlash($txp_user)."'"); 260 $args = func_get_args(); 261 if(!in_array($privs,$args)) { 262 exit(pageTop('Restricted').'<p style="margin-top:3em;text-align:center">'. 263 gTxt('restricted_area').'</p>'); 264 } 265 } 266 267 // ------------------------------------------------------------- 268 function add_privs($res, $perm = '1') // perm = '1,2,3' 269 { 270 global $txp_permissions; 271 // Don't let them override privs that exist 272 if (!isset($txp_permissions[$res])) 273 $txp_permissions[$res] = $perm; 274 } 275 276 // ------------------------------------------------------------- 277 function has_privs($res, $user='') 278 { 279 global $txp_user, $txp_permissions; 280 static $privs; 281 282 // If no user name is supplied, assume the current login name 283 if (empty($user)) 284 $user = $txp_user; 285 286 if (!isset($privs[$user])) 287 { 288 $privs[$user] = safe_field("privs", "txp_users", "name='".doSlash($user)."'"); 289 } 290 291 if (isset($txp_permissions[$res])) 292 { 293 return in_array($privs[$user], explode(',', $txp_permissions[$res])); 294 } 295 296 else 297 { 298 return false; 299 } 300 } 301 302 // ------------------------------------------------------------- 303 function require_privs($res, $user='') 304 { 305 if (!has_privs($res, $user)) 306 exit(pageTop('Restricted').'<p style="margin-top:3em;text-align:center">'. 307 gTxt('restricted_area').'</p>'); 308 } 309 310 // ------------------------------------------------------------- 311 function sizeImage($name) 312 { 313 $size = @getimagesize($name); 314 return(is_array($size)) ? $size[3] : false; 315 } 316 317 // ------------------------------------------------------------- 318 function gps($thing) // checks GET and POST for a named variable, or creates it blank 319 { 320 if (isset($_GET[$thing])) { 321 if (MAGIC_QUOTES_GPC) { 322 return doStrip($_GET[$thing]); 323 } else { 324 return $_GET[$thing]; 325 } 326 } elseif (isset($_POST[$thing])) { 327 if (MAGIC_QUOTES_GPC) { 328 return doStrip($_POST[$thing]); 329 } else { 330 return $_POST[$thing]; 331 } 332 } 333 return ''; 334 } 335 336 // ------------------------------------------------------------- 337 function gpsa($array) // performs gps() on an array of variable names 338 { 339 if(is_array($array)) { 340 foreach($array as $a) { 341 $out[$a] = gps($a); 342 } 343 return $out; 344 } 345 return false; 346 } 347 348 // ------------------------------------------------------------- 349 function ps($thing) // checks POST for a named variable, or creates it blank 350 { 351 if (isset($_POST[$thing])) { 352 if (MAGIC_QUOTES_GPC) { 353 return doStrip($_POST[$thing]); 354 } else { 355 return $_POST[$thing]; 356 } 357 } 358 return ''; 359 } 360 361 // ------------------------------------------------------------- 362 function psa($array) // performs ps on an array of variable names 363 { 364 foreach($array as $a) { 365 $out[$a] = ps($a); 366 } 367 return $out; 368 } 369 370 // ------------------------------------------------------------- 371 function psas($array) // same as above, but does strip_tags on post values 372 { 373 foreach($array as $a) { 374 $out[$a] = strip_tags(ps($a)); 375 } 376 return $out; 377 } 378 379 // ------------------------------------------------------------- 380 function stripPost() 381 { 382 if (isset($_POST)) { 383 if (MAGIC_QUOTES_GPC) { 384 return doStrip($_POST); 385 } else { 386 return $_POST; 387 } 388 } 389 return ''; 390 } 391 392 // ------------------------------------------------------------- 393 function serverSet($thing) // Get a var from $_SERVER global array, or create it 394 { 395 return (isset($_SERVER[$thing])) ? $_SERVER[$thing] : ''; 396 } 397 398 // ------------------------------------------------------------- 399 function pcs($thing) // Get a var from POST or COOKIE; if not, create it 400 { 401 if (isset($_COOKIE["txp_".$thing])) { 402 if (MAGIC_QUOTES_GPC) { 403 return doStrip($_COOKIE["txp_".$thing]); 404 } else return $_COOKIE["txp_".$thing]; 405 } elseif (isset($_POST[$thing])) { 406 if (MAGIC_QUOTES_GPC) { 407 return doStrip($_POST[$thing]); 408 } else return $_POST[$thing]; 409 } 410 return ''; 411 } 412 413 // ------------------------------------------------------------- 414 function cs($thing) // Get a var from COOKIE; if not, create it 415 { 416 if (isset($_COOKIE[$thing])) { 417 if (MAGIC_QUOTES_GPC) { 418 return doStrip($_COOKIE[$thing]); 419 } else return $_COOKIE[$thing]; 420 } 421 return ''; 422 } 423 424 // ------------------------------------------------------------- 425 function yes_no($status) 426 { 427 return ($status==0) ? (gTxt('no')) : (gTxt('yes')); 428 } 429 430 // ------------------------------------------------------------- 431 function getmicrotime() 432 { 433 list($usec, $sec) = explode(" ",microtime()); 434 return ((float)$usec + (float)$sec); 435 } 436 437 // ------------------------------------------------------------- 438 function load_plugin($name) 439 { 440 global $plugins, $plugins_ver, $prefs, $txp_current_plugin; 441 442 if (is_array($plugins) and in_array($name,$plugins)) { 443 return true; 444 } 445 446 if (!empty($prefs['plugin_cache_dir'])) { 447 $dir = rtrim($prefs['plugin_cache_dir'], '/') . '/'; 448 # in case it's a relative path 449 if (!is_dir($dir)) 450 $dir = rtrim(realpath(txpath.'/'.$dir), '/') . '/'; 451 if (is_file($dir . $name . '.php')) { 452 $plugins[] = $name; 453 set_error_handler("pluginErrorHandler"); 454 $txp_current_plugin = $name; 455 include($dir . $name . '.php'); 456 $plugins_ver[$name] = @$plugin['version']; 457 restore_error_handler(); 458 return true; 459 } 460 } 461 462 $rs = safe_row("name,code,version","txp_plugin","status = 1 AND name='".doSlash($name)."'"); 463 if ($rs) { 464 $plugins[] = $rs['name']; 465 $plugins_ver[$rs['name']] = $rs['version']; 466 467 set_error_handler("pluginErrorHandler"); 468 $txp_current_plugin = $rs['name']; 469 eval($rs['code']); 470 restore_error_handler(); 471 472 return true; 473 } 474 475 return false; 476 } 477 478 // ------------------------------------------------------------- 479 function require_plugin($name) 480 { 481 if (!load_plugin($name)) 482 trigger_error("Unable to include required plugin \"{$name}\"",E_USER_ERROR); 483 } 484 485 // ------------------------------------------------------------- 486 function include_plugin($name) 487 { 488 if (!load_plugin($name)) 489 trigger_error("Unable to include plugin \"{$name}\"",E_USER_WARNING); 490 } 491 492 // ------------------------------------------------------------- 493 function pluginErrorHandler($errno, $errstr, $errfile, $errline) 494 { 495 $error = array( E_WARNING => "Warning", E_NOTICE => "Notice", E_USER_ERROR => "User_Error", 496 E_USER_WARNING => "User_Warning", E_USER_NOTICE => "User_Notice"); 497 498 if (!($errno & error_reporting())) return; 499 500 global $txp_current_plugin, $production_status; 501 printf ("<pre>".gTxt('plugin_load_error').' <b>%s</b> -> <b>%s: %s on line %s</b></pre>', 502 $txp_current_plugin, $error[$errno], $errstr, $errline); 503 if ($production_status == 'debug') 504 print "\n<pre style=\"padding-left: 2em;\" class=\"backtrace\"><code>".htmlspecialchars(join("\n", get_caller(10)))."</code></pre>"; 505 } 506 507 // ------------------------------------------------------------- 508 function tagErrorHandler($errno, $errstr, $errfile, $errline) 509 { 510 global $production_status; 511 512 $error = array( E_WARNING => "Warning", E_NOTICE => "Notice", E_USER_ERROR => "Textpattern Error", 513 E_USER_WARNING => "Textpattern Warning", E_USER_NOTICE => "Textpattern Notice"); 514 515 if (!($errno & error_reporting())) return; 516 if ($production_status == 'live') return; 517 518 global $txp_current_tag; 519 $errline = ($errstr === 'unknown_tag') ? '' : " on line $errline"; 520 printf ("<pre>".gTxt('tag_error').' <b>%s</b> -> <b> %s: %s %s</b></pre>', 521 htmlspecialchars($txp_current_tag), $error[$errno], $errstr, $errline ); 522 if ($production_status == 'debug') 523 { 524 print "\n<pre style=\"padding-left: 2em;\" class=\"backtrace\"><code>".htmlspecialchars(join("\n", get_caller(10)))."</code></pre>"; 525 526 $trace_msg = gTxt('tag_error').' '.$txp_current_tag.' -> '.$error[$errno].': '.$errstr.' '.$errline; 527 trace_add( $trace_msg ); 528 } 529 } 530 531 // ------------------------------------------------------------- 532 function feedErrorHandler($errno, $errstr, $errfile, $errline) 533 { 534 global $production_status; 535 536 if ($production_status != 'debug') return; 537 538 return tagErrorHandler($errno, $errstr, $errfile, $errline); 539 } 540 541 // ------------------------------------------------------------- 542 function load_plugins($type=NULL) 543 { 544 global $prefs,$plugins, $plugins_ver; 545 546 if (!is_array($plugins)) $plugins = array(); 547 548 if (!empty($prefs['plugin_cache_dir'])) { 549 $dir = rtrim($prefs['plugin_cache_dir'], DS) . DS; 550 # allow a relative path 551 if (!is_dir($dir)) { 552 $dir = realpath(txpath.DS.$dir); 553 if($dir) $dir = rtrim($dir, DS) . DS; 554 } 555 $dh = @opendir($dir); 556 while ($dh and false !== ($f = @readdir($dh))) { 557 if ($f{0} != '.') 558 load_plugin(basename($f, '.php')); 559 } 560 } 561 562 $where = 'status = 1'; 563 if ($type !== NULL) 564 $where .= (" and type='".doSlash($type)."'"); 565 566 $rs = safe_rows("name, code, version", "txp_plugin", $where); 567 if ($rs) { 568 $old_error_handler = set_error_handler("pluginErrorHandler"); 569 foreach($rs as $a) { 570 if (!in_array($a['name'],$plugins)) { 571 $plugins[] = $a['name']; 572 $plugins_ver[$a['name']] = $a['version']; 573 $GLOBALS['txp_current_plugin'] = $a['name']; 574 $eval_ok = eval($a['code']); 575 if ($eval_ok === FALSE) 576 echo gTxt('plugin_load_error_above').strong($a['name']).n.br; 577 unset($GLOBALS['txp_current_plugin']); 578 } 579 } 580 restore_error_handler(); 581 } 582 } 583 584 // ------------------------------------------------------------- 585 function register_callback($func, $event, $step='', $pre=0) 586 { 587 global $plugin_callback; 588 589 $plugin_callback[] = array('function'=>$func, 'event'=>$event, 'step'=>$step, 'pre'=>$pre); 590 } 591 592 // ------------------------------------------------------------- 593 function register_page_extension($func, $event, $step='', $top=0) 594 { 595 # For now this just does the same as register_callback 596 register_callback($func, $event, $step, $top); 597 } 598 599 // ------------------------------------------------------------- 600 function callback_event($event, $step='', $pre=0) 601 { 602 global $plugin_callback; 603 604 if (!is_array($plugin_callback)) 605 return; 606 $return_value = ''; 607 foreach ($plugin_callback as $c) { 608 if ($c['event'] == $event and (empty($c['step']) or $c['step'] == $step) and $c['pre'] == $pre) { 609 if (is_callable($c['function'])) { 610 $return_value .= call_user_func($c['function'], $event, $step); 611 } 612 } 613 } 614 return $return_value; 615 } 616 617 // ------------------------------------------------------------- 618 function register_tab($area, $event, $title) 619 { 620 global $plugin_areas; 621 622 $plugin_areas[$area][$title] = $event; 623 } 624 625 // ------------------------------------------------------------- 626 // deprecated, use lAtts instead. Remove in crockery 627 function getAtt($name, $default=NULL) 628 { 629 global $theseatts; 630 return isset($theseatts[$name]) ? $theseatts[$name] : $default; 631 } 632 633 // ------------------------------------------------------------- 634 // deprecated, use lAtts instead. Remove in crockery 635 function gAtt(&$atts, $name, $default=NULL) { 636 return isset($atts[$name]) ? $atts[$name] : $default; 637 } 638 639 // ------------------------------------------------------------- 640 function lAtts($pairs, $atts, $warn=1) 641 { 642 global $production_status; 643 644 foreach($pairs as $name => $default) 645 { 646 $out[$name] = isset($atts[$name]) ? $atts[$name] : $default; 647 } 648 649 if ($warn and ($production_status == 'debug' or $production_status == 'testing')) 650 { 651 foreach (array_diff(array_keys($atts), array_keys($pairs)) as $a) 652 { 653 trigger_error(gTxt('unknown_attribute', array('{att}' => $a))); 654 } 655 } 656 657 return ($out) ? $out : false; 658 } 659 660 // ------------------------------------------------------------- 661 function select_buttons() 662 { 663 return 664 gTxt('select').': '. 665 fInput('button','selall',gTxt('all'),'smallerboxsp','select all','selectall();'). 666 fInput('button','selnone',gTxt('none'),'smallerboxsp','select none','deselectall();'). 667 fInput('button','selrange',gTxt('range'),'smallerboxsp','select range','selectrange();'); 668 } 669 670 // ------------------------------------------------------------- 671 function stripSpace($text, $force=0) 672 { 673 global $prefs; 674 if ($force or !empty($prefs['attach_titles_to_permalinks'])) 675 { 676 $text = sanitizeForUrl($text); 677 if ($prefs['permalink_title_format']) { 678 return strtolower($text); 679 } else { 680 return str_replace('-','',$text); 681 } 682 } 683 } 684 685 // ------------------------------------------------------------- 686 function sanitizeForUrl($text) 687 { 688 // Remove names entities and tags 689 $text = preg_replace("/(^|&\S+;)|(<[^>]*>)/U","",dumbDown($text)); 690 // Collapse spaces, minuses and non-words 691 $text = preg_replace('/[\s\-]+/', '-', trim(preg_replace('/[^\w\s\-]/', '', $text))); 692 // Remove all non-whitelisted characters 693 $text = preg_replace("/[^A-Za-z0-9\-_]/","",$text); 694 return $text; 695 } 696 697 // ------------------------------------------------------------- 698 function dumbDown($str, $lang=NULL) 699 { 700 $array = array( // nasty, huh?. 701 'À'=>'A','À'=>'A','Á'=>'A','Á'=>'A','Â'=>'A','Â'=>'A', 702 'Ã'=>'A','Ã'=>'A','Ä'=>'Ae','Ä'=>'A','Å'=>'A','Å'=>'A', 703 'Æ'=>'Ae','Æ'=>'AE', 704 'Ā'=>'A','Ą'=>'A','Ă'=>'A', 705 'Ç'=>'C','Ç'=>'C','Ć'=>'C','Č'=>'C','Ĉ'=>'C','Ċ'=>'C', 706 'Ď'=>'D','Đ'=>'D','Ð'=>'D','Ð'=>'D', 707 'È'=>'E','È'=>'E','É'=>'E','É'=>'E','Ê'=>'E','Ê'=>'E','Ë'=>'E','Ë'=>'E', 708 'Ē'=>'E','Ę'=>'E','Ě'=>'E','Ĕ'=>'E','Ė'=>'E', 709 'Ĝ'=>'G','Ğ'=>'G','Ġ'=>'G','Ģ'=>'G', 710 'Ĥ'=>'H','Ħ'=>'H', 711 'Ì'=>'I','Ì'=>'I','Í'=>'I','Í'=>'I','Î'=>'I','Î'=>'I','Ï'=>'I','Ï'=>'I', 712 'Ī'=>'I','Ĩ'=>'I','Ĭ'=>'I','Į'=>'I','İ'=>'I', 713 'IJ'=>'IJ', 714 'Ĵ'=>'J', 715 'Ķ'=>'K', 716 'Ł'=>'K','Ľ'=>'K','Ĺ'=>'K','Ļ'=>'K','Ŀ'=>'K', 717 'Ñ'=>'N','Ñ'=>'N','Ń'=>'N','Ň'=>'N','Ņ'=>'N','Ŋ'=>'N', 718 'Ò'=>'O','Ò'=>'O','Ó'=>'O','Ó'=>'O','Ô'=>'O','Ô'=>'O','Õ'=>'O','Õ'=>'O', 719 'Ö'=>'Oe','Ö'=>'Oe', 720 'Ø'=>'O','Ø'=>'O','Ō'=>'O','Ő'=>'O','Ŏ'=>'O', 721 'Œ'=>'OE', 722 'Ŕ'=>'R','Ř'=>'R','Ŗ'=>'R', 723 'Ś'=>'S','Š'=>'S','Ş'=>'S','Ŝ'=>'S','Ș'=>'S', 724 'Ť'=>'T','Ţ'=>'T','Ŧ'=>'T','Ț'=>'T', 725 'Ù'=>'U','Ù'=>'U','Ú'=>'U','Ú'=>'U','Û'=>'U','Û'=>'U', 726 'Ü'=>'Ue','Ū'=>'U','Ü'=>'Ue', 727 'Ů'=>'U','Ű'=>'U','Ŭ'=>'U','Ũ'=>'U','Ų'=>'U', 728 'Ŵ'=>'W', 729 'Ý'=>'Y','Ý'=>'Y','Ŷ'=>'Y','Ÿ'=>'Y', 730 'Ź'=>'Z','Ž'=>'Z','Ż'=>'Z', 731 'Þ'=>'T','Þ'=>'T', 732 'à'=>'a','á'=>'a','â'=>'a','ã'=>'a','ä'=>'ae', 733 'ä'=>'ae', 734 'å'=>'a','ā'=>'a','ą'=>'a','ă'=>'a','å'=>'a', 735 'æ'=>'ae', 736 'ç'=>'c','ć'=>'c','č'=>'c','ĉ'=>'c','ċ'=>'c', 737 'ď'=>'d','đ'=>'d','ð'=>'d', 738 'è'=>'e','é'=>'e','ê'=>'e','ë'=>'e','ē'=>'e', 739 'ę'=>'e','ě'=>'e','ĕ'=>'e','ė'=>'e', 740 'ƒ'=>'f', 741 'ĝ'=>'g','ğ'=>'g','ġ'=>'g','ģ'=>'g', 742 'ĥ'=>'h','ħ'=>'h', 743 'ì'=>'i','í'=>'i','î'=>'i','ï'=>'i','ī'=>'i', 744 'ĩ'=>'i','ĭ'=>'i','į'=>'i','ı'=>'i', 745 'ij'=>'ij', 746 'ĵ'=>'j', 747 'ķ'=>'k','ĸ'=>'k', 748 'ł'=>'l','ľ'=>'l','ĺ'=>'l','ļ'=>'l','ŀ'=>'l', 749 'ñ'=>'n','ń'=>'n','ň'=>'n','ņ'=>'n','ʼn'=>'n', 750 'ŋ'=>'n', 751 'ò'=>'o','ó'=>'o','ô'=>'o','õ'=>'o','ö'=>'oe', 752 'ö'=>'oe', 753 'ø'=>'o','ō'=>'o','ő'=>'o','ŏ'=>'o', 754 'œ'=>'oe', 755 'ŕ'=>'r','ř'=>'r','ŗ'=>'r', 756 'š'=>'s', 757 'ù'=>'u','ú'=>'u','û'=>'u','ü'=>'ue','ū'=>'u', 758 'ü'=>'ue', 759 'ů'=>'u','ű'=>'u','ŭ'=>'u','ũ'=>'u','ų'=>'u', 760 'ŵ'=>'w', 761 'ý'=>'y','ÿ'=>'y','ŷ'=>'y', 762 'ž'=>'z','ż'=>'z','ź'=>'z', 763 'þ'=>'t', 764 'ß'=>'ss', 765 'ſ'=>'ss', 766 'à'=>'a','á'=>'a','â'=>'a','ã'=>'a','ä'=>'ae', 767 'å'=>'a','æ'=>'ae','ç'=>'c','ð'=>'d', 768 'è'=>'e','é'=>'e','ê'=>'e','ë'=>'e', 769 'ì'=>'i','í'=>'i','î'=>'i','ï'=>'i', 770 'ñ'=>'n', 771 'ò'=>'o','ó'=>'o','ô'=>'o','õ'=>'o','ö'=>'oe', 772 'ø'=>'o', 773 'ù'=>'u','ú'=>'u','û'=>'u','ü'=>'ue', 774 'ý'=>'y','ÿ'=>'y', 775 'þ'=>'t', 776 'ß'=>'ss' 777 ); 778 779 780 if (is_file(txpath.'/lib/i18n-ascii.txt')) { 781 $i18n = parse_ini_file(txpath.'/lib/i18n-ascii.txt', true); 782 # load the global map 783 if (@is_array($i18n['default'])) { 784 $array = array_merge($array,$i18n['default']); 785 # language overrides 786 $lang = empty($lang) ? LANG : $lang; 787 if (@is_array($i18n[$lang])) 788 $array = array_merge($array,$i18n[$lang]); 789 } 790 # load an old file (no sections) just in case 791 else 792 $array = array_merge($array,$i18n); 793 } 794 795 return strtr($str, $array); 796 } 797 798 // ------------------------------------------------------------- 799 function clean_url($url) 800 { 801 return preg_replace("/\"|'|(?:\s.*$)/",'',$url); 802 } 803 804 // ------------------------------------------------------------- 805 function noWidow($str) 806 { 807 // replace the last space with a nbsp 808 if (REGEXP_UTF8 == 1) 809 return preg_replace('@[ ]+([[:punct:]]?\pL+[[:punct:]]?)$@u', ' $1', rtrim($str)); 810 return preg_replace('@[ ]+([[:punct:]]?\w+[[:punct:]]?)$@', ' $1', rtrim($str)); 811 } 812 813 // ------------------------------------------------------------- 814 function is_blacklisted($ip, $checks = '') 815 { 816 global $prefs; 817 if (!$checks) $checks = explode(',', $prefs['spam_blacklists']); 818 819 $rip = join('.',array_reverse(explode(".",$ip))); 820 foreach ($checks as $a) { 821 $parts = explode(':', trim($a), 2); 822 $rbl = $parts[0]; 823 if (isset($parts[1])) { 824 foreach (explode(':', $parts[1]) as $code) { 825 $codes[] = strpos($code, '.') ? $code : '127.0.0.'.$code; 826 } 827 } 828 $hosts = @gethostbynamel($rip.'.'.trim($rbl,'. ').'.'); 829 if ($hosts and (!isset($codes) or array_intersect($hosts, $codes))) { 830 $listed[] = $rbl; 831 } 832 } 833 return (!empty($listed)) ? join(', ',$listed) : false; 834 } 835 836 // ------------------------------------------------------------- 837 function is_logged_in($user = '') 838 { 839 $name = substr(cs('txp_login_public'), 10); 840 841 if (!strlen($name) or strlen($user) and $user !== $name) 842 { 843 return FALSE; 844 } 845 846 $rs = safe_row('nonce, name, RealName, email, privs', 'txp_users', "name = '".doSlash($name)."'"); 847 848 if ($rs and substr(md5($rs['nonce']), -10) === substr(cs('txp_login_public'), 0, 10)) 849 { 850 unset($rs['nonce']); 851 return $rs; 852 } 853 else 854 { 855 return FALSE; 856 } 857 } 858 859 // ------------------------------------------------------------- 860 function updateSitePath($here) 861 { 862 $here = doSlash($here); 863 $rs = safe_field ("name",'txp_prefs',"name = 'path_to_site'"); 864 if (!$rs) { 865 safe_insert("txp_prefs","prefs_id=1,name='path_to_site',val='$here'"); 866 } else { 867 safe_update('txp_prefs',"val='$here'","name='path_to_site'"); 868 } 869 } 870 871 // ------------------------------------------------------------- 872 function splat($text) 873 { 874 $atts = array(); 875 if (preg_match_all('/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)/', $text, $match, PREG_SET_ORDER)) { 876 foreach ($match as $m) { 877 if (!empty($m[1])) 878 $atts[strtolower($m[1])] = stripcslashes($m[2]); 879 elseif (!empty($m[3])) 880 $atts[strtolower($m[3])] = stripcslashes($m[4]); 881 elseif (!empty($m[5])) 882 $atts[strtolower($m[5])] = stripcslashes($m[6]); 883 } 884 } 885 return $atts; 886 } 887 888 // ------------------------------------------------------------- 889 function maxMemUsage($message = 'none', $returnit = 0) 890 { 891 static $memory_top = 0; 892 static $memory_message; 893 894 if (is_callable('memory_get_usage')) 895 { 896 $memory_now = memory_get_usage(); 897 if ($memory_now > $memory_top) 898 { 899 $memory_top = $memory_now; 900 $memory_message = $message; 901 } 902 } 903 904 if ($returnit != 0) 905 { 906 if (is_callable('memory_get_usage')) 907 return n.comment(sprintf('Memory: %sKb, %s', 908 ceil($memory_top/1024),$memory_message)); 909 else 910 return n.comment('Memory: no info available'); 911 } 912 } 913 914 // ------------------------------------------------------------- 915 function strip_rn($str) 916 { 917 return preg_replace('/[\r\n]/', ' ', $str); 918 } 919 920 // ------------------------------------------------------------- 921 922 function is_valid_email($address) 923 { 924 return preg_match('/^[a-z0-9](\.?[a-z0-9_+%-])*@([a-z0-9](-*[a-z0-9])*\.)+[a-z]{2,6}$/i', $address); 925 } 926 927 // ------------------------------------------------------------- 928 929 function txpMail($to_address, $subject, $body, $reply_to = null) 930 { 931 global $txp_user, $prefs; 932 933 // Likely sending passwords 934 if (isset($txp_user)) 935 { 936 extract(safe_row('RealName, email', 'txp_users', "name = '".doSlash($txp_user)."'")); 937 } 938 939 // Likely sending comments -> "to" equals "from" 940 else 941 { 942 extract(safe_row('RealName, email', 'txp_users', "email = '".doSlash($to_address)."'")); 943 } 944 945 if ($prefs['override_emailcharset'] and is_callable('utf8_decode')) 946 { 947 $charset = 'ISO-8859-1'; 948 949 $RealName = utf8_decode($RealName); 950 $subject = utf8_decode($subject); 951 $body = utf8_decode($body); 952 } 953 954 else 955 { 956 $charset = 'UTF-8'; 957 } 958 959 $RealName = encode_mailheader(strip_rn($RealName), 'phrase'); 960 $subject = encode_mailheader(strip_rn($subject), 'text'); 961 $email = strip_rn($email); 962 963 if (!is_null($reply_to)) 964 { 965 $reply_to = strip_rn($reply_to); 966 } 967 968 if (!is_callable('mail')) 969 { 970 return false; 971 } 972 973 else 974 { 975 $sep = !is_windows() ? "\n" : "\r\n"; 976 977 $body = str_replace("\r\n", "\n", $body); 978 $body = str_replace("\r", "\n", $body); 979 $body = str_replace("\n", $sep, $body); 980 981 return mail($to_address, $subject, $body, 982 983 "From: $RealName <$email>". 984 $sep.'Reply-To: '.( isset($reply_to) ? $reply_to : "$RealName <$email>" ). 985 $sep.'X-Mailer: Textpattern'. 986 $sep.'Content-Transfer-Encoding: 8bit'. 987 $sep.'Content-Type: text/plain; charset="'.$charset.'"'. 988 $sep 989 ); 990 } 991 } 992 993 // ------------------------------------------------------------- 994 function encode_mailheader($string, $type) 995 { 996 global $prefs; 997 if (!strstr($string,'=?') and !preg_match('/[\x00-\x1F\x7F-\xFF]/', $string)) { 998 if ("phrase" == $type) { 999 if (preg_match('/[][()<>@,;:".\x5C]/', $string)) { 1000 $string = '"'. strtr($string, array("\\" => "\\\\", '"' => '\"')) . '"'; 1001 } 1002 } 1003 elseif ( "text" != $type) { 1004 trigger_error( 'Unknown encode_mailheader type', E_USER_WARNING); 1005 } 1006 return $string; 1007 } 1008 if ($prefs['override_emailcharset'] and is_callable('utf8_decode')) { 1009 $start = '=?ISO-8859-1?B?'; 1010 $pcre = '/.{1,42}/s'; 1011 } 1012 else { 1013 $start = '=?UTF-8?B?'; 1014 $pcre = '/.{1,45}(?=[\x00-\x7F\xC0-\xFF]|$)/s'; 1015 } 1016 $end = '?='; 1017 $sep = is_windows() ? "\r\n" : "\n"; 1018 preg_match_all($pcre, $string, $matches); 1019 return $start . join($end.$sep.' '.$start, array_map('base64_encode',$matches[0])) . $end; 1020 } 1021 1022 // ------------------------------------------------------------- 1023 function stripPHP($in) 1024 { 1025 return preg_replace("/".chr(60)."\?(?:php)?|\?".chr(62)."/i",'',$in); 1026 } 1027 1028 // ------------------------------------------------------------- 1029 1030 /** 1031 * PEDRO: 1032 * Helper functions for common textpattern event files actions. 1033 * Code refactoring from original files. Intended to do easy and less error 1034 * prone the future build of new textpattern extensions, and to add new 1035 * events to multiedit forms. 1036 */ 1037 1038 function event_category_popup($name, $cat = '', $id = '') 1039 { 1040 $arr = array(''); 1041 $rs = getTree('root', $name); 1042 1043 if ($rs) 1044 { 1045 return treeSelectInput('category', $rs, $cat, $id); 1046 } 1047 1048 return false; 1049 } 1050 1051 // ------------------------------------------------------------- 1052 function event_change_pageby($name) 1053 { 1054 $qty = gps('qty'); 1055 safe_update('txp_prefs',"val='".doSlash($qty)."'","name='".doSlash($name).'_list_pageby'."'"); 1056 return; 1057 } 1058 1059 // ------------------------------------------------------------- 1060 1061 function event_multiedit_form($name, $methods = null, $page, $sort, $dir, $crit, $search_method) 1062 { 1063 $method = ps('edit_method'); 1064 1065 if ($methods === NULL) 1066 { 1067 $methods = array( 1068 'delete' => gTxt('delete') 1069 ); 1070 } 1071 1072 return '<label for="withselected">'.gTxt('with_selected').'</label>'.sp. 1073 selectInput('edit_method', $methods, $method, 1, 1074 ( ($name == 'list') ? ' id="withselected" onchange="poweredit(this); return false;"' : ' id="withselected"' ) 1075 ). 1076 n.eInput($name). 1077 n.sInput($name.'_multi_edit'). 1078 n.hInput('page', $page). 1079 ( $sort ? n.hInput('sort', $sort).n.hInput('dir', $dir) : '' ). 1080 ( $crit ? n.hInput('crit', $crit).n.hInput('search_method', $search_method) : '' ). 1081 n.fInput('submit', '', gTxt('go'), 'smallerbox'); 1082 } 1083 1084 // ------------------------------------------------------------- 1085 1086 function event_multi_edit($table, $id_key) 1087 { 1088 $method = ps('edit_method'); 1089 $selected = ps('selected'); 1090 1091 if ($selected) 1092 { 1093 if ($method == 'delete') 1094 { 1095 foreach ($selected as $id) 1096 { 1097 $id = assert_int($id); 1098 1099 if (safe_delete($table, "$id_key = $id")) 1100 { 1101 $ids[] = $id; 1102 } 1103 } 1104 1105 return join(', ', $ids); 1106 } 1107 } 1108 1109 return ''; 1110 } 1111 1112 // ------------------------------------------------------------- 1113 function since($stamp) 1114 { 1115 $diff = (time() - $stamp); 1116 if ($diff <= 3600) { 1117 $mins = round($diff / 60); 1118 $since = ($mins <= 1) 1119 ? ($mins==1) 1120 ? '1 '.gTxt('minute') 1121 : gTxt('a_few_seconds') 1122 : "$mins ".gTxt('minutes'); 1123 } else if (($diff <= 86400) && ($diff > 3600)) { 1124 $hours = round($diff / 3600); 1125 $since = ($hours <= 1) ? '1 '.gTxt('hour') : "$hours ".gTxt('hours'); 1126 } else if ($diff >= 86400) { 1127 $days = round($diff / 86400); 1128 $since = ($days <= 1) ? "1 ".gTxt('day') : "$days ".gTxt('days'); 1129 } 1130 return $since.' '.gTxt('ago'); // sorry, this needs to be hacked until a truly multilingual version is done 1131 } 1132 1133 // ------------------------------------------------------------- 1134 // Calculate the offset between the server local time and the 1135 // user's selected time zone 1136 function tz_offset() 1137 { 1138 global $gmtoffset, $is_dst; 1139 1140 extract(getdate()); 1141 $serveroffset = gmmktime(0,0,0,$mon,$mday,$year) - mktime(0,0,0,$mon,$mday,$year); 1142 $offset = $gmtoffset - $serveroffset; 1143 1144 return $offset + ($is_dst ? 3600 : 0); 1145 } 1146 1147 // ------------------------------------------------------------- 1148 // Format a time, respecting the locale and local time zone, 1149 // and make sure the output string is safe for UTF-8 1150 function safe_strftime($format, $time='', $gmt=0, $override_locale='') 1151 { 1152 global $locale; 1153 $old_locale = $locale; 1154 1155 if (!$time) 1156 $time = time(); 1157 1158 # we could add some other formats here 1159 if ($format == 'iso8601' or $format == 'w3cdtf') { 1160 $format = '%Y-%m-%dT%H:%M:%SZ'; 1161 $gmt = 1; 1162 } 1163 elseif ($format == 'rfc822') { 1164 $format = '%a, %d %b %Y %H:%M:%S GMT'; 1165 $gmt = 1; 1166 $override_locale = 'en-gb'; 1167 } 1168 1169 if ($override_locale) 1170 getlocale($override_locale); 1171 1172 if ($format == 'since') 1173 $str = since($time); 1174 elseif ($gmt) 1175 $str = gmstrftime($format, $time); 1176 else 1177 $str = strftime($format, $time + tz_offset()); 1178 1179 @list($lang, $charset) = explode('.', $locale); 1180 if (empty($charset)) 1181 $charset = 'ISO-8859-1'; 1182 elseif (is_windows() and is_numeric($charset)) 1183 // Score -1 for consistent naming conventions 1184 $charset = 'Windows-'.$charset; 1185 1186 if ($charset != 'UTF-8' and $format != 'since') { 1187 $new = ''; 1188 if (is_callable('iconv')) 1189 $new = @iconv($charset, 'UTF-8', $str); 1190 1191 if ($new) 1192 $str = $new; 1193 elseif (is_callable('utf8_encode')) 1194 $str = utf8_encode($str); 1195 } 1196 1197 # revert to the old locale 1198 if ($override_locale) 1199 $locale = setlocale(LC_ALL, $old_locale); 1200 1201 return $str; 1202 } 1203 1204 // ------------------------------------------------------------- 1205 // Convert a time string from the Textpattern time zone to GMT 1206 function safe_strtotime($time_str) 1207 { 1208 return strtotime($time_str, time()+tz_offset()) - tz_offset(); 1209 } 1210 1211 // ------------------------------------------------------------- 1212 function myErrorHandler($errno, $errstr, $errfile, $errline) 1213 { 1214 # error_reporting() returns 0 when the '@' suppression 1215 # operator is used 1216 if (!error_reporting()) 1217 return; 1218 1219 echo '<pre>'.n.n."$errno: $errstr in $errfile at line $errline\n"; 1220 # Requires PHP 4.3 1221 if (is_callable('debug_backtrace')) { 1222 echo "Backtrace:\n"; 1223 $trace = debug_backtrace(); 1224 foreach($trace as $ent) { 1225 if(isset($ent['file'])) echo $ent['file'].':'; 1226 if(isset($ent['function'])) { 1227 echo $ent['function'].'('; 1228 if(isset($ent['args'])) { 1229 $args=''; 1230 foreach($ent['args'] as $arg) { $args.=$arg.','; } 1231 echo rtrim($args,','); 1232 } 1233 echo ') '; 1234 } 1235 if(isset($ent['line'])) echo 'at line '.$ent['line'].' '; 1236 if(isset($ent['file'])) echo 'in '.$ent['file']; 1237 echo "\n"; 1238 } 1239 } 1240 echo "</pre>"; 1241 } 1242 1243 // ------------------------------------------------------------- 1244 function find_temp_dir() 1245 { 1246 global $path_to_site, $img_dir; 1247 1248 if (is_windows()) { 1249 $guess = array(txpath.DS.'tmp', getenv('TMP'), getenv('TEMP'), getenv('SystemRoot').DS.'Temp', 'C:'.DS.'Temp', $path_to_site.DS.$img_dir); 1250 foreach ($guess as $k=>$v) 1251 if (empty($v)) unset($guess[$k]); 1252 } 1253 else 1254 $guess = array(txpath.DS.'tmp', '', DS.'tmp', $path_to_site.DS.$img_dir); 1255 1256 foreach ($guess as $dir) { 1257 $tf = realpath(@tempnam($dir, 'txp_')); 1258 if ($tf and file_exists($tf)) { 1259 unlink($tf); 1260 return dirname($tf); 1261 } 1262 } 1263 1264 return false; 1265 } 1266 1267 // ------------------------------------------------------------- 1268 function get_uploaded_file($f, $dest='') 1269 { 1270 global $tempdir; 1271 1272 if (!is_uploaded_file($f)) 1273 return false; 1274 1275 if ($dest) { 1276 $newfile = $dest; 1277 } 1278 else { 1279 $newfile = @tempnam($tempdir, 'txp_'); 1280 if (!$newfile) 1281 return false; 1282 } 1283 1284 # $newfile is created by tempnam(), but move_uploaded_file 1285 # will overwrite it 1286 if (move_uploaded_file($f, $newfile)) 1287 return $newfile; 1288 } 1289 1290 // -------------------------------------------------------------- 1291 function set_error_level($level) 1292 { 1293 1294 if ($level == 'debug') { 1295 error_reporting(E_ALL); 1296 } 1297 elseif ($level == 'live') { 1298 // don't show errors on screen 1299 error_reporting(E_ALL ^ (E_WARNING | E_NOTICE)); 1300 @ini_set("display_errors","1"); 1301 } 1302 else { 1303 // default is 'testing': display everything except notices 1304 error_reporting(E_ALL ^ (E_NOTICE)); 1305 } 1306 } 1307 1308 1309 // ------------------------------------------------------------- 1310 function shift_uploaded_file($f, $dest) 1311 { 1312 // Rename might not work, but it's worth a try 1313 if (@rename($f, $dest)) 1314 return true; 1315 1316 if (@copy($f, $dest)) { 1317 unlink($f); 1318 return true; 1319 } 1320 } 1321 // ------------------------------------------------------------- 1322 function upload_get_errormsg($err_code) 1323 { 1324 $msg = ''; 1325 switch ($err_code) 1326 { 1327 // Value: 0; There is no error, the file uploaded with success. 1328 case UPLOAD_ERR_OK : $msg = '';break; 1329 // Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini. 1330 case UPLOAD_ERR_INI_SIZE : $msg = gTxt('upload_err_ini_size');break; 1331 // Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form. 1332 case UPLOAD_ERR_FORM_SIZE : $msg = gTxt('upload_err_form_size');break; 1333 // Value: 3; The uploaded file was only partially uploaded. 1334 case UPLOAD_ERR_PARTIAL : $msg = gTxt('upload_err_partial');break; 1335 // Value: 4; No file was uploaded. 1336 case UPLOAD_ERR_NO_FILE : $msg = gTxt('upload_err_no_file');break; 1337 // Value: 6; Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3. 1338 case UPLOAD_ERR_NO_TMP_DIR : $msg = gTxt('upload_err_tmp_dir');break; 1339 // Value: 7; Failed to write file to disk. Introduced in PHP 5.1.0. 1340 case UPLOAD_ERR_CANT_WRITE : $msg = gTxt('upload_err_cant_write');break; 1341 // Value: 8; File upload stopped by extension. Introduced in PHP 5.2.0. 1342 case UPLOAD_ERR_EXTENSION : $msg = gTxt('upload_err_extension');break; 1343 } 1344 return $msg; 1345 } 1346 1347 // ------------------------------------------------------------- 1348 function is_windows() 1349 { 1350 return (PHP_OS == 'WINNT' or PHP_OS == 'WIN32' or PHP_OS == 'Windows'); 1351 } 1352 1353 // ------------------------------------------------------------- 1354 function is_cgi() 1355 { 1356 return IS_CGI; 1357 } 1358 1359 // ------------------------------------------------------------- 1360 function is_mod_php() 1361 { 1362 return IS_APACHE; 1363 } 1364 1365 // -------------------------------------------------------------- 1366 function build_file_path($base,$path) 1367 { 1368 $base = rtrim($base,'/\\'); 1369 $path = ltrim($path,'/\\'); 1370 1371 return $base.DIRECTORY_SEPARATOR.$path; 1372 } 1373 1374 // -------------------------------------------------------------- 1375 function get_author_name($name) 1376 { 1377 static $authors = array(); 1378 1379 if (isset($authors[$name])) 1380 return $authors[$name]; 1381 1382 $realname = fetch('RealName','txp_users','name',doSlash($name)); 1383 $authors[$name] = $realname; 1384 return ($realname) ? $realname : $name; 1385 } 1386 1387 1388 // -------------------------------------------------------------- 1389 function EvalElse($thing, $condition) 1390 { 1391 $f = '@(</?txp:\S+\b.*(?:(?<!br )/)?'.chr(62).')@sU'; 1392 1393 $parsed = preg_split($f, $thing, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); 1394 1395 $tagpat = '@^<(/?)txp:(\w+).*?(/?)>$@'; 1396 1397 $parts = array(0 => '', 1 => ''); 1398 $in = 0; 1399 $level = 0; 1400 foreach ($parsed as $chunk) { 1401 if (preg_match($tagpat, $chunk, $m)) { 1402 if ($m[2] == 'else' and $m[3] == '/' and $level == 0) { 1403 $in = 1-$in; 1404 } 1405 elseif ($m[1] == '' and $m[3] == '') { 1406 ++$level; 1407 $parts[$in] .= $chunk; 1408 } 1409 elseif ($m[1] == '/') { 1410 --$level; 1411 $parts[$in] .= $chunk; 1412 } 1413 else { 1414 $parts[$in] .= $chunk; 1415 } 1416 } 1417 else { 1418 $parts[$in] .= $chunk; 1419 } 1420 } 1421 1422 global $txp_current_tag; 1423 trace_add("[$txp_current_tag: ".($condition ? gTxt('true') : gTxt('false'))."]"); 1424 return ($condition ? $parts[0] : $parts[1]); 1425 } 1426 1427 // -------------------------------------------------------------- 1428 function fetch_form($name) 1429 { 1430 static $forms = array(); 1431 1432 if (isset($forms[$name])) 1433 $f = $forms[$name]; 1434 else { 1435 $row = safe_row('Form', 'txp_form',"name='".doSlash($name)."'"); 1436 if (!$row) { 1437 trigger_error(gTxt('form_not_found').': '.$name); 1438 return; 1439 } 1440 $f = $row['Form']; 1441 $forms[$name] = $f; 1442 } 1443 1444 trace_add('['.gTxt('form').': '.$name.']'); 1445 return $f; 1446 } 1447 1448 // -------------------------------------------------------------- 1449 function parse_form($name) 1450 { 1451 static $stack = array(); 1452 1453 $f = fetch_form($name); 1454 if ($f) { 1455 if (in_array($name, $stack)) { 1456 trigger_error(gTxt('form_circular_reference', array('{name}' => $name))); 1457 return; 1458 } 1459 array_push($stack, $name); 1460 $out = parse($f); 1461 array_pop($stack); 1462 return $out; 1463 } 1464 } 1465 1466 // -------------------------------------------------------------- 1467 function fetch_category_title($name, $type='article') 1468 { 1469 static $cattitles = array(); 1470 1471 if (isset($cattitles[$type][$name])) 1472 return $cattitles[$type][$name]; 1473 1474 $f = safe_field('title','txp_category',"name='".doSlash($name)."' and type='".doSlash($type)."'"); 1475 $cattitles[$type][$name] = $f; 1476 return $f; 1477 } 1478 1479 // ------------------------------------------------------------- 1480 function fetch_section_title($name) 1481 { 1482 static $sectitles = array(); 1483 1484 if (isset($sectitles[$name])) 1485 return $sectitles[$name]; 1486 1487 $f = safe_field('title','txp_section',"name='".doSlash($name)."'"); 1488 $sectitles[$name] = $f; 1489 return $f; 1490 } 1491 1492 // ------------------------------------------------------------- 1493 function update_comments_count($id) 1494 { 1495 $id = assert_int($id); 1496 $thecount = safe_field('count(*)','txp_discuss','parentid='.$id.' and visible='.VISIBLE); 1497 $thecount = assert_int($thecount); 1498 $updated = safe_update('textpattern','comments_count='.$thecount,'ID='.$id); 1499 return ($updated) ? true : false; 1500 } 1501 1502 // ------------------------------------------------------------- 1503 function clean_comment_counts($parentids) 1504 { 1505 $parentids = array_map('assert_int',$parentids); 1506 $rs = safe_rows_start('parentid, count(*) as thecount','txp_discuss','parentid IN ('.implode(',',$parentids).') AND visible='.VISIBLE.' group by parentid'); 1507 if (!$rs) return; 1508 1509 $updated = array(); 1510 while($a = nextRow($rs)) { 1511 safe_update('textpattern',"comments_count=".$a['thecount'],"ID=".$a['parentid']); 1512 $updated[] = $a['parentid']; 1513 } 1514 // We still need to update all those, that have zero comments left. 1515 $leftover = array_diff($parentids, $updated); 1516 if ($leftover) 1517 safe_update('textpattern',"comments_count=0","ID IN (".implode(',',$leftover).")"); 1518 } 1519 1520 // ------------------------------------------------------------- 1521 1522 function markup_comment($msg) 1523 { 1524 global $prefs; 1525 1526 $disallow_images = !empty($prefs['comments_disallow_images']); 1527 $lite = empty($prefs['comments_use_fat_textile']); 1528 1529 $rel = !empty($prefs['comment_nofollow']) ? 'nofollow' : ''; 1530 1531 include_once txpath.'/lib/classTextile.php'; 1532 1533 $textile = new Textile(); 1534 1535 return $textile->TextileRestricted($msg, $lite, $disallow_images, $rel); 1536 } 1537 1538 //------------------------------------------------------------- 1539 function update_lastmod() { 1540 safe_upsert("txp_prefs", "val = now()", "name = 'lastmod'"); 1541 } 1542 1543 //------------------------------------------------------------- 1544 function get_lastmod($unix_ts=NULL) { 1545 global $prefs; 1546 1547 if ($unix_ts === NULL) 1548 $unix_ts = @strtotime($prefs['lastmod']); 1549 1550 # check for future articles that are now visible 1551 if ($max_article = safe_field('unix_timestamp(Posted)', 'textpattern', "Posted <= now() and Status >= 4 order by Posted desc limit 1")) { 1552 $unix_ts = max($unix_ts, $max_article); 1553 } 1554 1555 return $unix_ts; 1556 } 1557 1558 //------------------------------------------------------------- 1559 function handle_lastmod($unix_ts=NULL, $exit=1) { 1560 global $prefs; 1561 extract($prefs); 1562 1563 if($send_lastmod and $production_status == 'live') { 1564 $unix_ts = get_lastmod($unix_ts); 1565 1566 # make sure lastmod isn't in the future 1567 $unix_ts = min($unix_ts, time()); 1568 # or too far in the past (7 days) 1569 $unix_ts = max($unix_ts, time() - 3600*24*7); 1570 1571 $last = safe_strftime('rfc822', $unix_ts, 1); 1572 header("Last-Modified: $last"); 1573 header('Cache-Control: no-cache'); 1574 1575 $hims = serverset('HTTP_IF_MODIFIED_SINCE'); 1576 if ($hims and @strtotime($hims) >= $unix_ts) { 1577 log_hit('304'); 1578 if (!$exit) 1579 return array('304', $last); 1580 txp_status_header('304 Not Modified'); 1581 # some mod_deflate versions have a bug that breaks subsequent 1582 # requests when keepalive is used. dropping the connection 1583 # is the only reliable way to fix this. 1584 if (empty($lastmod_keepalive)) 1585 header('Connection: close'); 1586 header('Content-Length: 0'); 1587 # discard all output 1588 while (@ob_end_clean()); 1589 exit; 1590 } 1591 1592 if (!$exit) 1593 return array('200', $last); 1594 } 1595 } 1596 1597 //------------------------------------------------------------- 1598 function set_pref($name, $val, $event='publish', $type=0, $html='text_input') 1599 { 1600 extract(doSlash(func_get_args())); 1601 1602 if (!safe_row("*", 'txp_prefs', "name = '$name'") ) { 1603 return safe_insert('txp_prefs', " 1604 name = '$name', 1605 val = '$val', 1606 event = '$event', 1607 html = '$html', 1608 type = '$type', 1609 prefs_id = 1" 1610 ); 1611 } else { 1612 return safe_update('txp_prefs', "val = '$val'","name like '$name'"); 1613 } 1614 return false; 1615 } 1616 1617 // ------------------------------------------------------------- 1618 function txp_status_header($status='200 OK') 1619 { 1620 if (IS_FASTCGI) 1621 header("Status: $status"); 1622 elseif ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0') 1623 header("HTTP/1.0 $status"); 1624 else 1625 header("HTTP/1.1 $status"); 1626 } 1627 1628 // ------------------------------------------------------------- 1629 function txp_die($msg, $status='503') 1630 { 1631 // 503 status might discourage search engines from indexing or caching the error message 1632 1633 //Make it possible to call this function as a tag, e.g. in an article <txp:txp_die status="410" /> 1634 if (is_array($msg)) 1635 extract(lAtts(array('msg' => '', 'status' => '503'),$msg)); 1636 1637 // Intentionally incomplete - just the ones we're likely to use 1638 $codes = array( 1639 '200' => 'OK', 1640 '301' => 'Moved Permanently', 1641 '302' => 'Found', 1642 '304' => 'Not Modified', 1643 '307' => 'Temporary Redirect', 1644 '401' => 'Unauthorized', 1645 '403' => 'Forbidden', 1646 '404' => 'Not Found', 1647 '410' => 'Gone', 1648 '414' => 'Request-URI Too Long', 1649 '500' => 'Internal Server Error', 1650 '501' => 'Not Implemented', 1651 '503' => 'Service Unavailable', 1652 ); 1653 1654 if ($status) { 1655 if (isset($codes[strval($status)])) 1656 $status = strval($status) . ' ' . $codes[$status]; 1657 1658 txp_status_header($status); 1659 } 1660 1661 $code = ''; 1662 if ($status and $parts = @explode(' ', $status, 2)) { 1663 $code = @$parts[0]; 1664 } 1665 1666 if (@$GLOBALS['connected']) { 1667 $out = safe_field('user_html','txp_page',"name='error_".doSlash($code)."'"); 1668 if (empty($out)) 1669 $out = safe_field('user_html','txp_page',"name='error_default'"); 1670 } 1671 1672 if (empty($out)) 1673 $out = <<<eod 1674 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 1675 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 1676 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 1677 <head> 1678 <meta http-equiv="content-type" content="text/html; charset=utf-8" /> 1679 <title>Textpattern Error: <txp:error_status /></title> 1680 </head> 1681 <body> 1682 <p align="center" style="margin-top:4em"><txp:error_message /></p> 1683 </body> 1684 </html> 1685 eod; 1686 1687 header("Content-type: text/html; charset=utf-8"); 1688 1689 if (is_callable('parse')) { 1690 1691 $GLOBALS['txp_error_message'] = $msg; 1692 $GLOBALS['txp_error_status'] = $status; 1693 $GLOBALS['txp_error_code'] = $code; 1694 1695 set_error_handler("tagErrorHandler"); 1696 die(parse($out)); 1697 } 1698 else { 1699 $out = preg_replace(array('@<txp:error_status[^>]*/>@', '@<txp:error_message[^>]*/>@'), 1700 array($status, $msg), 1701 $out); 1702 die($out); 1703 } 1704 } 1705 1706 // ------------------------------------------------------------- 1707 function join_qs($q) 1708 { 1709 $qs = array(); 1710 foreach ($q as $k=>$v) 1711 if ($v) 1712 $qs[] = urlencode($k) . '=' . urlencode($v); 1713 1714 $str = join('&', $qs); 1715 return ($str ? '?'.$str : ''); 1716 } 1717 1718 // ------------------------------------------------------------- 1719 1720 function pagelinkurl($parts, $inherit = array()) 1721 { 1722 global $permlink_mode; 1723 1724 // $inherit can be used to add parameters to an existing url, e.g: 1725 // $url = pagelinkurl(array('pg'=>2), $pretext); 1726 $keys = array_merge($inherit, $parts); 1727 1728 // can't use this to link to an article 1729 if (isset($keys['id'])) 1730 { 1731 unset($keys['id']); 1732 } 1733 1734 if (@$keys['s'] == 'default') 1735 { 1736 unset($keys['s']); 1737 } 1738 1739 if ($permlink_mode == 'messy') 1740 { 1741 return hu.'index.php'.join_qs($keys); 1742 } 1743 1744 else 1745 { 1746 // all clean URL modes use the same schemes for list pages 1747 $url = ''; 1748 1749 if (!empty($keys['rss'])) 1750 { 1751 $url = hu.'rss/'; 1752 unset($keys['rss']); 1753 return $url.join_qs($keys); 1754 } 1755 1756 elseif (!empty($keys['atom'])) 1757 { 1758 $url = hu.'atom/'; 1759 unset($keys['atom']); 1760 return $url.join_qs($keys); 1761 } 1762 1763 elseif (!empty($keys['s'])) 1764 { 1765 $url = hu.urlencode($keys['s']).'/'; 1766 unset($keys['s']); 1767 return $url.join_qs($keys); 1768 } 1769 1770 elseif (!empty($keys['author'])) 1771 { 1772 $url = hu.strtolower(urlencode(gTxt('author'))).'/'.urlencode($keys['author']).'/'; 1773 unset($keys['author']); 1774 return $url.join_qs($keys); 1775 } 1776 1777 elseif (!empty($keys['c'])) 1778 { 1779 $url = hu.strtolower(urlencode(gTxt('category'))).'/'.urlencode($keys['c']).'/'; 1780 unset($keys['c']); 1781 return $url.join_qs($keys); 1782 } 1783 1784 return hu.join_qs($keys); 1785 } 1786 } 1787 1788 // ------------------------------------------------------------- 1789 function filedownloadurl($id, $filename='') 1790 { 1791 global $permlink_mode; 1792 1793 $filename = urlencode($filename); 1794 #FIXME: work around yet another mod_deflate problem (double compression) 1795 # http://blogs.msdn.com/wndp/archive/2006/08/21/Content-Encoding-not-equal-Content-Type.aspx 1796 if (preg_match('/gz$/i', $filename)) 1797 $filename .= a; 1798 return ($permlink_mode == 'messy') ? 1799 hu.'index.php?s=file_download'.a.'id='.$id : 1800 hu.gTxt('file_download').'/'.$id.($filename ? '/'.$filename : ''); 1801 } 1802 1803 // ------------------------------------------------------------- 1804 1805 function in_list($val, $list, $delim = ',') 1806 { 1807 $args = do_list($list, $delim); 1808 1809 return in_array($val, $args); 1810 } 1811 1812 // ------------------------------------------------------------- 1813 1814 function do_list($list, $delim = ',') 1815 { 1816 return array_map('trim', explode($delim, $list)); 1817 } 1818 1819 // ------------------------------------------------------------- 1820 function doQuote($val) 1821 { 1822 return "'$val'"; 1823 } 1824 1825 // ------------------------------------------------------------- 1826 function quote_list($in) 1827 { 1828 $out = doSlash($in); 1829 return doArray($out, 'doQuote'); 1830 } 1831 1832 // ------------------------------------------------------------- 1833 function trace_add($msg) 1834 { 1835 global $production_status,$txptrace,$txptracelevel; 1836 1837 if (in_array($production_status, array('debug'))) 1838 @$txptrace[] = str_repeat("\t", @$txptracelevel).$msg; 1839 } 1840 1841 //------------------------------------------------------------- 1842 function article_push() { 1843 global $thisarticle, $stack_article; 1844 $stack_article[] = @$thisarticle; 1845 } 1846 1847 //------------------------------------------------------------- 1848 function article_pop() { 1849 global $thisarticle, $stack_article; 1850 $thisarticle = array_pop($stack_article); 1851 } 1852 // ------------------------------------------------------------- 1853 1854 function relative_path($path, $pfx=NULL) 1855 { 1856 if ($pfx === NULL) 1857 $pfx = dirname(txpath); 1858 return preg_replace('@^/'.preg_quote(ltrim($pfx, '/'), '@').'/?@', '', $path); 1859 } 1860 1861 // ------------------------------------------------------------- 1862 function get_caller($num=1,$start=2) 1863 { 1864 $out = array(); 1865 if (!is_callable('debug_backtrace')) 1866 return $out; 1867 1868 $bt = debug_backtrace(); 1869 for ($i=$start; $i< $num+$start; $i++) { 1870 if (!empty($bt[$i])) { 1871 $t = ''; 1872 if (!empty($bt[$i]['file'])) 1873 $t .= relative_path($bt[$i]['file']); 1874 if (!empty($bt[$i]['line'])) 1875 $t .= ':'.$bt[$i]['line']; 1876 if ($t) 1877 $t .= ' '; 1878 if (!empty($bt[$i]['class'])) 1879 $t .= $bt[$i]['class']; 1880 if (!empty($bt[$i]['type'])) 1881 $t .= $bt[$i]['type']; 1882 if (!empty($bt[$i]['function'])) { 1883 $t .= $bt[$i]['function']; 1884 1885 $t .= '()'; 1886 } 1887 1888 1889 $out[] = $t; 1890 } 1891 } 1892 return $out; 1893 } 1894 1895 //------------------------------------------------------------- 1896 // function name is misleading but remains for legacy reasons 1897 // this actually sets the locale 1898 function getlocale($lang) { 1899 global $locale; 1900 1901 if (empty($locale)) 1902 $locale = @setlocale(LC_TIME, '0'); 1903 1904 // Locale identifiers vary from system to system. The 1905 // following code will attempt to discover which identifiers 1906 // are available. We'll need to expand these lists to 1907 // improve support. 1908 // ISO identifiers: http://www.w3.org/WAI/ER/IG/ert/iso639.htm 1909 // Windows: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_language_strings.asp 1910 $guesses = array( 1911 'ar-dz' => array('ar_DZ.UTF-8', 'ar_DZ', 'ara', 'ar', 'arabic', 'ar_DZ.ISO_8859-6'), 1912 'bg-bg' => array('bg_BG.UTF-8', 'bg_BG', 'bg', 'bul', 'bulgarian', 'bg_BG.ISO8859-5'), 1913 'ca-es' => array('ca_ES.UTF-8', 'ca_ES', 'cat', 'ca', 'catalan', 'ca_ES.ISO_8859-1'), 1914 'cs-cz' => array('cs_CZ.UTF-8', 'cs_CZ', 'ces', 'cze', 'cs', 'csy', 'czech', 'cs_CZ.cs_CZ.ISO_8859-2'), 1915 'da-dk' => array('da_DK.UTF-8', 'da_DK'), 1916 'de-de' => array('de_DE.UTF-8', 'de_DE', 'de', 'deu', 'german', 'de_DE.ISO_8859-1'), 1917 'en-gb' => array('en_GB.UTF-8', 'en_GB', 'en_UK', 'eng', 'en', 'english-uk', 'english', 'en_GB.ISO_8859-1','C'), 1918 'en-us' => array('en_US.UTF-8', 'en_US', 'english-us', 'en_US.ISO_8859-1'), 1919 'es-es' => array('es_ES.UTF-8', 'es_ES', 'esp', 'spanish', 'es_ES.ISO_8859-1'), 1920 'et-ee' => array('et_EE.UTF-8', 'et_EE'), 1921 'el-gr' => array('el_GR.UTF-8', 'el_GR', 'el', 'gre', 'greek', 'el_GR.ISO_8859-7'), 1922 'fi-fi' => array('fi_FI.UTF-8', 'fi_FI', 'fin', 'fi', 'finnish', 'fi_FI.ISO_8859-1'), 1923 'fr-fr' => array('fr_FR.UTF-8', 'fr_FR', 'fra', 'fre', 'fr', 'french', 'fr_FR.ISO_8859-1'), 1924 'gl-gz' => array('gl_GZ.UTF-8', 'gl_GZ', 'glg', 'gl', '', ''), 1925 'he_il' => array('he_IL.UTF-8', 'he_IL', 'heb', 'he', 'hebrew', 'he_IL.ISO_8859-8'), 1926 'hr-hr' => array('hr_HR.UTF-8', 'hr_HR', 'hr'), 1927 'hu-hu' => array('hu_HU.UTF-8', 'hu_HU', 'hun', 'hu', 'hungarian', 'hu_HU.ISO8859-2'), 1928 'id-id' => array('id_ID.UTF-8', 'id_ID', 'id', 'ind', 'indonesian','id_ID.ISO_8859-1'), 1929 'is-is' => array('is_IS.UTF-8', 'is_IS'), 1930 'it-it' => array('it_IT.UTF-8', 'it_IT', 'it', 'ita', 'italian', 'it_IT.ISO_8859-1'), 1931 'ja-jp' => array('ja_JP.UTF-8', 'ja_JP', 'ja', 'jpn', 'japanese', 'ja_JP.ISO_8859-1'), 1932 'ko-kr' => array('ko_KR.UTF-8', 'ko_KR', 'ko', 'kor', 'korean'), 1933 'lv-lv' => array('lv_LV.UTF-8', 'lv_LV', 'lv', 'lav'), 1934 'nl-nl' => array('nl_NL.UTF-8', 'nl_NL', 'dut', 'nla', 'nl', 'nld', 'dutch', 'nl_NL.ISO_8859-1'), 1935 'no-no' => array('no_NO.UTF-8', 'no_NO', 'no', 'nor', 'norwegian', 'no_NO.ISO_8859-1'), 1936 'pl-pl' => array('pl_PL.UTF-8', 'pl_PL', 'pl', 'pol', 'polish', ''), 1937 'pt-br' => array('pt_BR.UTF-8', 'pt_BR', 'pt', 'ptb', 'portuguese-brazil', ''), 1938 'pt-pt' => array('pt_PT.UTF-8', 'pt_PT', 'por', 'portuguese', 'pt_PT.ISO_8859-1'), 1939 'ro-ro' => array('ro_RO.UTF-8', 'ro_RO', 'ron', 'rum', 'ro', 'romanian', 'ro_RO.ISO8859-2'), 1940 'ru-ru' => array('ru_RU.UTF-8', 'ru_RU', 'ru', 'rus', 'russian', 'ru_RU.ISO8859-5'), 1941 'sk-sk' => array('sk_SK.UTF-8', 'sk_SK', 'sk', 'slo', 'slk', 'sky', 'slovak', 'sk_SK.ISO_8859-1'), 1942 'sv-se' => array('sv_SE.UTF-8', 'sv_SE', 'sv', 'swe', 'sve', 'swedish', 'sv_SE.ISO_8859-1'), 1943 'th-th' => array('th_TH.UTF-8', 'th_TH', 'th', 'tha', 'thai', 'th_TH.ISO_8859-11'), 1944 'uk-ua' => array('uk_UA.UTF-8', 'uk_UA', 'uk', 'ukr'), 1945 'vi-vn' => array('vi_VN.UTF-8', 'vi_VN', 'vi', 'vie'), 1946 'zh-cn' => array('zh_CN.UTF-8', 'zh_CN'), 1947 'zh-tw' => array('zh_TW.UTF-8', 'zh_TW'), 1948 ); 1949 1950 if (!empty($guesses[$lang])) { 1951 $l = @setlocale(LC_TIME, $guesses[$lang]); 1952 if ($l !== false) 1953 $locale = $l; 1954 } 1955 @setlocale(LC_TIME, $locale); 1956 1957 return $locale; 1958 } 1959 1960 //------------------------------------------------------------- 1961 function assert_article() { 1962 global $thisarticle; 1963 if (empty($thisarticle)) 1964 trigger_error(gTxt('error_article_context')); 1965 } 1966 1967 //------------------------------------------------------------- 1968 function assert_comment() { 1969 global $thiscomment; 1970 if (empty($thiscomment)) 1971 trigger_error(gTxt('error_comment_context')); 1972 } 1973 1974 //------------------------------------------------------------- 1975 function assert_file() { 1976 global $thisfile; 1977 if (empty($thisfile)) 1978 trigger_error(gTxt('error_file_context')); 1979 } 1980 1981 //------------------------------------------------------------- 1982 function assert_link() { 1983 global $thislink; 1984 if (empty($thislink)) 1985 trigger_error(gTxt('error_link_context')); 1986 } 1987 1988 //------------------------------------------------------------- 1989 function assert_int($myvar) { 1990 global $production_status; 1991 1992 if (is_numeric($myvar) and $myvar == intval($myvar)) { 1993 return (int) $myvar; 1994 } 1995 1996 if (($production_status == 'debug') || (txpinterface == 'admin')) { 1997 trigger_error("<pre>Error: '".htmlspecialchars($myvar)."' is not an integer</pre>". 1998 "\n".'<pre style="padding-left: 2em;" class="backtrace"><code>'. 1999 htmlspecialchars(join("\n", get_caller(5,1))).'</code></pre>', E_USER_WARNING); 2000 } else trigger_error("'".htmlspecialchars($myvar)."' is not an integer.", E_USER_WARNING); 2001 return false; 2002 } 2003 2004 //------------------------------------------------------------- 2005 function replace_relative_urls($html, $permalink='') { 2006 2007 global $siteurl; 2008 2009 # urls like "/foo/bar" - relative to the domain 2010 if (serverSet('HTTP_HOST')) { 2011 $html = preg_replace('@(<a[^>]+href=")/@','$1'.PROTOCOL.serverSet('HTTP_HOST').'/',$html); 2012 $html = preg_replace('@(<img[^>]+src=")/@','$1'.PROTOCOL.serverSet('HTTP_HOST').'/',$html); 2013 } 2014 # "foo/bar" - relative to the textpattern root 2015 # leave "http:", "mailto:" et al. as absolute urls 2016 $html = preg_replace('@(<a[^>]+href=")(?!\w+:)@','$1'.PROTOCOL.$siteurl.'/$2',$html); 2017 $html = preg_replace('@(<img[^>]+src=")(?!\w+:)@','$1'.PROTOCOL.$siteurl.'/$2',$html); 2018 2019 if ($permalink) 2020 $html = preg_replace("/href=\\\"#(.*)\"/","href=\"".$permalink."#\\1\"",$html); 2021 return ($html); 2022 } 2023 2024 //------------------------------------------------------------- 2025 function show_clean_test($pretext) { 2026 echo md5(@$pretext['req']).n; 2027 if (serverSet('SERVER_ADDR') == serverSet('REMOTE_ADDR')) 2028 { 2029 var_export($pretext); 2030 } 2031 } 2032 2033 //------------------------------------------------------------- 2034 2035 function pager($total, $limit, $page) { 2036 $total = (int) $total; 2037 $limit = (int) $limit; 2038 $page = (int) $page; 2039 2040 $num_pages = ceil($total / $limit); 2041 2042 $page = min(max($page, 1), $num_pages); 2043 2044 $offset = max(($page - 1) * $limit, 0); 2045 2046 return array($page, $offset, $num_pages); 2047 } 2048 2049 //------------------------------------------------------------- 2050 // word-wrap a string using a zero width space 2051 function soft_wrap($text, $width, $break='​') 2052 { 2053 $wbr = chr(226).chr(128).chr(139); 2054 $words = explode(' ', $text); 2055 foreach($words as $wordnr => $word) { 2056 $word = preg_replace('|([,./\\>?!:;@-]+)(?=.)|', '$1 ', $word); 2057 $parts = explode(' ', $word); 2058 foreach($parts as $partnr => $part) { 2059 $len = strlen(utf8_decode($part)); 2060 if (!$len) continue; 2061 $parts[$partnr] = preg_replace('/(.{'.ceil($len/ceil($len/$width)).'})(?=.)/u', '$1'.$wbr, $part); 2062 } 2063 $words[$wordnr] = join($wbr, $parts); 2064 } 2065 return join(' ', $words); 2066 } 2067 2068 //------------------------------------------------------------- 2069 function strip_prefix($str, $pfx) { 2070 return preg_replace('/^'.preg_quote($pfx, '/').'/', '', $str); 2071 } 2072 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Feb 18 03:42:45 2008 | Cross-referenced by PHPXref 0.7 |