[ Index ]

PHP Cross Reference of Textpattern 4.0.8

title

Body

[close]

/textpattern/ -> publish.php (source)

   1  <?php
   2  /*
   3              _______________________________________
   4     ________|                                       |_________
   5    \        |                                       |        /
   6     \       |              Textpattern              |       /
   7      \      |                                       |      /
   8      /      |_______________________________________|      \
   9     /___________)                               (___________\
  10  
  11      Copyright 2005 by Dean Allen
  12      All rights reserved.
  13  
  14      Use of this software denotes acceptance of the Textpattern license agreement
  15  
  16  $HeadURL: https://textpattern.googlecode.com/svn/releases/4.0.8/source/textpattern/publish.php $
  17  $LastChangedRevision: 3050 $
  18  
  19  */
  20  
  21      if (!defined('txpath'))
  22          define("txpath", dirname(__FILE__));
  23      if (!defined("txpinterface"))
  24          die('If you just updated and expect to see your site here, please also update the files in your main installation directory.'.
  25              ' (Otherwise note that publish.php cannot be called directly.)');
  26  
  27  
  28      include_once txpath.'/lib/constants.php';
  29      include_once txpath.'/lib/txplib_misc.php';
  30      include_once txpath.'/lib/txplib_db.php';
  31      include_once txpath.'/lib/txplib_html.php';
  32      include_once txpath.'/lib/txplib_forms.php';
  33      include_once txpath.'/lib/admin_config.php';
  34  
  35      include_once txpath.'/publish/taghandlers.php';
  36      include_once txpath.'/publish/log.php';
  37      include_once txpath.'/publish/comment.php';
  38  
  39  //    set_error_handler('myErrorHandler');
  40  
  41      ob_start();
  42  
  43          // start the clock for runtime
  44      $microstart = getmicrotime();
  45  
  46          // initialize parse trace globals
  47      $txptrace        = array();
  48      $txptracelevel   = '';
  49      $txp_current_tag = '';
  50  
  51          // get all prefs as an array
  52      $prefs = get_prefs();
  53  
  54          // add prefs to globals
  55      extract($prefs);
  56  
  57      // check the size of the url request
  58      bombShelter();
  59  
  60          // set a higher error level during initialization
  61      set_error_level(@$production_status == 'live' ? 'testing' : @$production_status);
  62  
  63          // use the current URL path if $siteurl is unknown
  64      if (empty($siteurl))
  65          $prefs['siteurl'] = $siteurl = $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['SCRIPT_NAME']), '/');
  66  
  67      if (empty($path_to_site))
  68          updateSitePath(dirname(dirname(__FILE__)));
  69  
  70      if (!defined('PROTOCOL')) {
  71          switch (serverSet('HTTPS')) {
  72              case '':
  73              case 'off': // ISAPI with IIS
  74                  define('PROTOCOL', 'http://');
  75              break;
  76  
  77              default:
  78                  define('PROTOCOL', 'https://');
  79              break;
  80          }
  81      }
  82  
  83          // v1.0: this should be the definitive http address of the site
  84      if (!defined('hu'))
  85          define("hu",PROTOCOL.$siteurl.'/');
  86  
  87          // v1.0 experimental relative url global
  88      if (!defined('rhu'))
  89          define("rhu",preg_replace("|^https?://[^/]+|","",hu));
  90  
  91          // 1.0: a new $here variable in the top-level index.php
  92          // should let us know the server path to the live site
  93          // let's save it to prefs
  94      if (isset($here) and $path_to_site != $here) updateSitePath($here);
  95  
  96          // 1.0 removed $doc_root variable from config, but we'll
  97          // leave it here for a bit until plugins catch up
  98      $txpcfg['doc_root'] = @$_SERVER['DOCUMENT_ROOT'];
  99      // work around the IIS lobotomy
 100      if (empty($txpcfg['doc_root']))
 101          $txpcfg['doc_root'] = @$_SERVER['PATH_TRANSLATED'];
 102  
 103      if (!defined('LANG'))
 104          define("LANG",$language);
 105      if (!empty($locale)) setlocale(LC_ALL, $locale);
 106  
 107          //Initialize the current user
 108      $txp_user = NULL;
 109  
 110          //i18n: $textarray = load_lang('en-gb');
 111      $textarray = load_lang(LANG);
 112  
 113          // here come the plugins
 114      if ($use_plugins) load_plugins();
 115  
 116          // this step deprecated as of 1.0 : really only useful with old-style
 117          // section placeholders, which passed $s='section_name'
 118      $s = (empty($s)) ? '' : $s;
 119  
 120      $pretext = !isset($pretext) ? array() : $pretext;
 121      $pretext = array_merge($pretext, pretext($s,$prefs));
 122      callback_event('pretext_end');
 123      extract($pretext);
 124  
 125      // Now that everything is initialized, we can crank down error reporting
 126      set_error_level($production_status);
 127  
 128      if (gps('parentid') && gps('submit')) {
 129          saveComment();
 130      } elseif (gps('parentid') and $comments_mode==1) { // popup comments?
 131          header("Content-type: text/html; charset=utf-8");
 132          exit(popComments(gps('parentid')));
 133      }
 134  
 135      // we are dealing with a download
 136      if (@$s == 'file_download') {
 137          callback_event('file_download');
 138          if (!isset($file_error)) {
 139  
 140                  $fullpath = build_file_path($file_base_path,$filename);
 141  
 142                  if (is_file($fullpath)) {
 143  
 144                      // discard any error php messages
 145                      ob_clean();
 146                      $filesize = filesize($fullpath); $sent = 0;
 147                      header('Content-Description: File Download');
 148                      header('Content-Type: application/octet-stream');
 149                      header('Content-Disposition: attachment; filename="' . basename($filename) . '"; size = "'.$filesize.'"');
 150                      // Fix for lame IE 6 pdf bug on servers configured to send cache headers
 151                      header('Cache-Control: private');
 152                      @ini_set("zlib.output_compression", "Off");
 153                      @set_time_limit(0);
 154                      @ignore_user_abort(true);
 155                      if ($file = fopen($fullpath, 'rb')) {
 156                          while(!feof($file) and (connection_status()==0)) {
 157                              echo fread($file, 1024*64); $sent+=(1024*64);
 158                              ob_flush();
 159                              flush();
 160                          }
 161                          fclose($file);
 162                          // record download
 163                          if ((connection_status()==0) and !connection_aborted() ) {
 164                              safe_update("txp_file", "downloads=downloads+1", 'id='.intval($id));
 165                              log_hit('200');
 166                          } else {
 167                              $pretext['request_uri'] .= ($sent >= $filesize)
 168                                  ? '#aborted'
 169                                  : "#aborted-at-".floor($sent*100/$filesize)."%";
 170                              log_hit('200');
 171                          }
 172                      }
 173                  } else {
 174                      $file_error = 404;
 175                  }
 176          }
 177  
 178          // deal with error
 179          if (isset($file_error)) {
 180              switch($file_error) {
 181              case 403:
 182                  txp_die(gTxt('403_forbidden'), '403');
 183                  break;
 184              case 404:
 185                  txp_die(gTxt('404_not_found'), '404');
 186                  break;
 187              default:
 188                  txp_die(gTxt('500_internal_server_error'), '500');
 189                  break;
 190              }
 191          }
 192  
 193          // download done
 194          exit(0);
 195      }
 196  
 197  
 198      // send 304 Not Modified if appropriate
 199      handle_lastmod();
 200  
 201      // log the page view
 202      log_hit($status);
 203  
 204  
 205  // -------------------------------------------------------------
 206  	function preText($s,$prefs)
 207      {
 208          extract($prefs);
 209  
 210          callback_event('pretext');
 211  
 212          if(gps('rss')) {
 213              include txpath.'/publish/rss.php';
 214              exit(rss());
 215          }
 216  
 217          if(gps('atom')) {
 218              include txpath.'/publish/atom.php';
 219              exit(atom());
 220          }
 221              // set messy variables
 222          $out =  makeOut('id','s','c','q','pg','p','month','author');
 223  
 224              // some useful vars for taghandlers, plugins
 225          $out['request_uri'] = preg_replace("|^https?://[^/]+|i","",serverSet('REQUEST_URI'));
 226          $out['qs'] = serverSet('QUERY_STRING');
 227              // IIS fix
 228          if (!$out['request_uri'] and serverSet('SCRIPT_NAME'))
 229              $out['request_uri'] = serverSet('SCRIPT_NAME').( (serverSet('QUERY_STRING')) ? '?'.serverSet('QUERY_STRING') : '');
 230              // another IIS fix
 231          if (!$out['request_uri'] and serverSet('argv'))
 232          {
 233              $argv = serverSet('argv');
 234              $out['request_uri'] = @substr($argv[0], strpos($argv[0], ';') + 1);
 235          }
 236  
 237              // define the useable url, minus any subdirectories.
 238              // this is pretty fugly, if anyone wants to have a go at it - dean
 239          $out['subpath'] = $subpath = preg_quote(preg_replace("/https?:\/\/.*(\/.*)/Ui","$1",hu),"/");
 240          $out['req'] = $req = preg_replace("/^$subpath/i","/",$out['request_uri']);
 241  
 242          $is_404 = 0;
 243  
 244              // if messy vars exist, bypass url parsing
 245          if (!$out['id'] && !$out['s'] && !(txpinterface=='css') &&! ( txpinterface=='admin') ) {
 246  
 247              // return clean URL test results for diagnostics
 248              if (gps('txpcleantest')) {
 249                  exit(show_clean_test($out));
 250              }
 251  
 252              extract(chopUrl($req));
 253  
 254                  //first we sniff out some of the preset url schemes
 255              if (strlen($u1)) {
 256  
 257                  switch($u1) {
 258  
 259                      case 'atom':
 260                          include txpath.'/publish/atom.php'; exit(atom());
 261  
 262                      case 'rss':
 263                          include txpath.'/publish/rss.php'; exit(rss());
 264  
 265                      // urldecode(strtolower(urlencode())) looks ugly but is the only way to
 266                      // make it multibyte-safe without breaking backwards-compatibility
 267                      case urldecode(strtolower(urlencode(gTxt('section')))):
 268                          $out['s'] = (ckEx('section',$u2)) ? $u2 : ''; $is_404 = empty($out['s']); break;
 269  
 270                      case urldecode(strtolower(urlencode(gTxt('category')))):
 271                          $out['c'] = (ckEx('category',$u2)) ? $u2 : ''; $is_404 = empty($out['c']); break;
 272  
 273                      case urldecode(strtolower(urlencode(gTxt('author')))):
 274                          $out['author'] = (!empty($u2)) ? $u2 : ''; break;
 275                          // AuthorID gets resolved from Name further down
 276  
 277                      case urldecode(strtolower(urlencode(gTxt('file_download')))):
 278                          $out['s'] = 'file_download';
 279                          $out['id'] = (!empty($u2)) ? $u2 : ''; break;
 280  
 281                      default:
 282                          // then see if the prefs-defined permlink scheme is usable
 283                          switch ($permlink_mode) {
 284  
 285                              case 'section_id_title':
 286                                  if (empty($u2)) {
 287                                      $out['s'] = (ckEx('section',$u1)) ? $u1 : '';
 288                                      $is_404 = empty($out['s']);
 289                                  }
 290                                  else {
 291                                      $rs = lookupByIDSection($u2, $u1);
 292                                      $out['s'] = @$rs['Section'];
 293                                      $out['id'] = @$rs['ID'];
 294                                      $is_404 = (empty($out['s']) or empty($out['id']));
 295                                  }
 296                              break;
 297  
 298                              case 'year_month_day_title':
 299                                  if (empty($u2)) {
 300                                      $out['s'] = (ckEx('section',$u1)) ? $u1 : '';
 301                                      $is_404 = empty($out['s']);
 302                                  }
 303                                  elseif (empty($u4)){
 304                                      $month = "$u1-$u2";
 305                                      if (!empty($u3)) $month.= "-$u3";
 306                                      if (preg_match('/\d+-\d+(?:-\d+)?/', $month)) {
 307                                          $out['month'] = $month;
 308                                          $out['s'] = 'default';
 309                                      }
 310                                      else {
 311                                          $is_404 = 1;
 312                                      }
 313                                  }else{
 314                                      $when = "$u1-$u2-$u3";
 315                                      $rs = lookupByDateTitle($when,$u4);
 316                                      $out['id'] = (!empty($rs['ID'])) ? $rs['ID'] : '';
 317                                      $out['s'] = (!empty($rs['Section'])) ? $rs['Section'] : '';
 318                                      $is_404 = (empty($out['s']) or empty($out['id']));
 319                                  }
 320                              break;
 321  
 322                              case 'section_title':
 323                                  if (empty($u2)) {
 324                                      $out['s'] = (ckEx('section',$u1)) ? $u1 : '';
 325                                      $is_404 = empty($out['s']);
 326                                  }
 327                                  else {
 328                                      $rs = lookupByTitleSection($u2,$u1);
 329                                      $out['id'] = @$rs['ID'];
 330                                      $out['s'] = @$rs['Section'];
 331                                      $is_404 = (empty($out['s']) or empty($out['id']));
 332                                  }
 333                              break;
 334  
 335                              case 'title_only':
 336                                  $rs = lookupByTitle($u1);
 337                                  $out['id'] = @$rs['ID'];
 338                                  $out['s'] = (empty($rs['Section']) ? ckEx('section', $u1) :
 339                                          $rs['Section']);
 340                                  $is_404 = empty($out['s']);
 341                              break;
 342  
 343                              case 'id_title':
 344                                  if (is_numeric($u1) && ckExID($u1))
 345                                  {
 346                                      $rs = lookupByID($u1);
 347                                      $out['id'] = (!empty($rs['ID'])) ? $rs['ID'] : '';
 348                                      $out['s'] = (!empty($rs['Section'])) ? $rs['Section'] : '';
 349                                      $is_404 = (empty($out['s']) or empty($out['id']));
 350                                  }else{
 351                                      # We don't want to miss the /section/ pages
 352                                      $out['s']= ckEx('section',$u1)? $u1 : '';
 353                                      $is_404 = empty($out['s']);
 354                                  }
 355                              break;
 356  
 357                          }
 358                  }
 359              } else {
 360                  $out['s'] = 'default';
 361              }
 362          }
 363          else {
 364              // Messy mode, but prevent to get the id for file_downloads
 365              if ($out['id'] && !$out['s']) {
 366                  $rs = lookupByID($out['id']);
 367                  $out['id'] = (!empty($rs['ID'])) ? $rs['ID'] : '';
 368                  $out['s'] = (!empty($rs['Section'])) ? $rs['Section'] : '';
 369                  $is_404 = (empty($out['s']) or empty($out['id']));
 370              }
 371          }
 372  
 373          // Resolve AuthorID from Authorname
 374          if ($out['author'])
 375          {
 376              $name = urldecode(strtolower(urlencode($out['author'])));
 377  
 378              $name = safe_field('name', 'txp_users', "RealName like '".doSlash($out['author'])."'");
 379  
 380              if ($name)
 381              {
 382                  $out['author'] = $name;
 383              }
 384  
 385              else
 386              {
 387                  $out['author'] = '';
 388                  $is_404 = true;
 389              }
 390          }
 391  
 392          // allow article preview
 393          if (gps('txpreview') and is_logged_in())
 394          {
 395              global $nolog;
 396  
 397              $nolog = true;
 398              $rs = safe_row("ID as id,Section as s",'textpattern','ID = '.intval(gps('txpreview')).' limit 1');
 399  
 400              if ($rs and $is_404)
 401              {
 402                  $is_404 = false;
 403                  $out = array_merge($out, $rs);
 404              }
 405          }
 406  
 407          // Stats: found or not
 408          $out['status'] = ($is_404 ? '404' : '200');
 409  
 410          $out['pg'] = is_numeric($out['pg']) ? intval($out['pg']) : '';
 411          $out['id'] = is_numeric($out['id']) ? intval($out['id']) : '';
 412  
 413          if ($out['s'] == 'file_download') {
 414              // get id of potential filename
 415              if (!is_numeric($out['id'])) {
 416                  $rs = safe_row("*", "txp_file", "filename='".doSlash($out['id'])."' and status = 4");
 417              } else {
 418                  $rs = safe_row("*", "txp_file", 'id='.intval($out['id']).' and status = 4');
 419              }
 420  
 421              $out = ($rs)? array_merge($out, $rs) : array('s'=>'file_download','file_error'=> 404);
 422              return $out;
 423          }
 424  
 425          if (!$is_404)
 426              $out['s'] = (empty($out['s'])) ? 'default' : $out['s'];
 427          $s = $out['s'];
 428          $id = $out['id'];
 429  
 430          // hackish
 431          global $is_article_list;
 432          if(empty($id)) $is_article_list = true;
 433  
 434              // by this point we should know the section, so grab its page and css
 435          $rs = safe_row("page, css", "txp_section", "name = '".doSlash($s)."' limit 1");
 436          $out['page'] = @$rs['page'];
 437          $out['css'] = @$rs['css'];
 438  
 439          if(is_numeric($id) and !$is_404) {
 440              $a = safe_row('*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod', 'textpattern', 'ID='.intval($id).(gps('txpreview') ? '' : ' and Status in (4,5)'));
 441              if ($a) {
 442                  $Posted             = $a['Posted'];
 443                  $out['id_keywords'] = $a['Keywords'];
 444                  $out['id_author']   = $a['AuthorID'];
 445                  populateArticleData($a);
 446                  
 447                  $uExpires = $a['uExpires'];
 448                  if ($uExpires and time() > $uExpires and !$publish_expired_articles) {
 449                      $out['status'] = '410';
 450                  }
 451  
 452                  if ($np = getNextPrev($id, $Posted, $s))
 453                      $out = array_merge($out, $np);
 454              }
 455          }
 456  
 457          $out['path_from_root'] = rhu; // these are deprecated as of 1.0
 458          $out['pfr']            = rhu; // leaving them here for plugin compat
 459  
 460          $out['path_to_site']   = $path_to_site;
 461          $out['permlink_mode']  = $permlink_mode;
 462          $out['sitename']       = $sitename;
 463  
 464          return $out;
 465  
 466      }
 467  
 468  //    textpattern() is the function that assembles a page, based on
 469  //    the variables passed to it by pretext();
 470  
 471  // -------------------------------------------------------------
 472  	function textpattern()
 473      {
 474          global $pretext,$microstart,$prefs,$qcount,$qtime,$production_status,$txptrace,$siteurl,$has_article_tag;
 475  
 476          $has_article_tag = false;
 477  
 478          callback_event('textpattern');
 479  
 480          if ($pretext['status'] == '404')
 481              txp_die(gTxt('404_not_found'), '404');
 482  
 483          if ($pretext['status'] == '410')
 484              txp_die(gTxt('410_gone'), '410');
 485  
 486          $html = safe_field('user_html','txp_page',"name='".doSlash($pretext['page'])."'");
 487          if (!$html)
 488              txp_die(gTxt('unknown_section'), '404');
 489  
 490          // useful for clean urls with error-handlers
 491          txp_status_header('200 OK');
 492  
 493          trace_add('['.gTxt('page').': '.$pretext['page'].']');
 494          set_error_handler("tagErrorHandler");
 495          $pretext['secondpass'] = false;
 496          $html = parse($html);
 497          $pretext['secondpass'] = true;
 498          trace_add('[ ~~~ '.gTxt('secondpass').' ~~~ ]');
 499          $html = parse($html); // the function so nice, he ran it twice
 500          if ($prefs['allow_page_php_scripting']) $html = evalString($html);
 501  
 502          // make sure the page has an article tag if necessary
 503          if (!$has_article_tag and $production_status != 'live' and (!empty($pretext['id']) or !empty($pretext['c']) or !empty($pretext['q']) or !empty($pretext['pg'])))
 504              trigger_error(gTxt('missing_article_tag', array('{page}' => $pretext['page'])));
 505          restore_error_handler();
 506  
 507          header("Content-type: text/html; charset=utf-8");
 508          echo $html;
 509  
 510          if (in_array($production_status, array('debug', 'testing'))) {
 511              $microdiff = (getmicrotime() - $microstart);
 512              echo n,comment('Runtime:    '.substr($microdiff,0,6));
 513              echo n,comment('Query time: '.sprintf('%02.6f', $qtime));
 514              echo n,comment('Queries: '.$qcount);
 515              echo maxMemUsage('end of textpattern()',1);
 516              if (!empty($txptrace) and is_array($txptrace))
 517                  echo n, comment('txp tag trace: '.n.str_replace('--','&shy;&shy;',join(n, $txptrace)).n);
 518                  // '&shy;&shy;' is *no* tribute to Kajagoogoo, but an attempt to avoid prematurely terminating HTML comments
 519          }
 520  
 521          callback_event('textpattern_end');
 522      }
 523  
 524  // -------------------------------------------------------------
 525  	function output_css($s='',$n='')
 526      {
 527          if ($n) {
 528              $cssname = $n;
 529          } elseif ($s) {
 530              $cssname = safe_field('css','txp_section',"name='".doSlash($s)."'");
 531          }
 532  
 533          $css = safe_field('css','txp_css',"name='".doSlash($cssname)."'");
 534          if ($css) echo base64_decode($css);
 535      }
 536  
 537  //    article() is called when parse() finds a <txp:article /> tag.
 538  //    If an $id has been established, we output a single article,
 539  //    otherwise, output a list.
 540  
 541  // -------------------------------------------------------------
 542  	function article($atts, $thing = NULL)
 543      {
 544          global $is_article_body, $has_article_tag;
 545          if ($is_article_body) {
 546              trigger_error(gTxt('article_tag_illegal_body'));
 547              return '';
 548          }
 549          $has_article_tag = true;
 550          return parseArticles($atts, '0', $thing);
 551      }
 552  
 553  // -------------------------------------------------------------
 554  	function doArticles($atts, $iscustom, $thing = NULL)
 555      {
 556          global $pretext, $prefs;
 557          extract($pretext);
 558          extract($prefs);
 559          $customFields = getCustomFields();
 560          $customlAtts = array_null(array_flip($customFields));
 561  
 562          //getting attributes
 563          $theAtts = lAtts(array(
 564              'form'      => 'default',
 565              'listform'  => '',
 566              'searchform'=> '',
 567              'limit'     => 10,
 568              'pageby'    => '',
 569              'category'  => '',
 570              'section'   => '',
 571              'excerpted' => '',
 572              'author'    => '',
 573              'sort'      => '',
 574              'sortby'    => '',
 575              'sortdir'   => '',
 576              'month'     => '',
 577              'keywords'  => '',
 578              'frontpage' => '',
 579              'id'        => '',
 580              'time'      => 'past',
 581              'status'    => '4',
 582              'pgonly'    => 0,
 583              'searchall' => 1,
 584              'searchsticky' => 0,
 585              'allowoverride' => (!$q and !$iscustom),
 586              'offset'    => 0,
 587              'wraptag'    => '',
 588              'break'        => '',
 589              'label'        => '',
 590              'labeltag'    => '',
 591              'class'        => ''
 592          )+$customlAtts,$atts);
 593  
 594          // if an article ID is specified, treat it as a custom list
 595          $iscustom = (!empty($theAtts['id'])) ? true : $iscustom;
 596  
 597          //for the txp:article tag, some attributes are taken from globals;
 598          //override them before extract
 599          if (!$iscustom)
 600          {
 601              $theAtts['category'] = ($c)? $c : '';
 602              $theAtts['section'] = ($s && $s!='default')? $s : '';
 603              $theAtts['author'] = (!empty($author)? $author: '');
 604              $theAtts['month'] = (!empty($month)? $month: '');
 605              $theAtts['frontpage'] = ($s && $s=='default')? true: false;
 606              $theAtts['excerpted'] = '';
 607          }
 608          extract($theAtts);
 609  
 610          // if a listform is specified, $thing is for doArticle() - hence ignore here.
 611          if (!empty($listform)) $thing = '';
 612  
 613          $pageby = (empty($pageby) ? $limit : $pageby);
 614  
 615          // treat sticky articles differently wrt search filtering, etc
 616          $status = in_array(strtolower($status), array('sticky', '5')) ? 5 : 4;
 617          $issticky = ($status == 5);
 618  
 619          // give control to search, if necessary
 620          if ($q && !$iscustom && !$issticky)
 621          {
 622              include_once txpath.'/publish/search.php';
 623  
 624              $s_filter = ($searchall ? filterSearch() : '');
 625              $q = doSlash($q);
 626  
 627                      // searchable article fields are limited to the columns of 
 628                      // the textpattern table and a matching fulltext index must exist.
 629              $cols = do_list($searchable_article_fields);
 630              if (empty($cols) or $cols[0] == '') $cols = array('Title', 'Body');
 631  
 632              $match = ', match (`'.join('`, `', $cols)."`) against ('$q') as score";
 633              for ($i = 0; $i < count($cols); $i++)
 634              {
 635                  $cols[$i] = "`$cols[$i]` rlike '$q'";
 636              }            
 637              $cols = join(" or ", $cols);
 638              $search = " and ($cols) $s_filter";
 639              
 640              // searchall=0 can be used to show search results for the current section only
 641              if ($searchall) $section = '';
 642              if (!$sort) $sort = 'score desc';
 643          }
 644          else {
 645              $match = $search = '';
 646              if (!$sort) $sort = 'Posted desc';
 647          }
 648  
 649          // for backwards compatibility
 650          // sortby and sortdir are deprecated
 651          if ($sortby)
 652          {
 653              if (!$sortdir)
 654              {
 655                  $sortdir = 'desc';
 656              }
 657  
 658              $sort = "$sortby $sortdir";
 659          }
 660  
 661          elseif ($sortdir)
 662          {
 663              $sort = "Posted $sortdir";
 664          }
 665  
 666          //Building query parts
 667          $frontpage = ($frontpage and (!$q or $issticky)) ? filterFrontPage() : '';
 668          $category  = join("','", doSlash(do_list($category)));
 669          $category  = (!$category)  ? '' : " and (Category1 IN ('".$category."') or Category2 IN ('".$category."'))";
 670          $section   = (!$section)   ? '' : " and Section IN ('".join("','", doSlash(do_list($section)))."')";
 671          $excerpted = ($excerpted=='y')  ? " and Excerpt !=''" : '';
 672          $author    = (!$author)    ? '' : " and AuthorID IN ('".join("','", doSlash(do_list($author)))."')";
 673          $month     = (!$month)     ? '' : " and Posted like '".doSlash($month)."%'";
 674          $id        = (!$id)        ? '' : " and ID IN (".join(',', array_map('intval', do_list($id))).")";
 675          switch ($time) {
 676              case 'any':
 677                  $time = ""; break;
 678              case 'future':
 679                  $time = " and Posted > now()"; break;
 680              default:
 681                  $time = " and Posted <= now()";
 682          }        
 683          if (!$publish_expired_articles) {
 684              $time .= " and (now() <= Expires or Expires = ".NULLDATETIME.")";
 685          }
 686  
 687          $custom = '';
 688  
 689          if ($customFields) {
 690              foreach($customFields as $cField) {
 691                  if (isset($atts[$cField]))
 692                      $customPairs[$cField] = $atts[$cField];
 693              }
 694              if(!empty($customPairs)) {
 695                  $custom = buildCustomSql($customFields,$customPairs);
 696              }
 697          }
 698  
 699          //Allow keywords for no-custom articles. That tagging mode, you know
 700          if ($keywords) {
 701              $keys = doSlash(do_list($keywords));
 702              foreach ($keys as $key) {
 703                  $keyparts[] = "FIND_IN_SET('".$key."',Keywords)";
 704              }
 705              $keywords = " and (" . join(' or ',$keyparts) . ")";
 706          }
 707  
 708          if ($q and $searchsticky)
 709              $statusq = ' and Status >= 4';
 710          elseif ($id)
 711              $statusq = ' and Status >= 4';
 712          else
 713              $statusq = ' and Status = '.intval($status);
 714  
 715          $where = "1=1" . $statusq. $time.
 716              $search . $id . $category . $section . $excerpted . $month . $author . $keywords . $custom . $frontpage;
 717  
 718          //do not paginate if we are on a custom list
 719          if (!$iscustom and !$issticky)
 720          {
 721              $grand_total = safe_count('textpattern',$where);
 722              $total = $grand_total - $offset;
 723              $numPages = ceil($total/$pageby);
 724              $pg = (!$pg) ? 1 : $pg;
 725              $pgoffset = $offset + (($pg - 1) * $pageby);
 726              // send paging info to txp:newer and txp:older
 727              $pageout['pg']       = $pg;
 728              $pageout['numPages'] = $numPages;
 729              $pageout['s']        = $s;
 730              $pageout['c']        = $c;
 731              $pageout['grand_total'] = $grand_total;
 732              $pageout['total']    = $total;
 733  
 734              global $thispage;
 735              if (empty($thispage))
 736                  $thispage = $pageout;
 737              if ($pgonly)
 738                  return;
 739          }else{
 740              $pgoffset = $offset;
 741          }
 742  
 743          $rs = safe_rows_start("*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod".$match, 'textpattern',
 744          $where.' order by '.doSlash($sort).' limit '.intval($pgoffset).', '.intval($limit));
 745          // get the form name
 746          if ($q and !$iscustom and !$issticky)
 747              $fname = ($searchform ? $searchform : 'search_results');
 748          else
 749              $fname = ($listform ? $listform : $form);
 750  
 751          if ($rs) {
 752              $count = 0;
 753              $last = numRows($rs);
 754  
 755              $articles = array();
 756              while($a = nextRow($rs)) {
 757                  ++$count;
 758                  populateArticleData($a);
 759                  global $thisarticle, $uPosted, $limit;
 760                  $thisarticle['is_first'] = ($count == 1);
 761                  $thisarticle['is_last'] = ($count == $last);
 762  
 763                  if (@constant('txpinterface') === 'admin' and gps('Form')) {
 764                      $articles[] = parse(gps('Form'));
 765                  }
 766                  elseif ($allowoverride and $a['override_form']) {
 767                      $articles[] = parse_form($a['override_form']);
 768                  }
 769                  else {
 770                      $articles[] = ($thing) ? parse($thing) : parse_form($fname);
 771                  }
 772  
 773                  // sending these to paging_link(); Required?
 774                  $uPosted = $a['uPosted'];
 775  
 776                  unset($GLOBALS['thisarticle']);
 777              }
 778  
 779              return doLabel($label, $labeltag).doWrap($articles, $wraptag, $break, $class);
 780          }
 781      }
 782  
 783  // -------------------------------------------------------------
 784  
 785  	function filterFrontPage()
 786      {
 787          static $filterFrontPage;
 788  
 789          if (isset($filterFrontPage)) {
 790              return $filterFrontPage;
 791          }
 792  
 793          $filterFrontPage = false;
 794  
 795          $rs = safe_column('name', 'txp_section', "on_frontpage != '1'");
 796  
 797          if ($rs) {
 798              $filters = array();
 799  
 800              foreach ($rs as $name) {
 801                  $filters[] = " and Section != '".doSlash($name)."'";
 802              }
 803  
 804              $filterFrontPage = join('', $filters);
 805          }
 806  
 807          return $filterFrontPage;
 808      }
 809  
 810  // -------------------------------------------------------------
 811  	function doArticle($atts, $thing = NULL)
 812      {
 813          global $pretext,$prefs, $thisarticle;
 814          extract($prefs);
 815          extract($pretext);
 816  
 817          extract(gpsa(array('parentid', 'preview')));
 818  
 819          extract(lAtts(array(
 820              'allowoverride' => '1',
 821              'form'          => 'default',
 822              'status'        => '4',
 823          ),$atts, 0));
 824  
 825          // if a form is specified, $thing is for doArticles() - hence ignore $thing here.
 826          if (!empty($atts['form'])) $thing = '';
 827  
 828          if ($status)
 829          {
 830              $status = in_array(strtolower($status), array('sticky', '5')) ? 5 : 4;
 831          }
 832  
 833          if (empty($thisarticle) or $thisarticle['thisid'] != $id)
 834          {
 835              $thisarticle = NULL;
 836  
 837              $q_status = ($status ? 'and Status = '.intval($status) : 'and Status in (4,5)');
 838  
 839              $rs = safe_row("*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod",
 840                      "textpattern", 'ID = '.intval($id)." $q_status limit 1");
 841  
 842              if ($rs) {
 843                  extract($rs);
 844                  populateArticleData($rs);
 845              }
 846          }
 847  
 848          if (!empty($thisarticle) and ($thisarticle['status'] == $status or gps('txpreview')))
 849          {
 850              extract($thisarticle);
 851              $thisarticle['is_first'] = 1;
 852              $thisarticle['is_last'] = 1;
 853  
 854              if ($allowoverride and $override_form)
 855              {
 856                  $article = parse_form($override_form);
 857              }
 858              else
 859              {
 860                  $article = ($thing) ? parse($thing) : parse_form($form);
 861              }
 862  
 863              if ($use_comments and $comments_auto_append)
 864              {
 865                  $article .= parse_form('comments_display');
 866              }
 867  
 868              unset($GLOBALS['thisarticle']);
 869  
 870              return $article;
 871          }
 872      }
 873  
 874  // -------------------------------------------------------------
 875  	function article_custom($atts, $thing = NULL)
 876      {
 877          return parseArticles($atts, '1', $thing);
 878      }
 879  
 880  // -------------------------------------------------------------
 881  	function parseArticles($atts, $iscustom = 0, $thing = NULL)
 882      {
 883          global $pretext, $is_article_list;
 884          $old_ial = $is_article_list;
 885          $is_article_list = ($pretext['id'] && !$iscustom)? false : true;
 886          article_push();
 887          $r = ($is_article_list)? doArticles($atts, $iscustom, $thing) : doArticle($atts, $thing);
 888          article_pop();
 889          $is_article_list = $old_ial;
 890  
 891          return $r;
 892      }
 893  
 894  // -------------------------------------------------------------
 895  // Keep all the article tag-related values in one place,
 896  // in order to do easy bugfix and easily the addition of
 897  // new article tags.
 898  	function populateArticleData($rs)
 899      {
 900          global $thisarticle;
 901          extract($rs);
 902  
 903          trace_add("[".gTxt('Article')." $ID]");
 904          $thisarticle['thisid']          = $ID;
 905          $thisarticle['posted']          = $uPosted;
 906          $thisarticle['expires']         = $uExpires;
 907          $thisarticle['modified']        = $uLastMod;
 908          $thisarticle['annotate']        = $Annotate;
 909          $thisarticle['comments_invite'] = $AnnotateInvite;
 910          $thisarticle['authorid']        = $AuthorID;
 911          $thisarticle['title']           = $Title;
 912          $thisarticle['url_title']       = $url_title;
 913          $thisarticle['category1']       = $Category1;
 914          $thisarticle['category2']       = $Category2;
 915          $thisarticle['section']         = $Section;
 916          $thisarticle['keywords']        = $Keywords;
 917          $thisarticle['article_image']   = $Image;
 918          $thisarticle['comments_count']  = $comments_count;
 919          $thisarticle['body']            = $Body_html;
 920          $thisarticle['excerpt']         = $Excerpt_html;
 921          $thisarticle['override_form']   = $override_form;
 922          $thisarticle['status']          = $Status;
 923  
 924          $custom = getCustomFields();
 925          if ($custom) {
 926              foreach ($custom as $i => $name)
 927                  $thisarticle[$name] = $rs['custom_' . $i];
 928          }
 929  
 930      }
 931  
 932  // -------------------------------------------------------------
 933  	function getNeighbour($Posted, $s, $type)
 934      {
 935          global $prefs;
 936          extract($prefs);
 937          $expired = ($publish_expired_articles) ? '' : ' and (now() <= Expires or Expires = '.NULLDATETIME.')';
 938          $type = ($type == '>') ? '>' : '<';
 939          $safe_name = safe_pfx('textpattern');
 940          $q = array(
 941              "select ID, Title, url_title, unix_timestamp(Posted) as uposted
 942              from ".$safe_name." where Posted $type '".doSlash($Posted)."'",
 943              ($s!='' && $s!='default') ? "and Section = '".doSlash($s)."'" : filterFrontPage(),
 944              'and Status=4 and Posted < now()'.$expired.' order by Posted',
 945              ($type=='<') ? 'desc' : 'asc',
 946              'limit 1'
 947          );
 948  
 949          $out = getRow(join(' ',$q));
 950          return (is_array($out)) ? $out : '';
 951      }
 952  
 953  // -------------------------------------------------------------
 954  	function getNextPrev($id, $Posted, $s)
 955      {
 956          static $next, $cache;
 957  
 958          if (@isset($cache[$next[$id]]))
 959              $thenext = $cache[$next[$id]];
 960          else
 961              $thenext            = getNeighbour($Posted,$s,'>');
 962  
 963          $out['next_id']     = ($thenext) ? $thenext['ID'] : '';
 964          $out['next_title']  = ($thenext) ? $thenext['Title'] : '';
 965          $out['next_utitle'] = ($thenext) ? $thenext['url_title'] : '';
 966          $out['next_posted'] = ($thenext) ? $thenext['uposted'] : '';
 967  
 968          $theprev            = getNeighbour($Posted,$s,'<');
 969          $out['prev_id']     = ($theprev) ? $theprev['ID'] : '';
 970          $out['prev_title']  = ($theprev) ? $theprev['Title'] : '';
 971          $out['prev_utitle'] = ($theprev) ? $theprev['url_title'] : '';
 972          $out['prev_posted'] = ($theprev) ? $theprev['uposted'] : '';
 973  
 974          if ($theprev) {
 975              $cache[$theprev['ID']] = $theprev;
 976              $next[$theprev['ID']] = $id;
 977          }
 978  
 979          return $out;
 980      }
 981  
 982  // -------------------------------------------------------------
 983  	function lastMod()
 984      {
 985          $last = safe_field("unix_timestamp(val)", "txp_prefs", "`name`='lastmod' and prefs_id=1");
 986          return gmdate("D, d M Y H:i:s \G\M\T",$last);
 987      }
 988  
 989  // -------------------------------------------------------------
 990  	function parse($thing)
 991      {
 992          $f = '@(</?txp:\w+(?:\s+\w+\s*=\s*(?:"(?:[^"]|"")*"|\'(?:[^\']|\'\')*\'|[^\s\'"/>]+))*\s*/?'.chr(62).')@s';
 993          $t = '@:(\w+)(.*?)/?.$@s';
 994  
 995          $parsed = preg_split($f, $thing, -1, PREG_SPLIT_DELIM_CAPTURE);
 996  
 997          $level  = 0;
 998          $out    = '';
 999          $inside = '';
1000          $istag  = FALSE;
1001  
1002          foreach ($parsed as $chunk)
1003          {
1004              if ($istag)
1005              {
1006                  if ($level === 0)
1007                  {
1008                      preg_match($t, $chunk, $tag);
1009  
1010                      if (substr($chunk, -2, 1) === '/')
1011                      { # self closing
1012                          $out .= processTags($tag[1], $tag[2]);
1013                      }
1014                      else
1015                      { # opening
1016                          $level++;
1017                      }
1018                  }
1019                  else
1020                  {
1021                      if (substr($chunk, 1, 1) === '/')
1022                      { # closing
1023                          if (--$level === 0)
1024                          {
1025                              $out  .= processTags($tag[1], $tag[2], $inside);
1026                              $inside = '';
1027                          }
1028                          else
1029                          {
1030                              $inside .= $chunk;
1031                          }
1032                      }
1033                      elseif (substr($chunk, -2, 1) !== '/')
1034                      { # opening inside open
1035                          ++$level;
1036                          $inside .= $chunk;
1037                      }
1038                      else
1039                      {
1040                          $inside .= $chunk;
1041                      }
1042                  }
1043              }
1044              else
1045              {
1046                  if ($level)
1047                  {
1048                      $inside .= $chunk;
1049                  }
1050                  else
1051                  {
1052                      $out .= $chunk;
1053                  }
1054              }
1055  
1056              $istag = !$istag;
1057          }
1058  
1059          return $out;
1060      }
1061  
1062  // -------------------------------------------------------------
1063  
1064  	function processTags($tag, $atts, $thing = NULL)
1065      {
1066          global $production_status, $txptrace, $txptracelevel, $txp_current_tag;
1067  
1068          if ($production_status !== 'live')
1069          {
1070              $old_tag = $txp_current_tag;
1071  
1072              $txp_current_tag = '<txp:'.$tag.$atts.(isset($thing) ? '>' : '/>');
1073  
1074              trace_add($txp_current_tag);
1075              ++$txptracelevel;
1076  
1077              if ($production_status === 'debug')
1078              {
1079                  maxMemUsage($txp_current_tag);
1080              }
1081          }
1082  
1083          if ($tag === 'link')
1084          {
1085              $tag = 'tpt_'.$tag;
1086          }
1087  
1088          if (function_exists($tag))
1089          {
1090              $out = $tag(splat($atts), $thing);
1091          }
1092  
1093          // deprecated, remove in crockery
1094          elseif (isset($GLOBALS['pretext'][$tag]))
1095          {
1096              $out = htmlspecialchars($pretext[$tag]);
1097  
1098              trigger_error(gTxt('deprecated_tag'), E_USER_NOTICE);
1099          }
1100  
1101          else
1102          {
1103              $out = '';
1104              trigger_error(gTxt('unknown_tag'), E_USER_WARNING);
1105          }
1106  
1107          if ($production_status !== 'live')
1108          {
1109              --$txptracelevel;
1110  
1111              if (isset($thing))
1112              {
1113                  trace_add('</txp:'.$tag.'>');
1114              }
1115  
1116              $txp_current_tag = $old_tag;
1117          }
1118  
1119          return $out;
1120      }
1121  
1122  // -------------------------------------------------------------
1123  	function bombShelter() // protection from those who'd bomb the site by GET
1124      {
1125          global $prefs;
1126          $in = serverset('REQUEST_URI');
1127          if (!empty($prefs['max_url_len']) and strlen($in) > $prefs['max_url_len']) exit('Nice try.');
1128      }
1129  
1130  // -------------------------------------------------------------
1131  	function evalString($html)
1132      {
1133          global $prefs;
1134          if (strpos($html, chr(60).'?php') !== false) {
1135              trigger_error(gTxt('raw_php_deprecated'), E_USER_WARNING);
1136              if (!empty($prefs['allow_raw_php_scripting']))
1137                  $html = eval(' ?'.chr(62).$html.chr(60).'?php ');
1138              else
1139                  trigger_error(gTxt('raw_php_disabled'), E_USER_WARNING);
1140          }
1141          return $html;
1142      }
1143  
1144  // -------------------------------------------------------------
1145  	function getCustomFields()
1146      {
1147          global $prefs;
1148          $out = array();
1149          for ($i=1; $i<=10; $i++) {
1150              if (!empty($prefs['custom_'.$i.'_set'])) {
1151                  $out[$i] = strtolower($prefs['custom_'.$i.'_set']);
1152              }
1153          }
1154          return $out;
1155      }
1156  
1157  // -------------------------------------------------------------
1158  	function buildCustomSql($custom,$pairs)
1159      {
1160          if ($pairs) {
1161              $pairs = doSlash($pairs);
1162              foreach($pairs as $k => $v) {
1163                  if(in_array($k,$custom)) {
1164                      $no = array_keys($custom,$k);
1165                      # nb - use 'like' here to allow substring matches
1166                      $out[] = "and custom_".$no[0]." like '$v'";
1167                  }
1168              }
1169          }
1170          return (!empty($out)) ? ' '.join(' ',$out).' ' : false;
1171      }
1172  
1173  // -------------------------------------------------------------
1174  	function getStatusNum($name)
1175      {
1176          $labels = array('draft' => 1, 'hidden' => 2, 'pending' => 3, 'live' => 4, 'sticky' => 5);
1177          $status = strtolower($name);
1178          $num = empty($labels[$status]) ? 4 : $labels[$status];
1179          return $num;
1180      }
1181  
1182  // -------------------------------------------------------------
1183  	function ckEx($table,$val,$debug='')
1184      {
1185          return safe_field("name",'txp_'.$table,"`name` like '".doSlash($val)."' limit 1",$debug);
1186      }
1187  
1188  // -------------------------------------------------------------
1189  	function ckExID($val,$debug='')
1190      {
1191          return safe_row("ID,Section",'textpattern','ID = '.intval($val).' and Status >= 4 limit 1',$debug);
1192      }
1193  
1194  // -------------------------------------------------------------
1195  	function lookupByTitle($val,$debug='')
1196      {
1197          return safe_row("ID,Section",'textpattern',"url_title like '".doSlash($val)."' and Status >= 4 limit 1",$debug);
1198      }
1199  // -------------------------------------------------------------
1200  	function lookupByTitleSection($val,$section,$debug='')
1201      {
1202          return safe_row("ID,Section",'textpattern',"url_title like '".doSlash($val)."' AND Section='".doSlash($section)."' and Status >= 4 limit 1",$debug);
1203      }
1204  
1205  // -------------------------------------------------------------
1206  
1207  	function lookupByIDSection($id, $section, $debug = '')
1208      {
1209          return safe_row('ID, Section', 'textpattern',
1210              'ID = '.intval($id)." and Section = '".doSlash($section)."' and Status >= 4 limit 1", $debug);
1211      }
1212  
1213  // -------------------------------------------------------------
1214  	function lookupByID($id,$debug='')
1215      {
1216          return safe_row("ID,Section",'textpattern','ID = '.intval($id).' and Status >= 4 limit 1',$debug);
1217      }
1218  
1219  // -------------------------------------------------------------
1220  	function lookupByDateTitle($when,$title,$debug='')
1221      {
1222          return safe_row("ID,Section","textpattern",
1223          "posted like '".doSlash($when)."%' and url_title like '".doSlash($title)."' and Status >= 4 limit 1");
1224      }
1225  
1226  // -------------------------------------------------------------
1227  	function makeOut()
1228      {
1229          foreach(func_get_args() as $a) {
1230              $array[$a] = strval(gps($a));
1231          }
1232          return $array;
1233      }
1234  
1235  // -------------------------------------------------------------
1236  	function chopUrl($req)
1237      {
1238          $req = strtolower($req);
1239          //strip off query_string, if present
1240          $qs = strpos($req,'?');
1241          if ($qs) $req = substr($req, 0, $qs);
1242          $req = preg_replace('/index\.php$/', '', $req);
1243          $r = array_map('urldecode', explode('/',$req));
1244          $o['u0'] = (isset($r[0])) ? $r[0] : '';
1245          $o['u1'] = (isset($r[1])) ? $r[1] : '';
1246          $o['u2'] = (isset($r[2])) ? $r[2] : '';
1247          $o['u3'] = (isset($r[3])) ? $r[3] : '';
1248          $o['u4'] = (isset($r[4])) ? $r[4] : '';
1249  
1250          return $o;
1251      }
1252  
1253  ?>


Generated: Thu May 21 23:03:01 2009 Cross-referenced by PHPXref 0.7