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