[ Index ] [ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]

PHP Cross Reference of TXP stable 4.0.6

title

Body

[close]

/textpattern/lib/ -> txplib_misc.php (source)

   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              '&#60;'  => '<',
  37              '&lt;'   => '<',
  38              '&#x3C;' => '<',
  39              '&#62;'  => '>',
  40              '&gt;'   => '>',
  41              '&#x3E;' => '>'
  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                  '<' => '&#60;',
  83                  '>' => '&#62;',
  84                  "'" => '&#39;',
  85                  '"' => '&#34;',
  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                  '<' => '&#60;',
 103                  '>' => '&#62;',
 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&#160;%b&#160;%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              '&#192;'=>'A','&Agrave;'=>'A','&#193;'=>'A','&Aacute;'=>'A','&#194;'=>'A','&Acirc;'=>'A',
 702              '&#195;'=>'A','&Atilde;'=>'A','&#196;'=>'Ae','&Auml;'=>'A','&#197;'=>'A','&Aring;'=>'A',
 703              '&#198;'=>'Ae','&AElig;'=>'AE',
 704              '&#256;'=>'A','&#260;'=>'A','&#258;'=>'A',
 705              '&#199;'=>'C','&Ccedil;'=>'C','&#262;'=>'C','&#268;'=>'C','&#264;'=>'C','&#266;'=>'C',
 706              '&#270;'=>'D','&#272;'=>'D','&#208;'=>'D','&ETH;'=>'D',
 707              '&#200;'=>'E','&Egrave;'=>'E','&#201;'=>'E','&Eacute;'=>'E','&#202;'=>'E','&Ecirc;'=>'E','&#203;'=>'E','&Euml;'=>'E',
 708              '&#274;'=>'E','&#280;'=>'E','&#282;'=>'E','&#276;'=>'E','&#278;'=>'E',
 709              '&#284;'=>'G','&#286;'=>'G','&#288;'=>'G','&#290;'=>'G',
 710              '&#292;'=>'H','&#294;'=>'H',
 711              '&#204;'=>'I','&Igrave;'=>'I','&#205;'=>'I','&Iacute;'=>'I','&#206;'=>'I','&Icirc;'=>'I','&#207;'=>'I','&Iuml;'=>'I',
 712              '&#298;'=>'I','&#296;'=>'I','&#300;'=>'I','&#302;'=>'I','&#304;'=>'I',
 713              '&#306;'=>'IJ',
 714              '&#308;'=>'J',
 715              '&#310;'=>'K',
 716              '&#321;'=>'K','&#317;'=>'K','&#313;'=>'K','&#315;'=>'K','&#319;'=>'K',
 717              '&#209;'=>'N','&Ntilde;'=>'N','&#323;'=>'N','&#327;'=>'N','&#325;'=>'N','&#330;'=>'N',
 718              '&#210;'=>'O','&Ograve;'=>'O','&#211;'=>'O','&Oacute;'=>'O','&#212;'=>'O','&Ocirc;'=>'O','&#213;'=>'O','&Otilde;'=>'O',
 719              '&#214;'=>'Oe','&Ouml;'=>'Oe',
 720              '&#216;'=>'O','&Oslash;'=>'O','&#332;'=>'O','&#336;'=>'O','&#334;'=>'O',
 721              '&#338;'=>'OE',
 722              '&#340;'=>'R','&#344;'=>'R','&#342;'=>'R',
 723              '&#346;'=>'S','&#352;'=>'S','&#350;'=>'S','&#348;'=>'S','&#536;'=>'S',
 724              '&#356;'=>'T','&#354;'=>'T','&#358;'=>'T','&#538;'=>'T',
 725              '&#217;'=>'U','&Ugrave;'=>'U','&#218;'=>'U','&Uacute;'=>'U','&#219;'=>'U','&Ucirc;'=>'U',
 726              '&#220;'=>'Ue','&#362;'=>'U','&Uuml;'=>'Ue',
 727              '&#366;'=>'U','&#368;'=>'U','&#364;'=>'U','&#360;'=>'U','&#370;'=>'U',
 728              '&#372;'=>'W',
 729              '&#221;'=>'Y','&Yacute;'=>'Y','&#374;'=>'Y','&#376;'=>'Y',
 730              '&#377;'=>'Z','&#381;'=>'Z','&#379;'=>'Z',
 731              '&#222;'=>'T','&THORN;'=>'T',
 732              '&#224;'=>'a','&#225;'=>'a','&#226;'=>'a','&#227;'=>'a','&#228;'=>'ae',
 733              '&auml;'=>'ae',
 734              '&#229;'=>'a','&#257;'=>'a','&#261;'=>'a','&#259;'=>'a','&aring;'=>'a',
 735              '&#230;'=>'ae',
 736              '&#231;'=>'c','&#263;'=>'c','&#269;'=>'c','&#265;'=>'c','&#267;'=>'c',
 737              '&#271;'=>'d','&#273;'=>'d','&#240;'=>'d',
 738              '&#232;'=>'e','&#233;'=>'e','&#234;'=>'e','&#235;'=>'e','&#275;'=>'e',
 739              '&#281;'=>'e','&#283;'=>'e','&#277;'=>'e','&#279;'=>'e',
 740              '&#402;'=>'f',
 741              '&#285;'=>'g','&#287;'=>'g','&#289;'=>'g','&#291;'=>'g',
 742              '&#293;'=>'h','&#295;'=>'h',
 743              '&#236;'=>'i','&#237;'=>'i','&#238;'=>'i','&#239;'=>'i','&#299;'=>'i',
 744              '&#297;'=>'i','&#301;'=>'i','&#303;'=>'i','&#305;'=>'i',
 745              '&#307;'=>'ij',
 746              '&#309;'=>'j',
 747              '&#311;'=>'k','&#312;'=>'k',
 748              '&#322;'=>'l','&#318;'=>'l','&#314;'=>'l','&#316;'=>'l','&#320;'=>'l',
 749              '&#241;'=>'n','&#324;'=>'n','&#328;'=>'n','&#326;'=>'n','&#329;'=>'n',
 750              '&#331;'=>'n',
 751              '&#242;'=>'o','&#243;'=>'o','&#244;'=>'o','&#245;'=>'o','&#246;'=>'oe',
 752              '&ouml;'=>'oe',
 753              '&#248;'=>'o','&#333;'=>'o','&#337;'=>'o','&#335;'=>'o',
 754              '&#339;'=>'oe',
 755              '&#341;'=>'r','&#345;'=>'r','&#343;'=>'r',
 756              '&#353;'=>'s',
 757              '&#249;'=>'u','&#250;'=>'u','&#251;'=>'u','&#252;'=>'ue','&#363;'=>'u',
 758              '&uuml;'=>'ue',
 759              '&#367;'=>'u','&#369;'=>'u','&#365;'=>'u','&#361;'=>'u','&#371;'=>'u',
 760              '&#373;'=>'w',
 761              '&#253;'=>'y','&#255;'=>'y','&#375;'=>'y',
 762              '&#382;'=>'z','&#380;'=>'z','&#378;'=>'z',
 763              '&#254;'=>'t',
 764              '&#223;'=>'ss',
 765              '&#383;'=>'ss',
 766              '&agrave;'=>'a','&aacute;'=>'a','&acirc;'=>'a','&atilde;'=>'a','&auml;'=>'ae',
 767              '&aring;'=>'a','&aelig;'=>'ae','&ccedil;'=>'c','&eth;'=>'d',
 768              '&egrave;'=>'e','&eacute;'=>'e','&ecirc;'=>'e','&euml;'=>'e',
 769              '&igrave;'=>'i','&iacute;'=>'i','&icirc;'=>'i','&iuml;'=>'i',
 770              '&ntilde;'=>'n',
 771              '&ograve;'=>'o','&oacute;'=>'o','&ocirc;'=>'o','&otilde;'=>'o','&ouml;'=>'oe',
 772              '&oslash;'=>'o',
 773              '&ugrave;'=>'u','&uacute;'=>'u','&ucirc;'=>'u','&uuml;'=>'ue',
 774              '&yacute;'=>'y','&yuml;'=>'y',
 775              '&thorn;'=>'t',
 776              '&szlig;'=>'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', '&#160;$1', rtrim($str));
 810          return preg_replace('@[ ]+([[:punct:]]?\w+[[:punct:]]?)$@', '&#160;$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('&amp;', $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='&#8203;')
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  ?>


Generated: Mon Feb 18 03:42:45 2008 Cross-referenced by PHPXref 0.7