| [ Index ] |
|
Code source de GeekLog 1.4.1 |
1 <?php 2 3 /* Reminder: always indent with 4 spaces (no tabs). */ 4 // +---------------------------------------------------------------------------+ 5 // | Geeklog 1.4 | 6 // +---------------------------------------------------------------------------+ 7 // | lib-common.php | 8 // | | 9 // | Geeklog common library. | 10 // +---------------------------------------------------------------------------+ 11 // | Copyright (C) 2000-2006 by the following authors: | 12 // | | 13 // | Authors: Tony Bibbs - tony AT tonybibbs DOT com | 14 // | Mark Limburg - mlimburg AT users DOT sourceforge DOT net | 15 // | Jason Whittenburg - jwhitten AT securitygeeks DOT com | 16 // | Dirk Haun - dirk AT haun-online DOT de | 17 // | Vincent Furia - vinny01 AT users DOT sourceforge DOT net | 18 // +---------------------------------------------------------------------------+ 19 // | | 20 // | This program is free software; you can redistribute it and/or | 21 // | modify it under the terms of the GNU General Public License | 22 // | as published by the Free Software Foundation; either version 2 | 23 // | of the License, or (at your option) any later version. | 24 // | | 25 // | This program is distributed in the hope that it will be useful, | 26 // | but WITHOUT ANY WARRANTY; without even the implied warranty of | 27 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 28 // | GNU General Public License for more details. | 29 // | | 30 // | You should have received a copy of the GNU General Public License | 31 // | along with this program; if not, write to the Free Software Foundation, | 32 // | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 33 // | | 34 // +---------------------------------------------------------------------------+ 35 // 36 // $Id: lib-common.php,v 1.611 2006/12/16 18:10:37 dhaun Exp $ 37 38 // Prevent PHP from reporting uninitialized variables 39 error_reporting( E_ERROR | E_WARNING | E_PARSE | E_COMPILE_ERROR ); 40 41 /** 42 * This is the common library for Geeklog. Through our code, you will see 43 * functions with the COM_ prefix (e.g. COM_siteHeader()). Any such functions 44 * can be found in this file. This file provides all configuration variables 45 * needed by Geeklog with a series of includes (see futher down). 46 * 47 * --- You only need to modify one line in this file! --- 48 * 49 * WARNING: put any custom hacks in lib-custom.php and not in here. This file is 50 * modified frequently by the Geeklog development team. If you put your hacks in 51 * lib-custom.php you will find upgrading much easier. 52 * 53 */ 54 55 /** 56 * Turn this on to get various debug messages from the code in this library 57 * @global Boolean $_COM_VERBOSE 58 */ 59 60 $_COM_VERBOSE = false; 61 62 /** 63 * Here, we shall establish an error handler. This will mean that whenever a 64 * php level error is encountered, our own code handles it. This will hopefuly 65 * go someway towards preventing nasties like path exposures from ever being 66 * possible. That is, unless someone has overridden our error handler with one 67 * with a path exposure issue... 68 * 69 * Must make sure that the function hasn't been disabled before calling it. 70 * 71 */ 72 if( function_exists('set_error_handler') ) 73 { 74 if( PHP_VERSION >= 5 ) 75 { 76 /* Tell the error handler to use the default error reporting options. 77 * you may like to change this to use it in more/less cases, if so, 78 * just use the syntax used in the call to error_reporting() above. 79 */ 80 $defaultErrorHandler = set_error_handler('COM_handleError', error_reporting()); 81 } else { 82 $defaultErrorHandler = set_error_handler('COM_handleError'); 83 } 84 } 85 86 /** 87 * Configuration Include: You should ONLY have to modify this line. 88 * Leave the rest of this file intact! 89 * 90 * Make sure to include the name of the config file, 91 * i.e. the path should end in .../config.php 92 */ 93 require_once( '/path/to/geeklog/config.php' ); 94 95 // Before we do anything else, check to ensure site is enabled 96 97 if( isset( $_CONF['site_enabled'] ) && !$_CONF['site_enabled'] ) 98 { 99 if( empty( $_CONF['site_disabled_msg'] )) 100 { 101 echo $_CONF['site_name'] . ' is temporarily down. Please check back soon'; 102 } 103 else 104 { 105 // if the msg starts with http: assume it's a URL we should redirect to 106 if( preg_match( "/^(https?):/", $_CONF['site_disabled_msg'] ) === 1 ) 107 { 108 echo COM_refresh( $_CONF['site_disabled_msg'] ); 109 } 110 else 111 { 112 echo $_CONF['site_disabled_msg']; 113 } 114 } 115 116 exit; 117 } 118 119 // this file can't be used on its own - redirect to index.php 120 if( strpos( $_SERVER['PHP_SELF'], 'lib-common.php' ) !== false ) 121 { 122 echo COM_refresh( $_CONF['site_url'] . '/index.php' ); 123 exit; 124 } 125 126 // timezone hack - set the webserver's timezone 127 if( !empty( $_CONF['timezone'] ) && !ini_get( 'safe_mode' ) && 128 function_exists( 'putenv' )) { 129 putenv( 'TZ=' . $_CONF['timezone'] ); 130 } 131 132 133 // +---------------------------------------------------------------------------+ 134 // | Library Includes: You shouldn't have to touch anything below here | 135 // +---------------------------------------------------------------------------+ 136 137 /** 138 * If needed, add our PEAR path to the list of include paths 139 * 140 */ 141 if( !$_CONF['have_pear'] ) 142 { 143 $curPHPIncludePath = ini_get( 'include_path' ); 144 if( defined( 'PATH_SEPARATOR' )) 145 { 146 $separator = PATH_SEPARATOR; 147 } 148 else 149 { 150 // prior to PHP 4.3.0, we have to guess the correct separator ... 151 $separator = ';'; 152 if( strpos( $curPHPIncludePath, $separator ) === false ) 153 { 154 $separator = ':'; 155 } 156 } 157 if( ini_set( 'include_path', $_CONF['path_pear'] . $separator 158 . $curPHPIncludePath ) === false ) 159 { 160 COM_errorLog( 'ini_set failed - there may be problems using the PEAR classes.', 1); 161 } 162 } 163 164 165 /** 166 * This is necessary to ensure compatibility with PHP 4.1.x 167 * 168 */ 169 if( !function_exists( 'is_a' )) 170 { 171 require_once( 'PHP/Compat.php' ); 172 173 PHP_Compat::loadFunction( 'is_a' ); 174 } 175 176 177 /** 178 * Include page time -- used to time how fast each page was created 179 * 180 */ 181 182 require_once( $_CONF['path_system'] . 'classes/timer.class.php' ); 183 $_PAGE_TIMER = new timerobject(); 184 $_PAGE_TIMER->startTimer(); 185 186 /** 187 * Include URL class 188 * 189 * This provides optional URL rewriting functionality. 190 * Please note this code is still experimental and is only currently used by the 191 * staticpages plugin. 192 */ 193 194 require_once( $_CONF['path_system'] . 'classes/url.class.php' ); 195 $_URL = new url( $_CONF['url_rewrite'] ); 196 197 /** 198 * This is our HTML template class. It is the same one found in PHPLib and is 199 * licensed under the LGPL. See that file for details 200 * 201 */ 202 203 require_once( $_CONF['path_system'] . 'classes/template.class.php' ); 204 205 /** 206 * This is the database library. 207 * 208 * Including this gives you a working connection to the database 209 * 210 */ 211 212 require_once( $_CONF['path_system'] . 'lib-database.php' ); 213 214 /** 215 * This is the security library used for application security 216 * 217 */ 218 219 require_once( $_CONF['path_system'] . 'lib-security.php' ); 220 221 /** 222 * This is the syndication library used to offer (RSS) feeds. 223 * 224 */ 225 226 require_once( $_CONF['path_system'] . 'lib-syndication.php' ); 227 228 /** 229 * This is the custom library. 230 * 231 * It is the sandbox for every Geeklog Admin to play in. 232 * We will never modify this file. This should hold all custom 233 * hacks to make upgrading easier. 234 * 235 */ 236 237 require_once( $_CONF['path_system'] . 'lib-custom.php' ); 238 239 /** 240 * Include plugin class. 241 * This is a poorly implemented class that was not very well thought out. 242 * Still very necessary 243 * 244 */ 245 246 require_once( $_CONF['path_system'] . 'lib-plugins.php' ); 247 248 /** 249 * Session management library 250 * 251 */ 252 253 require_once( $_CONF['path_system'] . 'lib-sessions.php' ); 254 255 /** 256 * Ulf Harnhammar's kses class 257 * 258 */ 259 260 require_once( $_CONF['path_system'] . 'classes/kses.class.php' ); 261 262 /** 263 * Multibyte functions 264 * 265 */ 266 require_once( $_CONF['path_system'] . 'lib-mbyte.php' ); 267 268 // Set theme 269 // Need to modify this code to check if theme was cached in user cookie. That 270 // way if user logged in and set theme and then logged out we would still know 271 // which theme to show them. 272 273 $usetheme = ''; 274 if( isset( $_POST['usetheme'] )) 275 { 276 $usetheme = preg_replace( '/[^a-zA-Z0-9\-_\.]/', '', $_POST['usetheme'] ); 277 $usetheme = str_replace( '..', '', $usetheme ); 278 } 279 if( !empty( $usetheme ) && is_dir( $_CONF['path_themes'] . $usetheme )) 280 { 281 $_CONF['theme'] = $usetheme; 282 $_CONF['path_layout'] = $_CONF['path_themes'] . $_CONF['theme'] . '/'; 283 $_CONF['layout_url'] = $_CONF['site_url'] . '/layout/' . $_CONF['theme']; 284 } 285 else if( $_CONF['allow_user_themes'] == 1 ) 286 { 287 if( isset( $_COOKIE[$_CONF['cookie_theme']] ) && empty( $_USER['theme'] )) 288 { 289 $theme = preg_replace( '/[^a-zA-Z0-9\-_\.]/', '', 290 $_COOKIE[$_CONF['cookie_theme']] ); 291 $theme = str_replace( '..', '', $theme ); 292 if( is_dir( $_CONF['path_themes'] . $theme )) 293 { 294 $_USER['theme'] = $theme; 295 } 296 } 297 298 if( !empty( $_USER['theme'] )) 299 { 300 if( is_dir( $_CONF['path_themes'] . $_USER['theme'] )) 301 { 302 $_CONF['theme'] = $_USER['theme']; 303 $_CONF['path_layout'] = $_CONF['path_themes'] . $_CONF['theme'] . '/'; 304 $_CONF['layout_url'] = $_CONF['site_url'] . '/layout/' . $_CONF['theme']; 305 } 306 else 307 { 308 $_USER['theme'] = $_CONF['theme']; 309 } 310 } 311 } 312 313 /** 314 * Include theme functions file 315 */ 316 317 // Include theme functions file which may/may not do anything 318 319 if( file_exists( $_CONF['path_layout'] . 'functions.php' )) 320 { 321 require_once( $_CONF['path_layout'] . 'functions.php' ); 322 } 323 324 // themes can now specify the default image type 325 // fall back to 'gif' if they don't 326 327 if( empty( $_IMAGE_TYPE )) 328 { 329 $_IMAGE_TYPE = 'gif'; 330 } 331 332 // Similarly set language 333 334 if( isset( $_COOKIE[$_CONF['cookie_language']] ) && empty( $_USER['language'] )) 335 { 336 $language = preg_replace( '/[^a-z0-9\-_]/', '', 337 $_COOKIE[$_CONF['cookie_language']] ); 338 if( is_file( $_CONF['path_language'] . $language . '.php' ) && 339 ( $_CONF['allow_user_language'] == 1 )) 340 { 341 $_USER['language'] = $language; 342 $_CONF['language'] = $language; 343 } 344 } 345 else if( !empty( $_USER['language'] )) 346 { 347 if( is_file( $_CONF['path_language'] . $_USER['language'] . '.php' ) && 348 ( $_CONF['allow_user_language'] == 1 )) 349 { 350 $_CONF['language'] = $_USER['language']; 351 } 352 } 353 else if( isset( $_CONF['languages'] ) && isset( $_CONF['language_files'] )) 354 { 355 $_CONF['language'] = COM_getLanguage(); 356 } 357 358 // Handle Who's Online block 359 if( empty( $_USER['uid'] ) OR $_USER['uid'] == 1 ) 360 { 361 // The following code handles anonymous users so they show up properly 362 DB_query( "DELETE FROM {$_TABLES['sessions']} WHERE remote_ip = '{$_SERVER['REMOTE_ADDR']}' AND uid = 1" ); 363 364 $tries = 0; 365 do 366 { 367 // Build a useless sess_id (needed for insert to work properly) 368 mt_srand(( double )microtime() * 1000000 ); 369 $sess_id = mt_rand(); 370 $curtime = time(); 371 372 // Insert anonymous user session 373 $result = DB_query( "INSERT INTO {$_TABLES['sessions']} (sess_id, start_time, remote_ip, uid) VALUES ($sess_id, $curtime, '{$_SERVER['REMOTE_ADDR']}', 1)", 1 ); 374 $tries++; 375 } 376 while(( $result === false) && ( $tries < 5 )); 377 } 378 379 // Clear out any expired sessions 380 DB_query( "DELETE FROM {$_TABLES['sessions']} WHERE uid = 1 AND start_time < " . ( time() - $_CONF['whosonline_threshold'] )); 381 382 /** 383 * 384 * Language include 385 * 386 */ 387 388 require_once( $_CONF['path_language'] . $_CONF['language'] . '.php' ); 389 390 COM_switchLocaleSettings(); 391 392 if( setlocale( LC_ALL, $_CONF['locale'] ) === false ) 393 { 394 setlocale( LC_TIME, $_CONF['locale'] ); 395 } 396 397 /** 398 * Global array of groups current user belongs to 399 * 400 * @global array $_GROUPS 401 * 402 */ 403 404 if( isset( $_USER['uid'] )) 405 { 406 $_GROUPS = SEC_getUserGroups( $_USER['uid'] ); 407 } 408 else 409 { 410 $_GROUPS = SEC_getUserGroups( 1 ); 411 } 412 413 /** 414 * Global array of current user permissions [read,edit] 415 * 416 * @global array $_RIGHTS 417 * 418 */ 419 420 $_RIGHTS = explode( ',', SEC_getUserPermissions() ); 421 422 if( isset( $_GET['topic'] )) 423 { 424 $topic = COM_applyFilter( $_GET['topic'] ); 425 } 426 else if( isset( $_POST['topic'] )) 427 { 428 $topic = COM_applyFilter( $_POST['topic'] ); 429 } 430 else 431 { 432 $topic = ''; 433 } 434 435 436 // +---------------------------------------------------------------------------+ 437 // | HTML WIDGETS | 438 // +---------------------------------------------------------------------------+ 439 440 /** 441 * Return the file to use for a block template. 442 * 443 * This returns the template needed to build the HTML for a block. This function 444 * allows designers to give a block it's own custom look and feel. If no 445 * templates for the block are specified, the default blockheader.html and 446 * blockfooter.html will be used. 447 * 448 * @param string $blockname corresponds to name field in block table 449 * @param string $which can be either 'header' or 'footer' for corresponding template 450 * @see function COM_startBlock 451 * @see function COM_endBlock 452 * @see function COM_showBlocks 453 * @see function COM_showBlock 454 * @return string template name 455 */ 456 function COM_getBlockTemplate( $blockname, $which ) 457 { 458 global $_BLOCK_TEMPLATE, $_COM_VERBOSE; 459 460 if( $_COM_VERBOSE ) 461 { 462 COM_errorLog( "_BLOCK_TEMPLATE[$blockname] = " . $_BLOCK_TEMPLATE[$blockname], 1 ); 463 } 464 465 if( !empty( $_BLOCK_TEMPLATE[$blockname] )) 466 { 467 $templates = explode( ',', $_BLOCK_TEMPLATE[$blockname] ); 468 if( $which == 'header' ) 469 { 470 if( !empty( $templates[0] )) 471 { 472 $template = $templates[0]; 473 } 474 else 475 { 476 $template = 'blockheader.thtml'; 477 } 478 } 479 else 480 { 481 if( !empty( $templates[1] )) 482 { 483 $template = $templates[1]; 484 } 485 else 486 { 487 $template = 'blockfooter.thtml'; 488 } 489 } 490 } 491 else 492 { 493 if( $which == 'header' ) 494 { 495 $template = 'blockheader.thtml'; 496 } 497 else 498 { 499 $template = 'blockfooter.thtml'; 500 } 501 } 502 503 if( $_COM_VERBOSE ) 504 { 505 COM_errorLog( "Block template for the $which of $blockname is: $template", 1 ); 506 } 507 508 return $template; 509 } 510 511 /** 512 * Gets all installed themes 513 * 514 * Returns a list of all the directory names in $_CONF['path_themes'], i.e. 515 * a list of all the theme names. 516 * 517 * @param bool $all if true, return all themes even if users aren't allowed to change their default themes 518 * @return array All installed themes 519 * 520 */ 521 function COM_getThemes( $all = false ) 522 { 523 global $_CONF; 524 525 $index = 1; 526 527 $themes = array(); 528 529 $fd = opendir( $_CONF['path_themes'] ); 530 531 // If users aren't allowed to change their theme then only return the default theme 532 533 if(( $_CONF['allow_user_themes'] == 0 ) && !$all ) 534 { 535 $themes[$index] = $_CONF['theme']; 536 } 537 else 538 { 539 while(( $dir = @readdir( $fd )) == TRUE ) 540 { 541 if( is_dir( $_CONF['path_themes'] . $dir) && $dir <> '.' && $dir <> '..' && $dir <> 'CVS' && substr( $dir, 0 , 1 ) <> '.' ) 542 { 543 clearstatcache(); 544 $themes[$index] = $dir; 545 $index++; 546 } 547 } 548 } 549 550 return $themes; 551 } 552 553 /** 554 * Create the menu, i.e. replace {menu_elements} in the site header with the 555 * actual menu entries. 556 * 557 * @param Template $header reference to the header template 558 * @param array $plugin_menu array of plugin menu entries, if any 559 * 560 */ 561 function COM_renderMenu( &$header, $plugin_menu ) 562 { 563 global $_CONF, $_USER, $LANG01, $topic; 564 565 if( empty( $_CONF['menu_elements'] )) 566 { 567 $_CONF['menu_elements'] = array( // default set of links 568 'contribute', 'search', 'stats', 'directory', 'plugins' ); 569 } 570 571 $anon = ( empty( $_USER['uid'] ) || ( $_USER['uid'] <= 1 )) ? true : false; 572 $menuCounter = 0; 573 $allowedCounter = 0; 574 $counter = 0; 575 576 $num_plugins = sizeof( $plugin_menu ); 577 if( ( $num_plugins == 0 ) && in_array( 'plugins', $_CONF['menu_elements'] )) 578 { 579 $key = array_search( 'plugins', $_CONF['menu_elements'] ); 580 unset( $_CONF['menu_elements'][$key] ); 581 } 582 583 if( in_array( 'custom', $_CONF['menu_elements'] )) 584 { 585 $custom_entries = array(); 586 if( function_exists( 'CUSTOM_menuEntries' )) 587 { 588 $custom_entries = CUSTOM_menuEntries(); 589 } 590 if( sizeof( $custom_entries ) == 0 ) 591 { 592 $key = array_search( 'custom', $_CONF['menu_elements'] ); 593 unset( $_CONF['menu_elements'][$key] ); 594 } 595 } 596 597 $num_elements = sizeof( $_CONF['menu_elements'] ); 598 599 foreach( $_CONF['menu_elements'] as $item ) 600 { 601 $counter++; 602 $allowed = true; 603 $last_entry = ( $counter == $num_elements ) ? true : false; 604 605 switch( $item ) 606 { 607 case 'contribute': 608 if( empty( $topic )) 609 { 610 $url = $_CONF['site_url'] . '/submit.php?type=story'; 611 $header->set_var( 'current_topic', '' ); 612 } 613 else 614 { 615 $url = $_CONF['site_url'] 616 . '/submit.php?type=story&topic=' . $topic; 617 $header->set_var( 'current_topic', '&topic=' . $topic ); 618 } 619 $label = $LANG01[71]; 620 if( $anon && ( $_CONF['loginrequired'] || 621 $_CONF['submitloginrequired'] )) 622 { 623 $allowed = false; 624 } 625 break; 626 627 case 'custom': 628 $custom_count = 0; 629 $custom_size = sizeof( $custom_entries ); 630 foreach( $custom_entries as $entry ) 631 { 632 $custom_count++; 633 634 if( empty( $entry['url'] ) || empty( $entry['label'] )) 635 { 636 continue; 637 } 638 639 $header->set_var( 'menuitem_url', $entry['url'] ); 640 $header->set_var( 'menuitem_text', $entry['label'] ); 641 642 if( $last_entry && ( $custom_count == $custom_size )) 643 { 644 $header->parse( 'menu_elements', 'menuitem_last', 645 true ); 646 } 647 else 648 { 649 $header->parse( 'menu_elements', 'menuitem', true ); 650 } 651 $menuCounter++; 652 } 653 $url = ''; 654 $label = ''; 655 break; 656 657 case 'directory': 658 $url = $_CONF['site_url'] . '/directory.php'; 659 if( !empty( $topic )) 660 { 661 $url = COM_buildUrl( $url . '?topic=' 662 . urlencode( $topic )); 663 } 664 $label = $LANG01[117]; 665 if( $anon && ( $_CONF['loginrequired'] || 666 $_CONF['directoryloginrequired'] )) 667 { 668 $allowed = false; 669 } 670 break; 671 672 case 'home': 673 $url = $_CONF['site_url'] . '/'; 674 $label = $LANG01[90]; 675 break; 676 677 case 'plugins': 678 for( $i = 1; $i <= $num_plugins; $i++ ) 679 { 680 $header->set_var( 'menuitem_url', current( $plugin_menu )); 681 $header->set_var( 'menuitem_text', key( $plugin_menu )); 682 683 if( $last_entry && ( $i == $num_plugins )) 684 { 685 $header->parse( 'menu_elements', 'menuitem_last', 686 true ); 687 } 688 else 689 { 690 $header->parse( 'menu_elements', 'menuitem', true ); 691 } 692 $menuCounter++; 693 694 next( $plugin_menu ); 695 } 696 $url = ''; 697 $label = ''; 698 break; 699 700 case 'prefs': 701 $url = $_CONF['site_url'] . '/usersettings.php?mode=edit'; 702 $label = $LANG01[48]; 703 break; 704 705 case 'search': 706 $url = $_CONF['site_url'] . '/search.php'; 707 $label = $LANG01[75]; 708 if( $anon && ( $_CONF['loginrequired'] || 709 $_CONF['searchloginrequired'] )) 710 { 711 $allowed = false; 712 } 713 break; 714 715 case 'stats': 716 $url = $_CONF['site_url'] . '/stats.php'; 717 $label = $LANG01[76]; 718 if( $anon && 719 ( $_CONF['loginrequired'] || $_CONF['statsloginrequired'] )) 720 { 721 $allowed = false; 722 } 723 break; 724 725 default: // unknown entry 726 $url = ''; 727 $label = ''; 728 break; 729 } 730 731 if( !empty( $url ) && !empty( $label )) 732 { 733 $header->set_var( 'menuitem_url', $url ); 734 $header->set_var( 'menuitem_text', $label ); 735 if( $last_entry ) 736 { 737 $header->parse( 'menu_elements', 'menuitem_last', true ); 738 } 739 else 740 { 741 $header->parse( 'menu_elements', 'menuitem', true ); 742 } 743 $menuCounter++; 744 745 if( $allowed ) 746 { 747 if( $last_entry ) 748 { 749 $header->parse( 'allowed_menu_elements', 'menuitem_last', 750 true ); 751 } 752 else 753 { 754 $header->parse( 'allowed_menu_elements', 'menuitem', true ); 755 } 756 $allowedCounter++; 757 } 758 } 759 } 760 761 if( $menuCounter == 0 ) 762 { 763 $header->parse( 'menu_elements', 'menuitem_none', true ); 764 } 765 if( $allowedCounter == 0 ) 766 { 767 $header->parse( 'allowed_menu_elements', 'menuitem_none', true ); 768 } 769 } 770 771 /** 772 * Returns the site header 773 * 774 * This loads the proper templates, does variable substitution and returns the 775 * HTML for the site header with or without blocks depending on the value of $what 776 * 777 * Programming Note: 778 * 779 * The two functions COM_siteHeader and COM_siteFooter provide the framework for 780 * page display in Geeklog. COM_siteHeader controls the display of the Header 781 * and left blocks and COM_siteFooter controls the dsiplay of the right blocks 782 * and the footer. You use them like a sandwich. Thus the following code will 783 * display a Geeklog page with both right and left blocks displayed. 784 * 785 * ------------------------------------------------------------------------------------- 786 * <?php 787 * require_once('lib-common.php'); 788 * $display .= COM_siteHeader(); //Change to COM_siteHeader('none') to not display left blocks 789 * $display .= "Here is your html for display"; 790 * $display .= COM_siteFooter(true); // Change to COM_siteFooter() to not display right blocks 791 * echo $display; 792 * ? > 793 * --------------------------------------------------------------------------------------- 794 * 795 * Note that the default for the header is to display the left blocks and the 796 * default of the footer is to not display the right blocks. 797 * 798 * This sandwich produces code like this (greatly simplified) 799 * 800 * // COM_siteHeader 801 * <table><tr><td colspan="3">Header</td></tr> 802 * <tr><td>Left Blocks</td><td> 803 * 804 * // Your HTML goes here 805 * Here is your html for display 806 * 807 * // COM_siteFooter 808 * </td><td>Right Blocks</td></tr> 809 * <tr><td colspan="3">Footer</td></table> 810 * 811 * @param string $what If 'none' then no left blocks are returned, if 'menu' (default) then right blocks are returned 812 * @param string $pagetitle optional content for the page's <title> 813 * @param string $headercode optional code to go into the page's <head> 814 * @return string Formatted HTML containing the site header 815 * @see function COM_siteFooter 816 * 817 */ 818 819 function COM_siteHeader( $what = 'menu', $pagetitle = '', $headercode = '' ) 820 { 821 global $_CONF, $_TABLES, $_USER, $LANG01, $LANG_BUTTONS, $LANG_CHARSET, 822 $LANG_DIRECTION, $_IMAGE_TYPE, $topic, $_COM_VERBOSE; 823 824 // If the theme implemented this for us then call their version instead. 825 826 $function = $_CONF['theme'] . '_siteHeader'; 827 828 if( function_exists( $function )) 829 { 830 return $function( $what, $pagetitle, $headercode ); 831 } 832 833 // send out the charset header 834 835 if( empty( $LANG_CHARSET )) { 836 $charset = $_CONF['default_charset']; 837 if( empty( $charset )) { 838 $charset = 'iso-8859-1'; 839 } 840 } else { 841 $charset = $LANG_CHARSET; 842 } 843 header ('Content-Type: text/html; charset=' . $charset); 844 845 // If we reach here then either we have the default theme OR 846 // the current theme only needs the default variable substitutions 847 848 $header = new Template( $_CONF['path_layout'] ); 849 $header->set_file( array( 850 'header' => 'header.thtml', 851 'menuitem' => 'menuitem.thtml', 852 'menuitem_last' => 'menuitem_last.thtml', 853 'menuitem_none' => 'menuitem_none.thtml', 854 'leftblocks' => 'leftblocks.thtml' 855 )); 856 857 // get topic if not on home page 858 if( !isset( $_GET['topic'] )) 859 { 860 if( isset( $_GET['story'] )) 861 { 862 $sid = COM_applyFilter( $_GET['story'] ); 863 } 864 elseif( isset( $_GET['sid'] )) 865 { 866 $sid = COM_applyFilter( $_GET['sid'] ); 867 } 868 elseif( isset( $_POST['story'] )) 869 { 870 $sid = COM_applyFilter( $_POST['story'] ); 871 } 872 if( empty( $sid ) && $_CONF['url_rewrite'] && 873 ( strpos( $_SERVER['PHP_SELF'], 'article.php' ) !== false )) 874 { 875 COM_setArgNames( array( 'story', 'mode' )); 876 $sid = COM_applyFilter( COM_getArgument( 'story' )); 877 } 878 if( !empty( $sid )) 879 { 880 $topic = DB_getItem( $_TABLES['stories'], 'tid', "sid='$sid'" ); 881 } 882 } 883 else 884 { 885 $topic = COM_applyFilter( $_GET['topic'] ); 886 } 887 888 $feed_url = array(); 889 if( $_CONF['backend'] == 1 ) // add feed-link to header if applicable 890 { 891 $baseurl = SYND_getFeedUrl(); 892 893 $sql = 'SELECT format, filename, title, language FROM ' 894 . $_TABLES['syndication'] . " WHERE (header_tid = 'all')"; 895 if( !empty( $topic )) 896 { 897 $sql .= " OR (header_tid = '" . addslashes( $topic ) . "')"; 898 } 899 $result = DB_query( $sql ); 900 $numRows = DB_numRows( $result ); 901 for( $i = 0; $i < $numRows; $i++ ) 902 { 903 $A = DB_fetchArray( $result ); 904 if ( !empty( $A['filename'] )) 905 { 906 $format = explode( '-', $A['format'] ); 907 $format_type = strtolower( $format[0] ); 908 $format_name = ucwords( $format[0] ); 909 910 $feed_url[] = '<link rel="alternate" type="application/' 911 . $format_type . '+xml" hreflang="' . $A['language'] 912 . '" href="' . $baseurl . $A['filename'] . '" title="' 913 . $format_name . ' Feed: ' . $A['title'] . '">'; 914 } 915 } 916 } 917 $header->set_var( 'feed_url', implode( LB, $feed_url )); 918 919 $relLinks = array(); 920 if( !COM_onFrontpage() ) 921 { 922 $relLinks['home'] = '<link rel="home" href="' . $_CONF['site_url'] 923 . '/" title="' . $LANG01[90] . '">'; 924 } 925 $loggedInUser = ( isset( $_USER['uid'] ) && ( $_USER['uid'] > 1 )); 926 if( $loggedInUser || (( $_CONF['loginrequired'] == 0 ) && 927 ( $_CONF['searchloginrequired'] == 0 ))) 928 { 929 if(( substr( $_SERVER['PHP_SELF'], -strlen( '/search.php' )) 930 != '/search.php' ) || isset( $_GET['mode'] )) 931 { 932 $relLinks['search'] = '<link rel="search" href="' 933 . $_CONF['site_url'] . '/search.php" title="' 934 . $LANG01[75] . '">'; 935 } 936 } 937 if( $loggedInUser || (( $_CONF['loginrequired'] == 0 ) && 938 ( $_CONF['directoryloginrequired'] == 0 ))) 939 { 940 if( strpos( $_SERVER['PHP_SELF'], '/article.php' ) !== false ) { 941 $relLinks['contents'] = '<link rel="contents" href="' 942 . $_CONF['site_url'] . '/directory.php" title="' 943 . $LANG01[117] . '">'; 944 } 945 } 946 // TBD: add a plugin API and a lib-custom.php function 947 $header->set_var( 'rel_links', implode( LB, $relLinks )); 948 949 if( empty( $pagetitle ) && isset( $_CONF['pagetitle'] )) 950 { 951 $pagetitle = $_CONF['pagetitle']; 952 } 953 if( empty( $pagetitle )) 954 { 955 if( empty( $topic )) 956 { 957 $pagetitle = $_CONF['site_slogan']; 958 } 959 else 960 { 961 $pagetitle = stripslashes( DB_getItem( $_TABLES['topics'], 'topic', 962 "tid = '$topic'" )); 963 } 964 } 965 if( !empty( $pagetitle )) 966 { 967 $pagetitle = ' - ' . $pagetitle; 968 } 969 $header->set_var( 'page_title', $_CONF['site_name'] . $pagetitle ); 970 971 if( isset( $_CONF['advanced_editor'] ) && ( $_CONF['advanced_editor'] == 1 ) 972 && file_exists( $_CONF['path_layout'] 973 . 'advanced_editor_header.thtml' )) 974 { 975 $header->set_file( 'editor' , 'advanced_editor_header.thtml'); 976 $header->parse( 'advanced_editor', 'editor' ); 977 978 } 979 else 980 { 981 $header->set_var( 'advanced_editor', '' ); 982 } 983 984 $langAttr = ''; 985 if( isset( $_CONF['languages'] ) && isset( $_CONF['language_files'] )) 986 { 987 $langId = COM_getLanguageId(); 988 } 989 else 990 { 991 // try to derive the language id from the locale 992 $l = explode( '.', $_CONF['locale'] ); 993 $langId = $l[0]; 994 } 995 if( !empty( $langId )) 996 { 997 $l = explode( '-', str_replace( '_', '-', $langId )); 998 if(( count( $l ) == 1 ) && ( strlen( $langId ) == 2 )) 999 { 1000 $langAttr = 'lang="' . $langId . '"'; 1001 } 1002 else if( count( $l ) == 2 ) 1003 { 1004 if(( $l[0] == 'i' ) || ( $l[0] == 'x' )) 1005 { 1006 $langId = implode( '-', $l ); 1007 $langAttr = 'lang="' . $langId . '"'; 1008 } 1009 else if( strlen( $l[0] ) == 2 ) 1010 { 1011 $langId = implode( '-', $l ); 1012 $langAttr = 'lang="' . $langId . '"'; 1013 } 1014 else 1015 { 1016 $langId = $l[0]; 1017 } 1018 } 1019 } 1020 $header->set_var( 'lang_id', $langId ); 1021 $header->set_var( 'lang_attribute', $langAttr ); 1022 1023 $header->set_var( 'background_image', $_CONF['layout_url'] 1024 . '/images/bg.' . $_IMAGE_TYPE ); 1025 $header->set_var( 'site_url', $_CONF['site_url'] ); 1026 $header->set_var( 'layout_url', $_CONF['layout_url'] ); 1027 $header->set_var( 'site_mail', "mailto:{$_CONF['site_mail']}" ); 1028 $header->set_var( 'site_name', $_CONF['site_name'] ); 1029 $header->set_var( 'site_slogan', $_CONF['site_slogan'] ); 1030 $rdf = substr_replace( $_CONF['rdf_file'], $_CONF['site_url'], 0, 1031 strlen( $_CONF['path_html'] ) - 1 ); 1032 $header->set_var( 'rdf_file', $rdf ); 1033 $header->set_var( 'rss_url', $rdf ); 1034 1035 $msg = $LANG01[67] . ' ' . $_CONF['site_name']; 1036 1037 if( !empty( $_USER['username'] )) 1038 { 1039 $msg .= ', ' . COM_getDisplayName( $_USER['uid'], $_USER['username'], 1040 $_USER['fullname'] ); 1041 } 1042 1043 $curtime = COM_getUserDateTimeFormat(); 1044 1045 $header->set_var( 'welcome_msg', $msg ); 1046 $header->set_var( 'datetime', $curtime[0] ); 1047 $header->set_var( 'site_logo', $_CONF['layout_url'] 1048 . '/images/logo.' . $_IMAGE_TYPE ); 1049 $header->set_var( 'css_url', $_CONF['layout_url'] . '/style.css' ); 1050 $header->set_var( 'theme', $_CONF['theme'] ); 1051 1052 if( empty( $LANG_CHARSET )) 1053 { 1054 $charset = $_CONF['default_charset']; 1055 1056 if( empty( $charset )) 1057 { 1058 $charset = 'iso-8859-1'; 1059 } 1060 } 1061 else 1062 { 1063 $charset = $LANG_CHARSET; 1064 } 1065 1066 $header->set_var( 'charset', $charset ); 1067 if( empty( $LANG_DIRECTION )) 1068 { 1069 // default to left-to-right 1070 $header->set_var( 'direction', 'ltr' ); 1071 } 1072 else 1073 { 1074 $header->set_var( 'direction', $LANG_DIRECTION ); 1075 } 1076 1077 // Now add variables for buttons like e.g. those used by the Yahoo theme 1078 $header->set_var( 'button_home', $LANG_BUTTONS[1] ); 1079 $header->set_var( 'button_contact', $LANG_BUTTONS[2] ); 1080 $header->set_var( 'button_contribute', $LANG_BUTTONS[3] ); 1081 $header->set_var( 'button_sitestats', $LANG_BUTTONS[7] ); 1082 $header->set_var( 'button_personalize', $LANG_BUTTONS[8] ); 1083 $header->set_var( 'button_search', $LANG_BUTTONS[9] ); 1084 $header->set_var( 'button_advsearch', $LANG_BUTTONS[10] ); 1085 $header->set_var( 'button_directory', $LANG_BUTTONS[11] ); 1086 1087 // Get plugin menu options 1088 $plugin_menu = PLG_getMenuItems(); 1089 1090 if( $_COM_VERBOSE ) 1091 { 1092 COM_errorLog( 'num plugin menu items in header = ' . count( $plugin_menu ), 1 ); 1093 } 1094 1095 // Now add nested template for menu items 1096 COM_renderMenu( $header, $plugin_menu ); 1097 1098 if( count( $plugin_menu ) == 0 ) 1099 { 1100 $header->parse( 'plg_menu_elements', 'menuitem_none', true ); 1101 } 1102 else 1103 { 1104 for( $i = 1; $i <= count( $plugin_menu ); $i++ ) 1105 { 1106 $header->set_var( 'menuitem_url', current( $plugin_menu )); 1107 $header->set_var( 'menuitem_text', key( $plugin_menu )); 1108 1109 if( $i == count( $plugin_menu )) 1110 { 1111 $header->parse( 'plg_menu_elements', 'menuitem_last', true ); 1112 } 1113 else 1114 { 1115 $header->parse( 'plg_menu_elements', 'menuitem', true ); 1116 } 1117 1118 next( $plugin_menu ); 1119 } 1120 } 1121 1122 if( $_CONF['left_blocks_in_footer'] == 1 ) 1123 { 1124 $header->set_var( 'geeklog_blocks', '' ); 1125 $header->set_var( 'left_blocks', '' ); 1126 } 1127 else 1128 { 1129 $lblocks = ''; 1130 1131 /* Check if an array has been passed that includes the name of a plugin 1132 * function or custom function 1133 * This can be used to take control over what blocks are then displayed 1134 */ 1135 if( is_array( $what )) 1136 { 1137 $function = $what[0]; 1138 if( function_exists( $function )) 1139 { 1140 $lblocks = $function( $what[1], 'left' ); 1141 } 1142 else 1143 { 1144 $lblocks = COM_showBlocks( 'left', $topic ); 1145 } 1146 } 1147 else if( $what <> 'none' ) 1148 { 1149 // Now show any blocks -- need to get the topic if not on home page 1150 $lblocks = COM_showBlocks( 'left', $topic ); 1151 } 1152 1153 if( empty( $lblocks )) 1154 { 1155 $header->set_var( 'geeklog_blocks', '' ); 1156 $header->set_var( 'left_blocks', '' ); 1157 } 1158 else 1159 { 1160 $header->set_var( 'geeklog_blocks', $lblocks ); 1161 $header->parse( 'left_blocks', 'leftblocks', true ); 1162 } 1163 } 1164 1165 // Call any plugin that may want to include extra Meta tags 1166 // or Javascript functions 1167 $header->set_var( 'plg_headercode', $headercode . PLG_getHeaderCode() ); 1168 1169 // Call to plugins to set template variables in the header 1170 PLG_templateSetVars( 'header', $header ); 1171 1172 // The following lines allow users to embed PHP in their templates. This 1173 // is almost a contradition to the reasons for using templates but this may 1174 // prove useful at times ... 1175 // Don't use PHP in templates if you can live without it! 1176 1177 $tmp = $header->parse( 'index_header', 'header' ); 1178 1179 ob_start(); 1180 eval( '?>' . $tmp ); 1181 $retval = ob_get_contents(); 1182 ob_end_clean(); 1183 1184 return $retval; 1185 } 1186 1187 1188 /** 1189 * Returns the site footer 1190 * 1191 * This loads the proper templates, does variable substitution and returns the 1192 * HTML for the site footer. 1193 * 1194 * @param boolean $rightblock Whether or not to show blocks on right hand side default is no 1195 * @param array $custom An array defining custom function to be used to format Rightblocks 1196 * @see function COM_siteHeader 1197 * @return string Formated HTML containing site footer and optionally right blocks 1198 * 1199 */ 1200 function COM_siteFooter( $rightblock = -1, $custom = '' ) 1201 { 1202 global $_CONF, $_TABLES, $LANG01, $_PAGE_TIMER, $topic; 1203 1204 if( $rightblock < 0 ) 1205 { 1206 if( isset( $_CONF['show_right_blocks'] )) 1207 { 1208 $rightblock = $_CONF['show_right_blocks']; 1209 } 1210 else 1211 { 1212 $rightblock = false; 1213 } 1214 } 1215 1216 // If the theme implemented this for us then call their version instead. 1217 1218 $function = $_CONF['theme'] . '_siteFooter'; 1219 1220 if( function_exists( $function )) 1221 { 1222 return $function( $rightblock, $custom ); 1223 } 1224 1225 // Set template directory 1226 $footer = new Template( $_CONF['path_layout'] ); 1227 1228 // Set template file 1229 $footer->set_file( array( 1230 'footer' => 'footer.thtml', 1231 'rightblocks' => 'rightblocks.thtml', 1232 'leftblocks' => 'leftblocks.thtml' 1233 )); 1234 1235 // Do variable assignments 1236 DB_change( $_TABLES['vars'], 'value', 'value + 1', 'name', 'totalhits', '', true ); 1237 1238 $footer->set_var( 'site_url', $_CONF['site_url']); 1239 $footer->set_var( 'layout_url',$_CONF['layout_url']); 1240 $footer->set_var( 'site_mail', "mailto:{$_CONF['site_mail']}" ); 1241 $footer->set_var( 'site_name', $_CONF['site_name'] ); 1242 $footer->set_var( 'site_slogan', $_CONF['site_slogan'] ); 1243 $rdf = substr_replace( $_CONF['rdf_file'], $_CONF['site_url'], 0, 1244 strlen( $_CONF['path_html'] ) - 1 ); 1245 $footer->set_var( 'rdf_file', $rdf ); 1246 $footer->set_var( 'rss_url', $rdf ); 1247 1248 $year = date( 'Y' ); 1249 $copyrightyear = $year; 1250 if( !empty( $_CONF['copyrightyear'] )) 1251 { 1252 $copyrightyear = $_CONF['copyrightyear']; 1253 } 1254 $footer->set_var( 'copyright_notice', ' ' . $LANG01[93] . ' © ' 1255 . $copyrightyear . ' ' . $_CONF['site_name'] . '<br> ' 1256 . $LANG01[94] ); 1257 $footer->set_var( 'copyright_msg', $LANG01[93] . ' © ' 1258 . $copyrightyear . ' ' . $_CONF['site_name'] ); 1259 $footer->set_var( 'current_year', $year ); 1260 $footer->set_var( 'lang_copyright', $LANG01[93] ); 1261 $footer->set_var( 'trademark_msg', $LANG01[94] ); 1262 $footer->set_var( 'powered_by', $LANG01[95] ); 1263 $footer->set_var( 'geeklog_url', 'http://www.geeklog.net/' ); 1264 $footer->set_var( 'geeklog_version', VERSION ); 1265 1266 /* Check if an array has been passed that includes the name of a plugin 1267 * function or custom function. 1268 * This can be used to take control over what blocks are then displayed 1269 */ 1270 if( is_array( $custom )) 1271 { 1272 $function = $custom['0']; 1273 if( function_exists( $function )) 1274 { 1275 $rblocks = $function( $custom['1'], 'right' ); 1276 } 1277 } 1278 elseif( $rightblock ) 1279 { 1280 $rblocks = COM_showBlocks( 'right', $topic ); 1281 } 1282 if( $rightblock && !empty( $rblocks )) 1283 { 1284 $footer->set_var( 'geeklog_blocks', $rblocks ); 1285 $footer->parse( 'right_blocks', 'rightblocks', true ); 1286 } 1287 else 1288 { 1289 $footer->set_var( 'geeklog_blocks', '' ); 1290 $footer->set_var( 'right_blocks', '' ); 1291 } 1292 1293 if( $_CONF['left_blocks_in_footer'] == 1 ) 1294 { 1295 $lblocks = ''; 1296 1297 /* Check if an array has been passed that includes the name of a plugin 1298 * function or custom function 1299 * This can be used to take control over what blocks are then displayed 1300 */ 1301 if( is_array( $custom )) 1302 { 1303 $function = $custom[0]; 1304 if( function_exists( $function )) 1305 { 1306 $lblocks = $function( $custom[1], 'left' ); 1307 } 1308 } 1309 else 1310 { 1311 $lblocks = COM_showBlocks( 'left', $topic ); 1312 } 1313 1314 if( empty( $lblocks )) 1315 { 1316 $footer->set_var( 'geeklog_blocks', '' ); 1317 $footer->set_var( 'left_blocks', '' ); 1318 } 1319 else 1320 { 1321 $footer->set_var( 'geeklog_blocks', $lblocks ); 1322 $footer->parse( 'left_blocks', 'leftblocks', true ); 1323 } 1324 } 1325 1326 // Global centerspan variable set in index.php 1327 if( isset( $GLOBALS['centerspan'] )) 1328 { 1329 $footer->set_var( 'centerblockfooter-span', '</td></tr></table>' ); 1330 } 1331 1332 $exectime = $_PAGE_TIMER->stopTimer(); 1333 $exectext = $LANG01[91] . ' ' . $exectime . ' ' . $LANG01[92]; 1334 1335 $footer->set_var( 'execution_time', $exectime ); 1336 $footer->set_var( 'execution_textandtime', $exectext ); 1337 1338 // Call to plugins to set template variables in the footer 1339 PLG_templateSetVars( 'footer', $footer ); 1340 1341 // Actually parse the template and make variable substitutions 1342 $footer->parse( 'index_footer', 'footer' ); 1343 1344 // Return resulting HTML 1345 return $footer->finish( $footer->get_var( 'index_footer' )); 1346 } 1347 1348 /** 1349 * Prints out standard block header 1350 * 1351 * Prints out standard block header but pulling header HTML formatting from 1352 * the database. 1353 * 1354 * Programming Note: The two functions COM_startBlock and COM_endBlock are used 1355 * to sandwich your block content. These functions are not used only for blocks 1356 * but anything that uses that format, e.g. Stats page. They are used like 1357 * COM_siteHeader and COM_siteFooter but for internal page elements. 1358 * 1359 * 1360 * @param string $title Value to set block title to 1361 * @param string $helpfile Help file, if one exists 1362 * @param string $template HTML template file to use to format the block 1363 * @see COM_endBlock 1364 * @see COM_siteHeader For similiar construct 1365 * @return string Formatted HTML containing block header 1366 * 1367 */ 1368 1369 function COM_startBlock( $title='', $helpfile='', $template='blockheader.thtml' ) 1370 { 1371 global $_CONF, $LANG01, $_IMAGE_TYPE; 1372 1373 $block = new Template( $_CONF['path_layout'] ); 1374 $block->set_file( 'block', $template ); 1375 1376 $block->set_var( 'site_url', $_CONF['site_url'] ); 1377 $block->set_var( 'layout_url', $_CONF['layout_url'] ); 1378 $block->set_var( 'block_title', stripslashes( $title )); 1379 1380 if( !empty( $helpfile )) 1381 { 1382 $helpimg = $_CONF['layout_url'] . '/images/button_help.' . $_IMAGE_TYPE; 1383 if( !stristr( $helpfile, 'http://' )) 1384 { 1385 $help = '<a class="blocktitle" href="' . $_CONF['site_url'] . '/help/' . $helpfile 1386 . '" target="_blank"><img src="' . $helpimg 1387 . '" border="0" alt="?"></a>'; 1388 } 1389 else 1390 { 1391 $help = '<a class="blocktitle" href="' . $helpfile 1392 . '" target="_blank"><img src="' . $helpimg 1393 . '" border="0" alt="?"></a>'; 1394 } 1395 1396 $block->set_var( 'block_help', $help ); 1397 } 1398 1399 $block->parse( 'startHTML', 'block' ); 1400 1401 return $block->finish( $block->get_var( 'startHTML' )); 1402 } 1403 1404 /** 1405 * Closes out COM_startBlock 1406 * 1407 * @param string $template HTML template file used to format block footer 1408 * @return string Formatted HTML to close block 1409 * @see function COM_startBlock 1410 * 1411 */ 1412 function COM_endBlock( $template='blockfooter.thtml' ) 1413 { 1414 global $_CONF; 1415 1416 $block = new Template( $_CONF['path_layout'] ); 1417 $block->set_file( 'block', $template ); 1418 1419 $block->set_var( 'site_url', $_CONF['site_url'] ); 1420 $block->set_var( 'layout_url', $_CONF['layout_url'] ); 1421 $block->parse( 'endHTML', 'block' ); 1422 1423 return $block->finish( $block->get_var( 'endHTML' )); 1424 } 1425 1426 1427 /** 1428 * Creates a <option> list from a database list for use in forms 1429 * 1430 * Creates option list form field using given arguments 1431 * 1432 * @param string $table Database Table to get data from 1433 * @param string $selection Comma delimited string of fields to pull The first field is the value of the option and the second is the label to be displayed. This is used in a SQL statement and can include DISTINCT to start. 1434 * @param string/array $selected Value (from $selection) to set to SELECTED or default 1435 * @param int $sortcol Which field to sort option list by 0 (value) or 1 (label) 1436 * @param string $where Optional WHERE clause to use in the SQL Selection 1437 * @see function COM_checkList 1438 * @return string Formated HTML of option values 1439 * 1440 */ 1441 function COM_optionList( $table, $selection, $selected='', $sortcol=1, $where='' ) 1442 { 1443 global $_DB_table_prefix; 1444 1445 $retval = ''; 1446 1447 $LangTableName = ''; 1448 if( substr( $table, 0, strlen( $_DB_table_prefix )) == $_DB_table_prefix ) 1449 { 1450 $LangTableName = 'LANG_' . substr( $table, strlen( $_DB_table_prefix )); 1451 } 1452 else 1453 { 1454 $LangTableName = 'LANG_' . $table; 1455 } 1456 1457 global $$LangTableName; 1458 1459 if( isset( $$LangTableName )) 1460 { 1461 $LangTable = $$LangTableName; 1462 } 1463 else 1464 { 1465 $LangTable = array(); 1466 } 1467 1468 $tmp = str_replace( 'DISTINCT ', '', $selection ); 1469 $select_set = explode( ',', $tmp ); 1470 1471 $sql = "SELECT $selection FROM $table"; 1472 if( $where != '' ) 1473 { 1474 $sql .= " WHERE $where"; 1475 } 1476 $sql .= " ORDER BY {$select_set[$sortcol]}"; 1477 $result = DB_query( $sql ); 1478 $nrows = DB_numRows( $result ); 1479 1480 for( $i = 0; $i < $nrows; $i++ ) 1481 { 1482 $A = DB_fetchArray( $result, true ); 1483 $retval .= '<option value="' . $A[0] . '"'; 1484 1485 if( is_array( $selected ) AND count( $selected ) > 0 ) 1486 { 1487 foreach( $selected as $selected_item ) 1488 { 1489 if( $A[0] == $selected_item ) 1490 { 1491 $retval .= ' selected="selected"'; 1492 } 1493 } 1494 } 1495 elseif( !is_array( $selected ) AND $A[0] == $selected ) 1496 { 1497 $retval .= ' selected="selected"'; 1498 } 1499 1500 $retval .= '>'; 1501 if( empty( $LangTable[$A[0]] )) 1502 { 1503 $retval .= $A[1]; 1504 } 1505 else 1506 { 1507 $retval .= $LangTable[$A[0]]; 1508 } 1509 $retval .= '</option>' . LB; 1510 } 1511 1512 return $retval; 1513 } 1514 1515 /** 1516 * Create and return a dropdown-list of available topics 1517 * 1518 * This is a variation of COM_optionList() from lib-common.php. It will add 1519 * only those topics to the option list which are accessible by the current 1520 * user. 1521 * 1522 * @param string $selection Comma delimited string of fields to pull The first field is the value of the option and the second is the label to be displayed. This is used in a SQL statement and can include DISTINCT to start. 1523 * @param string $selected Value (from $selection) to set to SELECTED or default 1524 * @param int $sortcol Which field to sort option list by 0 (value) or 1 (label) 1525 * @see function COM_optionList 1526 * @return string Formated HTML of option values 1527 * 1528 */ 1529 1530 function COM_topicList( $selection, $selected = '', $sortcol = 1, $ignorelang = false ) 1531 { 1532 global $_TABLES; 1533 1534 $retval = ''; 1535 1536 $tmp = str_replace( 'DISTINCT ', '', $selection ); 1537 $select_set = explode( ',', $tmp ); 1538 1539 $sql = "SELECT $selection FROM {$_TABLES['topics']}"; 1540 if( $ignorelang ) 1541 { 1542 $sql .= COM_getPermSQL(); 1543 } 1544 else 1545 { 1546 $permsql = COM_getPermSQL(); 1547 if( empty( $permsql )) 1548 { 1549 $sql .= COM_getLangSQL( 'tid' ); 1550 } 1551 else 1552 { 1553 $sql .= $permsql . COM_getLangSQL( 'tid', 'AND' ); 1554 } 1555 } 1556 $sql .= " ORDER BY $select_set[$sortcol]"; 1557 1558 $result = DB_query( $sql ); 1559 $nrows = DB_numRows( $result ); 1560 1561 for( $i = 0; $i < $nrows; $i++ ) 1562 { 1563 $A = DB_fetchArray( $result, true ); 1564 $retval .= '<option value="' . $A[0] . '"'; 1565 1566 if( $A[0] == $selected ) 1567 { 1568 $retval .= ' selected="selected"'; 1569 } 1570 1571 $retval .= '>' . stripslashes( $A[1] ) . '</option>' . LB; 1572 } 1573 1574 return $retval; 1575 } 1576 1577 /** 1578 * Creates a <input> checklist from a database list for use in forms 1579 * 1580 * Creates a group of checkbox form fields with given arguments 1581 * 1582 * @param string $table DB Table to pull data from 1583 * @param string $selection Comma delimited list of fields to pull from table 1584 * @param string $where Where clause of SQL statement 1585 * @param string $selected Value to set to CHECKED 1586 * @see function COM_optionList 1587 * @return string HTML with Checkbox code 1588 * 1589 */ 1590 1591 function COM_checkList( $table, $selection, $where='', $selected='' ) 1592 { 1593 global $_TABLES, $_COM_VERBOSE; 1594 1595 $retval = ''; 1596 1597 $sql = "SELECT $selection FROM $table"; 1598 1599 if( !empty( $where )) 1600 { 1601 $sql .= " WHERE $where"; 1602 } 1603 1604 $result = DB_query( $sql ); 1605 $nrows = DB_numRows( $result ); 1606 1607 if( !empty( $selected )) 1608 { 1609 if( $_COM_VERBOSE ) 1610 { 1611 COM_errorLog( "exploding selected array: $selected in COM_checkList", 1 ); 1612 } 1613 1614 $S = explode( ' ', $selected ); 1615 } 1616 else 1617 { 1618 if( $_COM_VERBOSE) 1619 { 1620 COM_errorLog( 'selected string was empty COM_checkList', 1 ); 1621 } 1622 1623 $S = array(); 1624 } 1625 1626 for( $i = 0; $i < $nrows; $i++ ) 1627 { 1628 $access = true; 1629 $A = DB_fetchArray( $result, true ); 1630 1631 if( $table == $_TABLES['topics'] AND SEC_hasTopicAccess( $A['tid'] ) == 0 ) 1632 { 1633 $access = false; 1634 } 1635 1636 if( $access ) 1637 { 1638 $retval .= '<input type="checkbox" name="' . $table . '[]" value="' . $A[0] . '"'; 1639 1640 for( $x = 0; $x < sizeof( $S ); $x++ ) 1641 { 1642 if( $A[0] == $S[$x] ) 1643 { 1644 $retval .= ' checked="checked"'; 1645 } 1646 } 1647 1648 if(( $table == $_TABLES['blocks'] ) && isset( $A[2] ) && ( $A[2] == 'gldefault' )) 1649 { 1650 $retval .= '><b>' . stripslashes( $A[1] ) . '</b><br>' . LB; 1651 } 1652 else 1653 { 1654 $retval .= '>' . stripslashes( $A[1] ) . '<br>' . LB; 1655 } 1656 } 1657 } 1658 1659 return $retval; 1660 } 1661 1662 /** 1663 * Prints out an associative array for debugging 1664 * 1665 * The core of this code has been lifted from phpweblog which is licenced 1666 * under the GPL. This is not used very much in the code but you can use it 1667 * if you see fit 1668 * 1669 * @param array $A Array to loop through and print values for 1670 * @return string Formated HTML List 1671 * 1672 */ 1673 1674 function COM_debug( $A ) 1675 { 1676 if( !empty( $A )) 1677 { 1678 $retval .= LB . '<pre><p>---- DEBUG ----</p>'; 1679 1680 for( reset( $A ); $k = key( $A ); next( $A )) 1681 { 1682 $retval .= sprintf( "<li>%13s [%s]</li>\n", $k, $A[$k] ); 1683 } 1684 1685 $retval .= '<p>---------------</p></pre>' . LB; 1686 } 1687 1688 return $retval; 1689 } 1690 1691 /** 1692 * 1693 * Checks to see if RDF file needs updating and updates it if so. 1694 * Checks to see if we need to update the RDF as a result 1695 * of an article with a future publish date reaching it's 1696 * publish time and if so updates the RDF file. 1697 * 1698 * @param string $updated_type (optional) feed type to update 1699 * @param string $updated_topic (optional) feed topic to update 1700 * @param string $updated_id (optional) feed id to update 1701 * 1702 * @note When called without parameters, this will only check for new entries to 1703 * include in the feeds. Pass the $updated_XXX parameters when the content 1704 * of an existing entry has changed. 1705 * 1706 * @see file lib-syndication.php 1707 * 1708 */ 1709 function COM_rdfUpToDateCheck( $updated_type = '', $updated_topic = '', $updated_id = '' ) 1710 { 1711 global $_CONF, $_TABLES; 1712 1713 if( $_CONF['backend'] > 0 ) 1714 { 1715 if( !empty( $updated_type ) && ( $updated_type != 'geeklog' )) 1716 { 1717 // when a plugin's feed is to be updated, skip Geeklog's own feeds 1718 $sql = "SELECT fid,type,topic,limits,update_info FROM {$_TABLES['syndication']} WHERE (is_enabled = 1) AND (type <> 'geeklog')"; 1719 } 1720 else 1721 { 1722 $sql = "SELECT fid,type,topic,limits,update_info FROM {$_TABLES['syndication']} WHERE is_enabled = 1"; 1723 } 1724 $result = DB_query( $sql ); 1725 $num = DB_numRows( $result ); 1726 for( $i = 0; $i < $num; $i++) 1727 { 1728 $A = DB_fetchArray( $result ); 1729 1730 $is_current = true; 1731 if( $A['type'] == 'geeklog' ) 1732 { 1733 $is_current = SYND_feedUpdateCheck( $A['topic'], 1734 $A['update_info'], $A['limits'], 1735 $updated_topic, $updated_id ); 1736 } 1737 else 1738 { 1739 $is_current = PLG_feedUpdateCheck( $A['type'], $A['fid'], 1740 $A['topic'], $A['update_info'], $A['limits'], 1741 $updated_type, $updated_topic, $updated_id ); 1742 } 1743 if( !$is_current ) 1744 { 1745 SYND_updateFeed( $A['fid'] ); 1746 } 1747 } 1748 } 1749 } 1750 1751 /** 1752 * Checks and Updates the featured status of all articles. 1753 * 1754 * Checks to see if any articles that were published for the future have been 1755 * published and, if so, will see if they are featured. If they are featured, 1756 * this will set old featured article (if there is one) to normal 1757 * 1758 */ 1759 1760 function COM_featuredCheck() 1761 { 1762 global $_TABLES; 1763 1764 $curdate = date( "Y-m-d H:i:s", time() ); 1765 1766 if( DB_getItem( $_TABLES['stories'], 'count(*)', "featured = 1 AND draft_flag = 0 AND date <= '$curdate'" ) > 1 ) 1767 { 1768 // OK, we have two featured stories, fix that 1769 1770 $sid = DB_getItem( $_TABLES['stories'], 'sid', "featured = 1 AND draft_flag = 0 ORDER BY date LIMIT 1" ); 1771 DB_query( "UPDATE {$_TABLES['stories']} SET featured = 0 WHERE sid = '$sid'" ); 1772 } 1773 } 1774 1775 /** 1776 * 1777 * Logs messages to error.log or the web page or both 1778 * 1779 * Prints a well formatted message to either the web page, error log 1780 * or both. 1781 * 1782 * @param string $logentry Text to log to error log 1783 * @param int $actionid 1 = write to log file, 2 = write to screen (default) both 1784 * @see function COM_accessLog 1785 * @return string If $actionid = 2 or '' then HTML formatted string (wrapped in block) else nothing 1786 * 1787 */ 1788 1789 function COM_errorLog( $logentry, $actionid = '' ) 1790 { 1791 global $_CONF, $LANG01; 1792 1793 $retval = ''; 1794 1795 if( !empty( $logentry )) 1796 { 1797 $logentry = str_replace( array( '<?', '?>' ), array( '(@', '@)' ), 1798 $logentry ); 1799 1800 $timestamp = strftime( '%c' ); 1801 1802 switch( $actionid ) 1803 { 1804 case 1: 1805 $logfile = $_CONF['path_log'] . 'error.log'; 1806 1807 if( !$file = fopen( $logfile, 'a' )) 1808 { 1809 $retval .= $LANG01[33] . ' ' . $logfile . ' (' . $timestamp . ')<br>' . LB; 1810 } 1811 else 1812 { 1813 fputs( $file, "$timestamp - $logentry \n" ); 1814 } 1815 break; 1816 1817 case 2: 1818 $retval .= COM_startBlock( $LANG01[55] . ' ' . $timestamp, '', 1819 COM_getBlockTemplate( '_msg_block', 'header' )) 1820 . nl2br( $logentry ) 1821 . COM_endBlock( COM_getBlockTemplate( '_msg_block', 1822 'footer' )); 1823 break; 1824 1825 default: 1826 $logfile = $_CONF['path_log'] . 'error.log'; 1827 1828 if( !$file = fopen( $logfile, 'a' )) 1829 { 1830 $retval .= $LANG01[33] . ' ' . $logfile . ' (' . $timestamp . ')<br>' . LB; 1831 } 1832 else 1833 { 1834 fputs( $file, "$timestamp - $logentry \n" ); 1835 $retval .= COM_startBlock( $LANG01[34] . ' - ' . $timestamp, 1836 '', COM_getBlockTemplate( '_msg_block', 1837 'header' )) 1838 . nl2br( $logentry ) 1839 . COM_endBlock( COM_getBlockTemplate( '_msg_block', 1840 'footer' )); 1841 } 1842 break; 1843 } 1844 } 1845 1846 return $retval; 1847 } 1848 1849 /** 1850 * Logs message to access.log 1851 * 1852 * This will print a message to the Geeklog access log 1853 * 1854 * @param string $string Message to write to access log 1855 * @see COM_errorLog 1856 * 1857 */ 1858 1859 function COM_accessLog( $logentry ) 1860 { 1861 global $_CONF, $_USER, $LANG01; 1862 1863 $retval = ''; 1864 1865 if( !empty( $logentry )) 1866 { 1867 $logentry = str_replace( array( '<?', '?>' ), array( '(@', '@)' ), 1868 $logentry ); 1869 1870 $timestamp = strftime( '%c' ); 1871 $logfile = $_CONF['path_log'] . 'access.log'; 1872 1873 if( !$file = fopen( $logfile, 'a' )) 1874 { 1875 return $LANG01[33] . $logfile . ' (' . $timestamp . ')<br>' . LB; 1876 } 1877 1878 if( isset( $_USER['uid'] )) 1879 { 1880 $byuser = $_USER['uid'] . '@' . $_SERVER['REMOTE_ADDR']; 1881 } 1882 else 1883 { 1884 $byuser = 'anon@' . $_SERVER['REMOTE_ADDR']; 1885 } 1886 1887 fputs( $file, "$timestamp ($byuser) - $logentry\n" ); 1888 } 1889 1890 return $retval; 1891 } 1892 1893 /** 1894 * Shows all available topics 1895 * 1896 * Show the topics in the system the user has access to and prints them in HTML. 1897 * This function is used to show the topics in the topics block. 1898 * 1899 * @param string $topic ID of currently selected topic 1900 * @return string HTML formatted topic list 1901 * 1902 */ 1903 1904 function COM_showTopics( $topic='' ) 1905 { 1906 global $_CONF, $_TABLES, $_USER, $LANG01, $_BLOCK_TEMPLATE, $page; 1907 1908 $langsql = COM_getLangSQL( 'tid' ); 1909 if( empty( $langsql )) 1910 { 1911 $op = 'WHERE'; 1912 } 1913 else 1914 { 1915 $op = 'AND'; 1916 } 1917 1918 $sql = "SELECT tid,topic,imageurl FROM {$_TABLES['topics']}" . $langsql; 1919 if( !empty( $_USER['uid'] ) && ( $_USER['uid'] > 1 )) 1920 { 1921 $tids = DB_getItem( $_TABLES['userindex'], 'tids', 1922 "uid = '{$_USER['uid']}'" ); 1923 if( !empty( $tids )) 1924 { 1925 $sql .= " $op (tid NOT IN ('" . str_replace( ' ', "','", $tids ) 1926 . "'))" . COM_getPermSQL( 'AND' ); 1927 } 1928 else 1929 { 1930 $sql .= COM_getPermSQL( $op ); 1931 } 1932 } 1933 else 1934 { 1935 $sql .= COM_getPermSQL( $op ); 1936 } 1937 if( $_CONF['sortmethod'] == 'alpha' ) 1938 { 1939 $sql .= ' ORDER BY topic ASC'; 1940 } 1941 else 1942 { 1943 $sql .= ' ORDER BY sortnum'; 1944 } 1945 $result = DB_query( $sql ); 1946 1947 $retval = ''; 1948 $sections = new Template( $_CONF['path_layout'] ); 1949 if( isset( $_BLOCK_TEMPLATE['topicoption'] )) 1950 { 1951 $templates = explode( ',', $_BLOCK_TEMPLATE['topicoption'] ); 1952 $sections->set_file( array( 'option' => $templates[0], 1953 'current' => $templates[1] )); 1954 } 1955 else 1956 { 1957 $sections->set_file( array( 'option' => 'topicoption.thtml', 1958 'inactive' => 'topicoption_off.thtml' )); 1959 } 1960 $sections->set_var( 'site_url', $_CONF['site_url'] ); 1961 $sections->set_var( 'layout_url', $_CONF['layout_url'] ); 1962 $sections->set_var( 'block_name', str_replace( '_', '-', 'section_block' )); 1963 1964 if( $_CONF['hide_home_link'] == 0 ) 1965 { 1966 // Give a link to the homepage here since a lot of people use this for 1967 // navigating the site 1968 1969 if( COM_onFrontpage() ) 1970 { 1971 $sections->set_var( 'option_url', '' ); 1972 $sections->set_var( 'option_label', $LANG01[90] ); 1973 $sections->set_var( 'option_count', '' ); 1974 $sections->set_var( 'topic_image', '' ); 1975 $retval .= $sections->parse( 'item', 'inactive' ); 1976 } 1977 else 1978 { 1979 $sections->set_var( 'option_url', 1980 $_CONF['site_url'] . '/index.php' ); 1981 $sections->set_var( 'option_label', $LANG01[90] ); 1982 $sections->set_var( 'option_count', '' ); 1983 $sections->set_var( 'topic_image', '' ); 1984 $retval .= $sections->parse( 'item', 'option' ); 1985 } 1986 } 1987 1988 if( $_CONF['showstorycount'] ) 1989 { 1990 $sql = "SELECT tid, COUNT(*) AS count FROM {$_TABLES['stories']} " 1991 . 'WHERE (draft_flag = 0) AND (date <= NOW()) ' 1992 . COM_getPermSQL( 'AND' ) 1993 . ' GROUP BY tid'; 1994 $rcount = DB_query( $sql ); 1995 while( $C = DB_fetchArray( $rcount )) 1996 { 1997 $storycount[$C['tid']] = $C['count']; 1998 } 1999 } 2000 2001 if( $_CONF['showsubmissioncount'] ) 2002 { 2003 $sql = "SELECT tid, COUNT(*) AS count FROM {$_TABLES['storysubmission']} " 2004 . ' GROUP BY tid'; 2005 $rcount = DB_query( $sql ); 2006 while( $C = DB_fetchArray( $rcount )) 2007 { 2008 $submissioncount[$C['tid']] = $C['count']; 2009 } 2010 } 2011 2012 while( $A = DB_fetchArray( $result ) ) 2013 { 2014 $topicname = stripslashes( $A['topic'] ); 2015 $sections->set_var( 'option_url', $_CONF['site_url'] 2016 . '/index.php?topic=' . $A['tid'] ); 2017 $sections->set_var( 'option_label', $topicname ); 2018 2019 $countstring = ''; 2020 if( $_CONF['showstorycount'] || $_CONF['showsubmissioncount'] ) 2021 { 2022 $countstring .= '('; 2023 2024 if( $_CONF['showstorycount'] ) 2025 { 2026 if( empty( $storycount[$A['tid']] )) 2027 { 2028 $countstring .= 0; 2029 } 2030 else 2031 { 2032 $countstring .= COM_numberFormat( $storycount[$A['tid']] ); 2033 } 2034 } 2035 2036 if( $_CONF['showsubmissioncount'] ) 2037 { 2038 if( $_CONF['showstorycount'] ) 2039 { 2040 $countstring .= '/'; 2041 } 2042 if( empty( $submissioncount[$A['tid']] )) 2043 { 2044 $countstring .= 0; 2045 } 2046 else 2047 { 2048 $countstring .= COM_numberFormat( $submissioncount[$A['tid']] ); 2049 } 2050 } 2051 2052 $countstring .= ')'; 2053 } 2054 $sections->set_var( 'option_count', $countstring ); 2055 2056 $topicimage = ''; 2057 if( !empty( $A['imageurl'] )) 2058 { 2059 $imageurl = COM_getTopicImageUrl( $A['imageurl'] ); 2060 $topicimage = '<img src="' . $imageurl . '" alt="' . $topicname 2061 . '" title="' . $topicname . '" border="0">'; 2062 } 2063 $sections->set_var( 'topic_image', $topicimage ); 2064 2065 if(( $A['tid'] == $topic ) && ( $page == 1 )) 2066 { 2067 $retval .= $sections->parse( 'item', 'inactive' ); 2068 } 2069 else 2070 { 2071 $retval .= $sections->parse( 'item', 'option' ); 2072 } 2073 } 2074 2075 return $retval; 2076 } 2077 2078 /** 2079 * Shows the user their menu options 2080 * 2081 * This shows the average joe use their menu options. This is the user block on right side 2082 * 2083 * @param string $help Help file to show 2084 * @param string $title Title of Menu 2085 * @see function COM_adminMenu 2086 * 2087 */ 2088 2089 function COM_userMenu( $help='', $title='' ) 2090 { 2091 global $_TABLES, $_USER, $_CONF, $LANG01, $LANG04, $_BLOCK_TEMPLATE; 2092 2093 $retval = ''; 2094 2095 if( !empty( $_USER['uid'] ) && ( $_USER['uid'] > 1 )) 2096 { 2097 $usermenu = new Template( $_CONF['path_layout'] ); 2098 if( isset( $_BLOCK_TEMPLATE['useroption'] )) 2099 { 2100 $templates = explode( ',', $_BLOCK_TEMPLATE['useroption'] ); 2101 $usermenu->set_file( array( 'option' => $templates[0], 2102 'current' => $templates[1] )); 2103 } 2104 else 2105 { 2106 $usermenu->set_file( array( 'option' => 'useroption.thtml', 2107 'current' => 'useroption_off.thtml' )); 2108 } 2109 $usermenu->set_var( 'site_url', $_CONF['site_url'] ); 2110 $usermenu->set_var( 'layout_url', $_CONF['layout_url'] ); 2111 $usermenu->set_var( 'block_name', str_replace( '_', '-', 'user_block' )); 2112 2113 if( empty( $title )) 2114 { 2115 $title = DB_getItem( $_TABLES['blocks'], 'title', 2116 "name='user_block'" ); 2117 } 2118 2119 // what's our current URL? 2120 $thisUrl = COM_getCurrentURL(); 2121 2122 $retval .= COM_startBlock( $title, $help, 2123 COM_getBlockTemplate( 'user_block', 'header' )); 2124 2125 // This function will show the user options for all installed plugins 2126 // (if any) 2127 2128 $plugin_options = PLG_getUserOptions(); 2129 $nrows = count( $plugin_options ); 2130 2131 for( $i = 0; $i < $nrows; $i++ ) 2132 { 2133 $plg = current( $plugin_options ); 2134 $usermenu->set_var( 'option_label', $plg->adminlabel ); 2135 2136 if( !empty( $plg->numsubmissions )) 2137 { 2138 $usermenu->set_var( 'option_count', '(' . $plg->numsubmissions . ')' ); 2139 } 2140 else 2141 { 2142 $usermenu->set_var( 'option_count', '' ); 2143 } 2144 2145 $usermenu->set_var( 'option_url', $plg->adminurl ); 2146 if( $thisUrl == $plg->adminurl ) 2147 { 2148 $retval .= $usermenu->parse( 'item', 'current' ); 2149 } 2150 else 2151 { 2152 $retval .= $usermenu->parse( 'item', 'option' ); 2153 } 2154 next( $plugin_options ); 2155 } 2156 2157 $url = $_CONF['site_url'] . '/usersettings.php?mode=edit'; 2158 $usermenu->set_var( 'option_label', $LANG01[48] ); 2159 $usermenu->set_var( 'option_count', '' ); 2160 $usermenu->set_var( 'option_url', $url ); 2161 if( $thisUrl == $url ) 2162 { 2163 $retval .= $usermenu->parse( 'item', 'current' ); 2164 } 2165 else 2166 { 2167 $retval .= $usermenu->parse( 'item', 'option' ); 2168 } 2169 2170 $url = $_CONF['site_url'] . '/users.php?mode=logout'; 2171 $usermenu->set_var( 'option_label', $LANG01[19] ); 2172 $usermenu->set_var( 'option_count', '' ); 2173 $usermenu->set_var( 'option_url', $url ); 2174 $retval .= $usermenu->parse( 'item', 'option' ); 2175 2176 $retval .= COM_endBlock( COM_getBlockTemplate( 'user_block', 'footer' )); 2177 } 2178 else 2179 { 2180 $retval .= COM_startBlock( $LANG01[47], $help, 2181 COM_getBlockTemplate( 'user_block', 'header' )); 2182 2183 $login = new Template( $_CONF['path_layout'] ); 2184 $login->set_file( 'form', 'loginform.thtml' ); 2185 $login->set_var( 'site_url', $_CONF['site_url'] ); 2186 $login->set_var( 'layout_url', $_CONF['layout_url'] ); 2187 $login->set_var( 'lang_username', $LANG01[21] ); 2188 $login->set_var( 'lang_password', $LANG01[57] ); 2189 $login->set_var( 'lang_forgetpassword', $LANG01[119] ); 2190 $login->set_var( 'lang_login', $LANG01[58] ); 2191 if( $_CONF['disable_new_user_registration'] == 1 ) 2192 { 2193 $login->set_var( 'lang_signup', '' ); 2194 } 2195 else 2196 { 2197 $login->set_var( 'lang_signup', $LANG01[59] ); 2198 } 2199 if( $_CONF['remoteauthentication'] && !$_CONF['usersubmission'] ) 2200 { 2201 // Build select 2202 $select = '<select name="service" id="service"><option value="">' . 2203 $_CONF['site_name'] . '</option>'; 2204 if( is_dir( $_CONF['path_system'] . 'classes/authentication/' )) 2205 { 2206 $folder = opendir( $_CONF['path_system'] 2207 . 'classes/authentication/' ); 2208 while(( $filename = @readdir( $folder )) !== false ) 2209 { 2210 $strpos = strpos( $filename, '.auth.class.php' ); 2211 if( $strpos ) 2212 { 2213 $service = substr( $filename, 0, $strpos ); 2214 $select .= '<option value="' . $service . '">' 2215 . $service . '</option>'; 2216 } 2217 } 2218 } 2219 $select .= '</select>'; 2220 $login->set_file( 'services', 'blockservices.thtml' ); 2221 $login->set_var( 'lang_service', $LANG04[121] ); 2222 $login->set_var( 'select_service', $select ); 2223 $login->parse( 'output', 'services' ); 2224 $login->set_var( 'services', 2225 $login->finish( $login->get_var( 'output' ))); 2226 } 2227 else 2228 { 2229 $login->set_var( 'services', '' ); 2230 } 2231 $retval .= $login->parse( 'output', 'form' ); 2232 2233 $retval .= COM_endBlock( COM_getBlockTemplate( 'user_block', 'footer' )); 2234 } 2235 2236 return $retval; 2237 } 2238 2239 /** 2240 * Prints administration menu 2241 * 2242 * This will return the administration menu items that the user has 2243 * sufficient rights to -- Admin Block on right side. 2244 * 2245 * @param string $help Help file to show 2246 * @param string $title Menu Title 2247 * @see function COM_userMenu 2248 * 2249 */ 2250 2251 function COM_adminMenu( $help = '', $title = '' ) 2252 { 2253 global $_TABLES, $_USER, $_CONF, $LANG01, $_BLOCK_TEMPLATE, $LANG_PDF, 2254 $_DB_dbms; 2255 2256 $retval = ''; 2257 2258 if( empty( $_USER['username'] )) 2259 { 2260 return $retval; 2261 } 2262 2263 $plugin_options = PLG_getAdminOptions(); 2264 $num_plugins = count( $plugin_options ); 2265 2266 if( SEC_isModerator() OR SEC_hasRights( 'story.edit,block.edit,topic.edit,user.edit,plugin.edit,user.mail,syndication.edit', 'OR' ) OR ( $num_plugins > 0 )) 2267 { 2268 // what's our current URL? 2269 $thisUrl = COM_getCurrentURL(); 2270 2271 $adminmenu = new Template( $_CONF['path_layout'] ); 2272 if( isset( $_BLOCK_TEMPLATE['adminoption'] )) 2273 { 2274 $templates = explode( ',', $_BLOCK_TEMPLATE['adminoption'] ); 2275 $adminmenu->set_file( array( 'option' => $templates[0], 2276 'current' => $templates[1] )); 2277 } 2278 else 2279 { 2280 $adminmenu->set_file( array( 'option' => 'adminoption.thtml', 2281 'current' => 'adminoption_off.thtml' )); 2282 } 2283 $adminmenu->set_var( 'site_url', $_CONF['site_url'] ); 2284 $adminmenu->set_var( 'layout_url', $_CONF['layout_url'] ); 2285 $adminmenu->set_var( 'block_name', str_replace( '_', '-', 'admin_block' )); 2286 2287 if( empty( $title )) 2288 { 2289 $title = DB_getItem( $_TABLES['blocks'], 'title', 2290 "name = 'admin_block'" ); 2291 } 2292 2293 $retval .= COM_startBlock( $title, $help, 2294 COM_getBlockTemplate( 'admin_block', 'header' )); 2295 2296 $topicsql = ''; 2297 if( SEC_isModerator() || SEC_hasRights( 'story.edit' )) 2298 { 2299 $tresult = DB_query( "SELECT tid FROM {$_TABLES['topics']}" 2300 . COM_getPermSQL() ); 2301 $trows = DB_numRows( $tresult ); 2302 if( $trows > 0 ) 2303 { 2304 $tids = array(); 2305 for( $i = 0; $i < $trows; $i++ ) 2306 { 2307 $T = DB_fetchArray( $tresult ); 2308 $tids[] = $T['tid']; 2309 } 2310 if( sizeof( $tids ) > 0 ) 2311 { 2312 $topicsql = " (tid IN ('" . implode( "','", $tids ) . "'))"; 2313 } 2314 } 2315 } 2316 2317 $modnum = 0; 2318 if( SEC_hasRights( 'story.edit,story.moderate', 'OR' ) || (( $_CONF['usersubmission'] == 1 ) && SEC_hasRights( 'user.edit,user.delete' ))) 2319 { 2320 2321 if( SEC_hasRights( 'story.moderate' )) 2322 { 2323 if( empty( $topicsql )) 2324 { 2325 $modnum += DB_count( $_TABLES['storysubmission'] ); 2326 } 2327 else 2328 { 2329 $sresult = DB_query( "SELECT COUNT(*) AS count FROM {$_TABLES['storysubmission']} WHERE" . $topicsql ); 2330 $S = DB_fetchArray( $sresult ); 2331 $modnum += $S['count']; 2332 } 2333 } 2334 2335 if(( $_CONF['listdraftstories'] == 1 ) && SEC_hasRights( 'story.edit' )) 2336 { 2337 $sql = "SELECT COUNT(*) AS count FROM {$_TABLES['stories']} WHERE (draft_flag = 1)"; 2338 if( !empty( $topicsql )) 2339 { 2340 $sql .= ' AND' . $topicsql; 2341 } 2342 $result = DB_query( $sql . COM_getPermSQL( 'AND', 0, 3 )); 2343 $A = DB_fetchArray( $result ); 2344 $modnum += $A['count']; 2345 } 2346 2347 if( $_CONF['usersubmission'] == 1 ) 2348 { 2349 if( SEC_hasRights( 'user.edit' ) && SEC_hasRights( 'user.delete' )) 2350 { 2351 $modnum += DB_count( $_TABLES['users'], 'status', '2' ); 2352 } 2353 } 2354 } 2355 2356 // now handle submissions for plugins 2357 $modnum += PLG_getSubmissionCount(); 2358 2359 if( SEC_hasRights( 'story.edit' )) 2360 { 2361 $url = $_CONF['site_admin_url'] . '/story.php'; 2362 $adminmenu->set_var( 'option_url', $url ); 2363 $adminmenu->set_var( 'option_label', $LANG01[11] ); 2364 if( empty( $topicsql )) 2365 { 2366 $numstories = DB_count( $_TABLES['stories'] ); 2367 } 2368 else 2369 { 2370 $nresult = DB_query( "SELECT COUNT(*) AS count from {$_TABLES['stories']} WHERE" . $topicsql . COM_getPermSql( 'AND' )); 2371 $N = DB_fetchArray( $nresult ); 2372 $numstories = $N['count']; 2373 } 2374 $adminmenu->set_var( 'option_count', 2375 COM_numberFormat( $numstories )); 2376 $menu_item = $adminmenu->parse( 'item', 2377 ( $thisUrl == $url ) ? 'current' : 'option' ); 2378 $link_array[$LANG01[11]] = $menu_item; 2379 } 2380 2381 if( SEC_hasRights( 'block.edit' )) 2382 { 2383 $result = DB_query( "SELECT COUNT(*) AS count FROM {$_TABLES['blocks']}" . COM_getPermSql()); 2384 list( $count ) = DB_fetchArray( $result ); 2385 2386 $url = $_CONF['site_admin_url'] . '/block.php'; 2387 $adminmenu->set_var( 'option_url', $url ); 2388 $adminmenu->set_var( 'option_label', $LANG01[12] ); 2389 $adminmenu->set_var( 'option_count', COM_numberFormat( $count )); 2390 2391 $menu_item = $adminmenu->parse( 'item', 2392 ( $thisUrl == $url ) ? 'current' : 'option' ); 2393 $link_array[$LANG01[12]] = $menu_item; 2394 } 2395 2396 if( SEC_hasRights( 'topic.edit' )) 2397 { 2398 $result = DB_query( "SELECT COUNT(*) AS count FROM {$_TABLES['topics']}" . COM_getPermSql()); 2399 list( $count ) = DB_fetchArray( $result ); 2400 2401 $url = $_CONF['site_admin_url'] . '/topic.php'; 2402 $adminmenu->set_var( 'option_url', $url ); 2403 $adminmenu->set_var( 'option_label', $LANG01[13] ); 2404 $adminmenu->set_var( 'option_count', COM_numberFormat( $count )); 2405 2406 $menu_item = $adminmenu->parse( 'item', 2407 ( $thisUrl == $url ) ? 'current' : 'option' ); 2408 $link_array[$LANG01[13]] = $menu_item; 2409 } 2410 2411 if( SEC_hasRights( 'user.edit' )) 2412 { 2413 $url = $_CONF['site_admin_url'] . '/user.php'; 2414 $adminmenu->set_var( 'option_url', $url ); 2415 $adminmenu->set_var( 'option_label', $LANG01[17] ); 2416 $adminmenu->set_var( 'option_count', 2417 COM_numberFormat( DB_count( $_TABLES['users'] ) -1 )); 2418 2419 $menu_item = $adminmenu->parse( 'item', 2420 ( $thisUrl == $url ) ? 'current' : 'option' ); 2421 $link_array[$LANG01[17]] = $menu_item; 2422 } 2423 2424 if( SEC_hasRights( 'group.edit' )) 2425 { 2426 if (SEC_inGroup('Root')) { 2427 $grpFilter = ''; 2428 } else { 2429 $thisUsersGroups = SEC_getUserGroups (); 2430 $grpFilter = 'WHERE (grp_id IN (' . implode (',', $thisUsersGroups) . '))'; 2431 } 2432 $result = DB_query( "SELECT COUNT(*) AS count FROM {$_TABLES['groups']} $grpFilter;" ); 2433 $A = DB_fetchArray( $result ); 2434 2435 $url = $_CONF['site_admin_url'] . '/group.php'; 2436 $adminmenu->set_var( 'option_url', $url ); 2437 $adminmenu->set_var( 'option_label', $LANG01[96] ); 2438 $adminmenu->set_var( 'option_count', 2439 COM_numberFormat( $A['count'] )); 2440 2441 $menu_item = $adminmenu->parse( 'item', 2442 ( $thisUrl == $url ) ? 'current' : 'option' ); 2443 $link_array[$LANG01[96]] = $menu_item; 2444 } 2445 2446 if( SEC_hasRights( 'user.mail' )) 2447 { 2448 $url = $_CONF['site_admin_url'] . '/mail.php'; 2449 $adminmenu->set_var( 'option_url', $url ); 2450 $adminmenu->set_var( 'option_label', $LANG01[105] ); 2451 $adminmenu->set_var( 'option_count', 'N/A' ); 2452 2453 $menu_item = $adminmenu->parse( 'item', 2454 ( $thisUrl == $url ) ? 'current' : 'option' ); 2455 $link_array[$LANG01[105]] = $menu_item; 2456 } 2457 2458 if(( $_CONF['backend'] == 1 ) && SEC_hasRights( 'syndication.edit' )) 2459 { 2460 $url = $_CONF['site_admin_url'] . '/syndication.php'; 2461 $adminmenu->set_var( 'option_url', $url ); 2462 $adminmenu->set_var( 'option_label', $LANG01[38] ); 2463 $count = COM_numberFormat( DB_count( $_TABLES['syndication'] )); 2464 $adminmenu->set_var( 'option_count', $count ); 2465 2466 $menu_item = $adminmenu->parse( 'item', 2467 ( $thisUrl == $url ) ? 'current' : 'option' ); 2468 $link_array[$LANG01[38]] = $menu_item; 2469 } 2470 2471 if(( $_CONF['trackback_enabled'] || $_CONF['pingback_enabled'] || 2472 $_CONF['ping_enabled'] ) && SEC_hasRights( 'story.ping' )) 2473 { 2474 $url = $_CONF['site_admin_url'] . '/trackback.php'; 2475 $adminmenu->set_var( 'option_url', $url ); 2476 $adminmenu->set_var( 'option_label', $LANG01[116] ); 2477 if( $_CONF['ping_enabled'] ) 2478 { 2479 $count = COM_numberFormat( DB_count( $_TABLES['pingservice'] )); 2480 $adminmenu->set_var( 'option_count', $count ); 2481 } 2482 else 2483 { 2484 $adminmenu->set_var( 'option_count', 'N/A' ); 2485 } 2486 2487 $menu_item = $adminmenu->parse( 'item', 2488 ( $thisUrl == $url ) ? 'current' : 'option' ); 2489 $link_array[$LANG01[116]] = $menu_item; 2490 } 2491 2492 if( SEC_hasRights( 'plugin.edit' )) 2493 { 2494 $url = $_CONF['site_admin_url'] . '/plugins.php'; 2495 $adminmenu->set_var( 'option_url', $url ); 2496 $adminmenu->set_var( 'option_label', $LANG01[77] ); 2497 $adminmenu->set_var( 'option_count', 2498 COM_numberFormat( DB_count( $_TABLES['plugins'] ))); 2499 2500 $menu_item = $adminmenu->parse( 'item', 2501 ( $thisUrl == $url ) ? 'current' : 'option' ); 2502 $link_array[$LANG01[77]] = $menu_item; 2503 } 2504 2505 // This will show the admin options for all installed plugins (if any) 2506 2507 for( $i = 0; $i < $num_plugins; $i++ ) 2508 { 2509 $plg = current( $plugin_options ); 2510 2511 $adminmenu->set_var( 'option_url', $plg->adminurl ); 2512 $adminmenu->set_var( 'option_label', $plg->adminlabel ); 2513 2514 if( empty( $plg->numsubmissions )) 2515 { 2516 $adminmenu->set_var( 'option_count', 'N/A' ); 2517 } 2518 else 2519 { 2520 $adminmenu->set_var( 'option_count', 2521 COM_numberFormat( $plg->numsubmissions )); 2522 } 2523 2524 $menu_item = $adminmenu->parse( 'item', 2525 ( $thisUrl == $plg->adminurl ) ? 'current' : 'option', true ); 2526 $link_array[$plg->adminlabel] = $menu_item; 2527 2528 next( $plugin_options ); 2529 } 2530 2531 if(( $_CONF['allow_mysqldump'] == 1 ) AND ( $_DB_dbms == 'mysql' ) AND 2532 SEC_inGroup( 'Root' )) 2533 { 2534 $url = $_CONF['site_admin_url'] . '/database.php'; 2535 $adminmenu->set_var( 'option_url', $url ); 2536 $adminmenu->set_var( 'option_label', $LANG01[103] ); 2537 $adminmenu->set_var( 'option_count', 'N/A' ); 2538 2539 $menu_item = $adminmenu->parse( 'item', 2540 ( $thisUrl == $url ) ? 'current' : 'option' ); 2541 $link_array[$LANG01[103]] = $menu_item; 2542 } 2543 2544 // Add PDF Generator Link if the feature is enabled 2545 if(( $_CONF['pdf_enabled'] == 1 ) AND SEC_inGroup( 'Root' )) 2546 { 2547 $url = $_CONF['site_url'] . '/pdfgenerator.php'; 2548 $adminmenu->set_var( 'option_url', $url ); 2549 $adminmenu->set_var( 'option_label', $LANG_PDF[9] ); 2550 $adminmenu->set_var( 'option_count', 'N/A' ); 2551 2552 $menu_item = $adminmenu->parse( 'item', 2553 ( $thisUrl == $url ) ? 'current' : 'option' ); 2554 $link_array[$LANG_PDF[9]] = $menu_item; 2555 } 2556 2557 if( $_CONF['link_documentation'] == 1 ) 2558 { 2559 $adminmenu->set_var( 'option_url', 2560 $_CONF['site_url'] . '/docs/index.html' ); 2561 $adminmenu->set_var( 'option_label', $LANG01[113] ); 2562 $adminmenu->set_var( 'option_count', 'N/A' ); 2563 $menu_item = $adminmenu->parse( 'item', 'option' ); 2564 $link_array[$LANG01[113]] = $menu_item; 2565 } 2566 2567 if( SEC_inGroup( 'Root' )) 2568 { 2569 $adminmenu->set_var( 'option_url', 2570 'http://www.geeklog.net/versionchecker.php?version=' . VERSION ); 2571 $adminmenu->set_var( 'option_label', $LANG01[107] ); 2572 $adminmenu->set_var( 'option_count', VERSION ); 2573 2574 $menu_item = $adminmenu->parse( 'item', 'option' ); 2575 $link_array[$LANG01[107]] = $menu_item; 2576 } 2577 2578 if( $_CONF['sort_admin'] ) 2579 { 2580 uksort( $link_array, 'strcasecmp' ); 2581 } 2582 2583 $url = $_CONF['site_admin_url'] . '/moderation.php'; 2584 $adminmenu->set_var( 'option_url', $url ); 2585 $adminmenu->set_var( 'option_label', $LANG01[10] ); 2586 $adminmenu->set_var( 'option_count', COM_numberFormat( $modnum )); 2587 $menu_item = $adminmenu->parse( 'item', 2588 ( $thisUrl == $url ) ? 'current' : 'option' ); 2589 $link_array = array( $menu_item ) + $link_array; 2590 2591 foreach( $link_array as $link ) 2592 { 2593 $retval .= $link; 2594 } 2595 2596 $retval .= COM_endBlock( COM_getBlockTemplate( 'admin_block', 'footer' )); 2597 } 2598 2599 return $retval; 2600 } 2601 2602 /** 2603 * Redirects user to a given URL 2604 * 2605 * This function COM_passes a meta tag to COM_refresh after a form is sent. This is 2606 * necessary because for some reason Nutscrape and PHP4 don't play well with 2607 * the header() function COM_100% of the time. 2608 * 2609 * @param string $url URL to send user to 2610 * 2611 */ 2612 2613 function COM_refresh( $url ) 2614 { 2615 return "<html><head><meta http-equiv=\"refresh\" content=\"0; URL=$url\"></head></html>\n"; 2616 } 2617 2618 /** 2619 * DEPRECIATED -- see CMT_userComments in lib-comment.php 2620 */ 2621 function COM_userComments( $sid, $title, $type='article', $order='', $mode='', $pid = 0, $page = 1, $cid = false, $delete_option = false ) { 2622 global $_CONF; 2623 2624 require_once $_CONF['path_system'] . 'lib-comment.php'; 2625 return CMT_userComments( $sid, $title, $type, $order, $mode, $pid, $page, $cid, $delete_option ); 2626 } 2627 2628 /** 2629 * This censors inappropriate content 2630 * 2631 * This will replace 'bad words' with something more appropriate 2632 * 2633 * @param string $Message String to check 2634 * @see function COM_checkHTML 2635 * @return string Edited $Message 2636 * 2637 */ 2638 2639 function COM_checkWords( $Message ) 2640 { 2641 global $_CONF; 2642 2643 $EditedMessage = $Message; 2644 2645 if( $_CONF['censormode'] != 0 ) 2646 { 2647 if( is_array( $_CONF['censorlist'] )) 2648 { 2649 $Replacement = $_CONF['censorreplace']; 2650 2651 switch( $_CONF['censormode']) 2652 { 2653 case 1: # Exact match 2654 $RegExPrefix = '(\s*)'; 2655 $RegExSuffix = '(\W*)'; 2656 break; 2657 2658 case 2: # Word beginning 2659 $RegExPrefix = '(\s*)'; 2660 $RegExSuffix = '(\w*)'; 2661 break; 2662 2663 case 3: # Word fragment 2664 $RegExPrefix = '(\w*)'; 2665 $RegExSuffix = '(\w*)'; 2666 break; 2667 } 2668 2669 for( $i = 0; $i < count( $_CONF['censorlist']); $i++ ) 2670 { 2671 $EditedMessage = MBYTE_eregi_replace( $RegExPrefix . $_CONF['censorlist'][$i] . $RegExSuffix, "\\1$Replacement\\2", $EditedMessage ); 2672 } 2673 } 2674 } 2675 2676 return $EditedMessage; 2677 } 2678 2679 /** 2680 * Takes some amount of text and replaces all javascript events on*= with in 2681 * 2682 * This script takes some amount of text and matches all javascript events, on*= (onBlur= onMouseClick=) 2683 * and replaces them with in*= 2684 * Essentially this will cause onBlur to become inBlur, onFocus to be inFocus 2685 * These are not valid javascript events and the browser will ignore them. 2686 * @param string $Message Text to filter 2687 * @return string $Message with javascript filtered 2688 * @see COM_checkWords 2689 * @see COM_checkHTML 2690 * 2691 */ 2692 2693 function COM_killJS( $Message ) 2694 { 2695 return( preg_replace( '/(\s)+[oO][nN](\w*) ?=/', '\1in\2=', $Message )); 2696 } 2697 2698 /** 2699 * Handles the part within a [code] ... [/code] section, i.e. escapes all 2700 * special characters. 2701 * 2702 * @param string $str the code section to encode 2703 * @return string $str with the special characters encoded 2704 * @see COM_checkHTML 2705 * 2706 */ 2707 function COM_handleCode( $str ) 2708 { 2709 $search = array( '&', '\\', '<', '>', '[', ']' ); 2710 $replace = array( '&', '\', '<', '>', '[', ']' ); 2711 2712 $str = str_replace( $search, $replace, $str ); 2713 2714 return( $str ); 2715 } 2716 2717 /** 2718 * This function checks html tags. 2719 * 2720 * Checks to see that the HTML tags are on the approved list and 2721 * removes them if not. 2722 * 2723 * @param string $str HTML to check 2724 * @param string $permissions comma-separated list of rights which identify the current user as an "Admin" 2725 * @return string Filtered HTML 2726 * 2727 */ 2728 function COM_checkHTML( $str, $permissions = 'story.edit' ) 2729 { 2730 global $_CONF; 2731 2732 // replace any \ with \ (HTML equiv) 2733 $str = str_replace('\\', '\', COM_stripslashes($str) ); 2734 2735 // Get rid of any newline characters 2736 $str = preg_replace( "/\n/", '', $str ); 2737 2738 // Replace any $ with $ (HTML equiv) 2739 $str = str_replace( '$', '$', $str ); 2740 // handle [code] ... [/code] 2741 do 2742 { 2743 $start_pos = MBYTE_strpos( MBYTE_strtolower( $str ), '[code]' ); 2744 if( $start_pos !== false ) 2745 { 2746 $end_pos = MBYTE_strpos( MBYTE_strtolower( $str ), '[/code]' ); 2747 if( $end_pos !== false ) 2748 { 2749 $encoded = COM_handleCode( MBYTE_substr( $str, $start_pos + 6, 2750 $end_pos - ( $start_pos + 6 ))); 2751 $encoded = '<pre><code>' . $encoded . '</code></pre>'; 2752 $str = MBYTE_substr( $str, 0, $start_pos ) . $encoded 2753 . MBYTE_substr( $str, $end_pos + 7 ); 2754 } 2755 else // missing [/code] 2756 { 2757 // Treat the rest of the text as code (so as not to lose any 2758 // special characters). However, the calling entity should 2759 // better be checking for missing [/code] before calling this 2760 // function ... 2761 $encoded = COM_handleCode( MBYTE_substr( $str, $start_pos + 6 )); 2762 $encoded = '<pre><code>' . $encoded . '</code></pre>'; 2763 $str = MBYTE_substr( $str, 0, $start_pos ) . $encoded; 2764 } 2765 } 2766 } 2767 while( $start_pos !== false ); 2768 2769 if( isset( $_CONF['skip_html_filter_for_root'] ) && 2770 ( $_CONF['skip_html_filter_for_root'] == 1 ) && 2771 SEC_inGroup( 'Root' )) 2772 { 2773 return $str; 2774 } 2775 2776 // strip_tags() gets confused by HTML comments ... 2777 $str = preg_replace( '/<!--.+?-->/', '', $str ); 2778 2779 $filter = new kses4; 2780 if( isset( $_CONF['allowed_protocols'] ) && is_array( $_CONF['allowed_protocols'] ) && ( sizeof( $_CONF['allowed_protocols'] ) > 0 )) 2781 { 2782 $filter->SetProtocols( $_CONF['allowed_protocols'] ); 2783 } 2784 else 2785 { 2786 $filter->SetProtocols( array( 'http:', 'https:', 'ftp:' )); 2787 } 2788 2789 if( empty( $permissions) || !SEC_hasRights( $permissions ) || 2790 empty( $_CONF['admin_html'] )) 2791 { 2792 $html = $_CONF['user_html']; 2793 } 2794 else 2795 { 2796 $html = array_merge_recursive( $_CONF['user_html'], 2797 $_CONF['admin_html'] ); 2798 } 2799 2800 foreach( $html as $tag => $attr ) 2801 { 2802 $filter->AddHTML( $tag, $attr ); 2803 } 2804 2805 return $filter->Parse( $str ); 2806 } 2807 2808 /** 2809 * undo function for htmlspecialchars() 2810 * 2811 * This function translates HTML entities created by htmlspecialchars() back 2812 * into their ASCII equivalents. Also handles the entities for $, {, and }. 2813 * 2814 * @param string $string The string to convert. 2815 * @return string The converted string. 2816 * 2817 */ 2818 function COM_undoSpecialChars( $string ) 2819 { 2820 $string = str_replace( '$', '$', $string ); 2821 $string = str_replace( '{', '{', $string ); 2822 $string = str_replace( '}', '}', $string ); 2823 $string = str_replace( '>', '>', $string ); 2824 $string = str_replace( '<', '<', $string ); 2825 $string = str_replace( '"', '"', $string ); 2826 $string = str_replace( ' ', ' ', $string ); 2827 $string = str_replace( '&', '&', $string ); 2828 2829 return( $string ); 2830 } 2831 2832 /** 2833 * Makes an ID based on current date/time 2834 * 2835 * This function creates a 17 digit sid for stories based on the 14 digit date 2836 * and a 3 digit random number that was seeded with the number of microseconds 2837 * (.000001th of a second) since the last full second. 2838 * NOTE: this is now used for more than just stories! 2839 * 2840 * @return string $sid Story ID 2841 * 2842 */ 2843 2844 function COM_makesid() 2845 { 2846 $sid = date( 'YmdHis' ); 2847 srand(( double ) microtime() * 1000000 ); 2848 $sid .= rand( 0, 999 ); 2849 2850 return $sid; 2851 } 2852 2853 /** 2854 * Checks to see if email address is valid. 2855 * 2856 * This function checks to see if an email address is in the correct from. 2857 * 2858 * @param string $email Email address to verify 2859 * @return boolean True if valid otherwise false 2860 * 2861 */ 2862 function COM_isEmail( $email ) 2863 { 2864 require_once( 'Mail/RFC822.php' ); 2865 2866 $rfc822 = new Mail_RFC822; 2867 2868 return( $rfc822->isValidInetAddress( $email ) ? true : false ); 2869 } 2870 2871 2872 /** 2873 * Encode a string such that it can be used in an email header 2874 * 2875 * @param string $string the text to be encoded 2876 * @return string encoded text 2877 * 2878 */ 2879 function COM_emailEscape( $string ) 2880 { 2881 global $_CONF, $LANG_CHARSET; 2882 2883 if( empty( $LANG_CHARSET )) 2884 { 2885 $charset = $_CONF['default_charset']; 2886 if( empty( $charset )) 2887 { 2888 $charset = 'iso-8859-1'; 2889 } 2890 } 2891 else 2892 { 2893 $charset = $LANG_CHARSET; 2894 } 2895 2896 if(( $charset == 'utf-8' ) && ( $string != utf8_decode( $string ))) 2897 { 2898 if( function_exists( 'iconv_mime_encode' )) 2899 { 2900 $mime_parameters = array( 'input-charset' => 'utf-8', 2901 'output-charset' => 'utf-8', 2902 // 'Q' encoding is more readable than 'B' 2903 'scheme' => 'Q' 2904 ); 2905 $string = substr( iconv_mime_encode( '', $string, 2906 $mime_parameters ), 2 ); 2907 } 2908 else 2909 { 2910 $string = '=?' . $charset . '?B?' . base64_encode( $string ) . '?='; 2911 } 2912 } 2913 else if( preg_match( '/[^0-9a-z\-\.,:;\?! ]/i', $string )) 2914 { 2915 $string = '=?' . $charset . '?B?' . base64_encode( $string ) . '?='; 2916 } 2917 2918 return $string; 2919 } 2920 2921 /** 2922 * Takes a name and an email address and returns a string that vaguely 2923 * resembles an email address specification conforming to RFC(2)822 ... 2924 * 2925 * @param string $name name, e.g. John Doe 2926 * @param string $address email address only, e.g. john.doe@example.com 2927 * @return string formatted email address 2928 * 2929 */ 2930 function COM_formatEmailAddress( $name, $address ) 2931 { 2932 $formatted_name = COM_emailEscape( $name ); 2933 2934 // if the name comes back unchanged, it's not UTF-8, so preg_match is fine 2935 if(( $formatted_name == $name ) && preg_match( '/[^0-9a-z ]/i', $name )) 2936 { 2937 $formatted_name = str_replace( '"', '\\"', $formatted_name ); 2938 $formatted_name = '"' . $formatted_name . '"'; 2939 } 2940 2941 return $formatted_name . ' <' . $address . '>'; 2942 } 2943 2944 /** 2945 * Send an email. 2946 * 2947 * All emails sent by Geeklog are sent through this function now. 2948 * 2949 * @param string $to recipients name and email address 2950 * @param string $subject subject of the email 2951 * @param string $message the text of the email 2952 * @param string $from (optional) sender of the the email 2953 * @param boolean $html (optional) true if to be sent as HTML email 2954 * @param int $priority (optional) add X-Priority header, if > 0 2955 * @param string $cc (optional) other recipients (name + email) 2956 * @return boolean true if successful, otherwise false 2957 * 2958 * @note Please note that using the $cc parameter will expose the email addresses 2959 * of all recipients. Use with care. 2960 * 2961 */ 2962 function COM_mail( $to, $subject, $message, $from = '', $html = false, $priority = 0, $cc = '' ) 2963 { 2964 global $_CONF, $LANG_CHARSET; 2965 2966 static $mailobj; 2967 2968 if( empty( $from )) 2969 { 2970 $from = COM_formatEmailAddress( $_CONF['site_name'], $_CONF['site_mail']); 2971 } 2972 2973 $to = substr( $to, 0, strcspn( $to, "\r\n" )); 2974 $cc = substr( $cc, 0, strcspn( $cc, "\r\n" )); 2975 $from = substr( $from, 0, strcspn( $from, "\r\n" )); 2976 $subject = substr( $subject, 0, strcspn( $subject, "\r\n" )); 2977 $subject = COM_emailEscape( $subject ); 2978 2979 if( function_exists( 'CUSTOM_mail' )) 2980 { 2981 return CUSTOM_mail( $to, $subject, $message, $from, $html, $priority, $cc ); 2982 } 2983 2984 include_once( 'Mail.php' ); 2985 include_once( 'Mail/RFC822.php' ); 2986 2987 $method = $_CONF['mail_settings']['backend']; 2988 2989 if( !isset( $mailobj )) 2990 { 2991 if(( $method == 'sendmail' ) || ( $method == 'smtp' )) 2992 { 2993 $mailobj =& Mail::factory( $method, $_CONF['mail_settings'] ); 2994 } 2995 else 2996 { 2997 $method = 'mail'; 2998 $mailobj =& Mail::factory( $method ); 2999 } 3000 } 3001 3002 if( empty( $LANG_CHARSET )) 3003 { 3004 $charset = $_CONF['default_charset']; 3005 if( empty( $charset )) 3006 { 3007 $charset = 'iso-8859-1'; 3008 } 3009 } 3010 else 3011 { 3012 $charset = $LANG_CHARSET; 3013 } 3014 3015 $headers = array(); 3016 3017 $headers['From'] = $from; 3018 if( $method != 'mail' ) 3019 { 3020 $headers['To'] = $to; 3021 } 3022 if( !empty( $cc )) 3023 { 3024 $headers['Cc'] = $cc; 3025 } 3026 $headers['Date'] = date( 'r' ); // RFC822 formatted date 3027 if( $method == 'smtp' ) 3028 { 3029 list( $usec, $sec ) = explode( ' ', microtime()); 3030 $m = substr( $usec, 2, 5 ); 3031 $headers['Message-Id'] = '<' . date( 'YmdHis' ) . '.' . $m 3032 . '@' . $_CONF['mail_settings']['host'] . '>'; 3033 } 3034 if( $html ) 3035 { 3036 $headers['Content-Type'] = 'text/html; charset=' . $charset; 3037 $headers['Content-Transfer-Encoding'] = '8bit'; 3038 } 3039 else 3040 { 3041 $headers['Content-Type'] = 'text/plain; charset=' . $charset; 3042 } 3043 $headers['Subject'] = $subject; 3044 if( $priority > 0 ) 3045 { 3046 $headers['X-Priority'] = $priority; 3047 } 3048 $headers['X-Mailer'] = 'GeekLog ' . VERSION; 3049 3050 $retval = $mailobj->send( $to, $headers, $message ); 3051 if( $retval !== true ) 3052 { 3053 COM_errorLog( $retval->toString(), 1 ); 3054 } 3055 3056 return( $retval === true ? true : false ); 3057 } 3058 3059 3060 /** 3061 * Creates older stuff block 3062 * 3063 * Creates the olderstuff block for display. 3064 * Actually updates the olderstuff record in the gl_blocks database. 3065 * @return void 3066 */ 3067 3068 function COM_olderStuff() 3069 { 3070 global $_TABLES, $_CONF; 3071 3072 $sql = "SELECT sid,tid,title,comments,UNIX_TIMESTAMP(date) AS day FROM {$_TABLES['stories']} WHERE (perm_anon = 2) AND (frontpage = 1) AND (date <= NOW()) AND (draft_flag = 0)" . COM_getTopicSQL( 'AND', 1 ) . " ORDER BY featured DESC, date DESC LIMIT {$_CONF['limitnews']}, {$_CONF['limitnews']}"; 3073 $result = DB_query( $sql ); 3074 $nrows = DB_numRows( $result ); 3075 3076 if( $nrows > 0 ) 3077 { 3078 $dateonly = $_CONF['dateonly']; 3079 if( empty( $dateonly )) 3080 { 3081 $dateonly = '%d-%b'; // fallback: day - abbrev. month name 3082 } 3083 3084 $day = 'noday'; 3085 $string = ''; 3086 3087 for( $i = 0; $i < $nrows; $i++ ) 3088 { 3089 $A = DB_fetchArray( $result ); 3090 3091 $daycheck = strftime( '%A', $A['day'] ); 3092 if( $day != $daycheck ) 3093 { 3094 if( $day != 'noday' ) 3095 { 3096 $daylist = COM_makeList( $oldnews, 'list-older-stories' ); 3097 $daylist = preg_replace( "/(\015\012)|(\015)|(\012)/", 3098 '', $daylist ); 3099 $string .= $daylist . '<br>'; 3100 } 3101 3102 $day2 = strftime( $dateonly, $A['day'] ); 3103 $string .= '<h3>' . $daycheck . '<small>' . $day2 3104 . '</small></h3>' . LB; 3105 $oldnews = array(); 3106 $day = $daycheck; 3107 } 3108 3109 $oldnews[] = '<a href="' . COM_buildUrl( $_CONF['site_url'] 3110 . '/article.php?story=' . $A['sid'] ) . '">' . $A['title'] 3111 . '</a> (' . COM_numberFormat( $A['comments'] ) . ')'; 3112 } 3113 3114 if( !empty( $oldnews )) 3115 { 3116 $daylist = COM_makeList( $oldnews, 'list-older-stories' ); 3117 $daylist = preg_replace( "/(\015\012)|(\015)|(\012)/", '', $daylist ); 3118 $string .= $daylist; 3119 $string = addslashes( $string ); 3120 3121 DB_query( "UPDATE {$_TABLES['blocks']} SET content = '$string' WHERE name = 'older_stories'" ); 3122 } 3123 } 3124 } 3125 3126 /** 3127 * Shows a single Geeklog block 3128 * 3129 * This shows a single block and is typically called from 3130 * COM_showBlocks OR from plugin code 3131 * 3132 * @param string $name Logical name of block (not same as title) -- 'user_block', 'admin_block', 'section_block', 'whats_new_block'. 3133 * @param string $help Help file location 3134 * @param string $title Title shown in block header 3135 * @see function COM_showBlocks 3136 * @return string HTML Formated block 3137 * 3138 */ 3139 3140 function COM_showBlock( $name, $help='', $title='' ) 3141 { 3142 global $_CONF, $topic, $_TABLES, $_USER; 3143 3144 $retval = ''; 3145 3146 if( !isset( $_USER['noboxes'] )) 3147 { 3148 if( !empty( $_USER['uid'] )) 3149 { 3150 $_USER['noboxes'] = DB_getItem( $_TABLES['userindex'], 'noboxes', 3151 "uid = {$_USER['uid']}" ); 3152 } 3153 else 3154 { 3155 $_USER['noboxes'] = 0; 3156 } 3157 } 3158 3159 switch( $name ) 3160 { 3161 case 'user_block': 3162 $retval .= COM_userMenu( $help,$title ); 3163 break; 3164 3165 case 'admin_block': 3166 $retval .= COM_adminMenu( $help,$title ); 3167 break; 3168 3169 case 'section_block': 3170 $retval .= COM_startBlock( $title, $help, 3171 COM_getBlockTemplate( $name, 'header' )) 3172 . COM_showTopics( $topic ) 3173 . COM_endBlock( COM_getBlockTemplate( $name, 'footer' )); 3174 break; 3175 3176 case 'whats_new_block': 3177 if( !$_USER['noboxes'] ) 3178 { 3179 $retval .= COM_whatsNewBlock( $help, $title ); 3180 } 3181 break; 3182 } 3183 3184 return $retval; 3185 } 3186 3187 3188 /** 3189 * Shows Geeklog blocks 3190 * 3191 * Returns HTML for blocks on a given side and, potentially, for 3192 * a given topic. Currentlly only used by static pages. 3193 * 3194 * @param string $side Side to get blocks for (right or left for now) 3195 * @param string $topic Only get blocks for this topic 3196 * @param string $name Block name (not used) 3197 * @see function COM_showBlock 3198 * @return string HTML Formated blocks 3199 * 3200 */ 3201 3202 function COM_showBlocks( $side, $topic='', $name='all' ) 3203 { 3204 global $_CONF, $_TABLES, $_USER, $LANG21, $topic, $page; 3205 3206 $retval = ''; 3207 3208 // Get user preferences on blocks 3209 if( !isset( $_USER['noboxes'] ) || !isset( $_USER['boxes'] )) 3210 { 3211 if( !empty( $_USER['uid'] )) 3212 { 3213 $result = DB_query( "SELECT boxes,noboxes FROM {$_TABLES['userindex']} " 3214 ."WHERE uid = '{$_USER['uid']}'" ); 3215 list($_USER['boxes'], $_USER['noboxes']) = DB_fetchArray( $result ); 3216 } 3217 else 3218 { 3219 $_USER['boxes'] = ''; 3220 $_USER['noboxes'] = 0; 3221 } 3222 } 3223 3224 $sql = "SELECT *,UNIX_TIMESTAMP(rdfupdated) AS date " 3225 . "FROM {$_TABLES['blocks']} WHERE is_enabled = 1"; 3226 3227 if( $side == 'left' ) 3228 { 3229 $sql .= " AND onleft = 1"; 3230 } 3231 else 3232 { 3233 $sql .= " AND onleft = 0"; 3234 } 3235 3236 if( !empty( $topic )) 3237 { 3238 $sql .= " AND (tid = '$topic' OR tid = 'all')"; 3239 } 3240 else 3241 { 3242 if( COM_onFrontpage() ) 3243 { 3244 $sql .= " AND (tid = 'homeonly' OR tid = 'all')"; 3245 } 3246 else 3247 { 3248 $sql .= " AND (tid = 'all')"; 3249 } 3250 } 3251 3252 if( !empty( $_USER['boxes'] )) 3253 { 3254 $BOXES = str_replace( ' ', ',', $_USER['boxes'] ); 3255 3256 $sql .= " AND (bid NOT IN ($BOXES) OR bid = '-1')"; 3257 } 3258 3259 $sql .= ' ORDER BY blockorder,title asc'; 3260 3261 $result = DB_query( $sql ); 3262 $nrows = DB_numRows( $result ); 3263 3264 // convert result set to an array of associated arrays 3265 $blocks = array(); 3266 for( $i = 0; $i < $nrows; $i++ ) 3267 { 3268 $blocks[] = DB_fetchArray( $result ); 3269 } 3270 3271 // Check and see if any plugins have blocks to show 3272 $pluginBlocks = PLG_getBlocks( $side, $topic, $name ); 3273 $blocks = array_merge( $blocks, $pluginBlocks ); 3274 3275 // sort the resulting array by block order 3276 $column = 'blockorder'; 3277 $sortedBlocks = $blocks; 3278 for( $i = 0; $i < sizeof( $sortedBlocks ) - 1; $i++ ) 3279 { 3280 for( $j = 0; $j < sizeof( $sortedBlocks ) - 1 - $i; $j++ ) 3281 { 3282 if( $sortedBlocks[$j][$column] > $sortedBlocks[$j+1][$column] ) 3283 { 3284 $tmp = $sortedBlocks[$j]; 3285 $sortedBlocks[$j] = $sortedBlocks[$j + 1]; 3286 $sortedBlocks[$j + 1] = $tmp; 3287 } 3288 } 3289 } 3290 $blocks = $sortedBlocks; 3291 3292 // Loop though resulting sorted array and pass associative arrays 3293 // to COM_formatBlock 3294 foreach( $blocks as $A ) 3295 { 3296 if( $A['type'] == 'dynamic' or SEC_hasAccess( $A['owner_id'], $A['group_id'], $A['perm_owner'], $A['perm_group'], $A['perm_members'], $A['perm_anon'] ) > 0 ) 3297 { 3298 $retval .= COM_formatBlock( $A, $_USER['noboxes'] ); 3299 } 3300 } 3301 3302 return $retval; 3303 } 3304 3305 /** 3306 * Formats a Geeklog block 3307 * 3308 * This shows a single block and is typically called from 3309 * COM_showBlocks OR from plugin code 3310 * 3311 * @param array $A Block Record 3312 * @param bool $noboxes Set to true if userpref is no blocks 3313 * @return string HTML Formated block 3314 * 3315 */ 3316 function COM_formatBlock( $A, $noboxes = false ) 3317 { 3318 global $_CONF, $_TABLES, $_USER, $LANG21; 3319 3320 $retval = ''; 3321 if( $A['type'] == 'portal' ) 3322 { 3323 if( COM_rdfCheck( $A['bid'], $A['rdfurl'], $A['date'], $A['rdflimit'] )) 3324 { 3325 $A['content'] = DB_getItem( $_TABLES['blocks'], 'content', 3326 "bid = '{$A['bid']}'"); 3327 } 3328 } 3329 3330 if( $A['type'] == 'gldefault' ) 3331 { 3332 $retval .= COM_showBlock( $A['name'], $A['help'], $A['title'] ); 3333 } 3334 3335 if( $A['type'] == 'phpblock' && !$noboxes ) 3336 { 3337 if( !( $A['name'] == 'whosonline_block' AND DB_getItem( $_TABLES['blocks'], 'is_enabled', "name='whosonline_block'" ) == 0 )) 3338 { 3339 $function = $A['phpblockfn']; 3340 $blkheader = COM_startBlock( $A['title'], $A['help'], 3341 COM_getBlockTemplate( $A['name'], 'header' )); 3342 $blkfooter = COM_endBlock( COM_getBlockTemplate( $A['name'], 3343 'footer' )); 3344 3345 if( function_exists( $function )) 3346 { 3347 $fretval = $function(); 3348 if( !empty( $fretval )) 3349 { 3350 $retval .= $blkheader; 3351 $retval .= $fretval; 3352 $retval .= $blkfooter; 3353 } 3354 } 3355 else 3356 { 3357 // show error message 3358 $retval .= $blkheader; 3359 $retval .= sprintf( $LANG21[31], $function ); 3360 $retval .= $blkfooter; 3361 } 3362 } 3363 } 3364 3365 if( !empty( $A['content'] ) && ( trim( $A['content'] ) != '' ) && !$noboxes ) 3366 { 3367 $blockcontent = stripslashes( $A['content'] ); 3368 3369 // Hack: If the block content starts with a '<' assume it 3370 // contains HTML and do not call nl2br() which would only add 3371 // unwanted <br> tags. 3372 3373 if( substr( $blockcontent, 0, 1 ) != '<' ) 3374 { 3375 $blockcontent = nl2br( $blockcontent ); 3376 } 3377 3378 if ($A['allow_autotags'] == 1) { 3379 $blockcontent = PLG_replaceTags( $blockcontent ); 3380 } 3381 $blockcontent = str_replace( array( '<?', '?>' ), '', $blockcontent ); 3382 3383 $retval .= COM_startBlock( $A['title'], $A['help'], 3384 COM_getBlockTemplate( $A['name'], 'header' )) 3385 . $blockcontent . LB 3386 . COM_endBlock( COM_getBlockTemplate( $A['name'], 'footer' )); 3387 } 3388 3389 return $retval; 3390 } 3391 3392 3393 /** 3394 * Checks to see if it's time to import and RDF/RSS block again 3395 * 3396 * Updates RDF/RSS block if needed 3397 * 3398 * @param string $bid Block ID 3399 * @param string $rdfurl URL to get headlines from 3400 * @param string $date Last time the headlines were imported 3401 * @param string $maxheadlines max. number of headlines to import 3402 * @return void 3403 * @see function COM_rdfImport 3404 * 3405 */ 3406 function COM_rdfCheck( $bid, $rdfurl, $date, $maxheadlines = 0 ) 3407 { 3408 $retval = false; 3409 $nextupdate = $date + 3600; 3410 3411 if( $nextupdate < time() ) 3412 { 3413 COM_rdfImport( $bid, $rdfurl, $maxheadlines ); 3414 $retval = true; 3415 } 3416 3417 return $retval; 3418 } 3419 3420 /** 3421 * Syndication import function. Imports headline data to a portal block. 3422 * 3423 * Rewritten December 19th 2004 by Michael Jervis (mike@fuckingbrit.com). Now 3424 * utilises a Factory Pattern to open a URL and automaticaly retreive a feed 3425 * object populated with feed data. Then import it into the portal block. 3426 * 3427 * @param string $bid Block ID 3428 * @param string $rdfurl URL to get content from 3429 * @param int $maxheadlines Maximum number of headlines to display 3430 * @return void 3431 * @see function COM_rdfCheck 3432 * 3433 */ 3434 function COM_rdfImport( $bid, $rdfurl, $maxheadlines = 0 ) 3435 { 3436 global $_CONF, $_TABLES, $LANG21, $LANG_CHARSET; 3437 3438 // Import the feed handling classes: 3439 require_once( $_CONF['path_system'] 3440 . '/classes/syndication/parserfactory.class.php' ); 3441 require_once( $_CONF['path_system'] 3442 . '/classes/syndication/feedparserbase.class.php' ); 3443 3444 // Load the actual feed handlers: 3445 $factory = new FeedParserFactory( $_CONF['path_system'] 3446 . '/classes/syndication/' ); 3447 $factory->userAgent = 'GeekLog/' . VERSION; 3448 $feed = $factory->reader( $rdfurl, $_CONF['default_charset'] ); 3449 3450 // Aquire a reader: 3451 if( $feed ) 3452 { 3453 /* We have located a reader, and populated it with the information from 3454 * the syndication file. Now we will sort out our display, and update 3455 * the block. 3456 */ 3457 if( $maxheadlines == 0 ) 3458 { 3459 if( !empty( $_CONF['syndication_max_headlines'] )) 3460 { 3461 $maxheadlines = $_CONF['syndication_max_headlines']; 3462 } 3463 else 3464 { 3465 $maxheadlines = count( $feed->articles ); 3466 } 3467 } 3468 3469 $update = date( 'Y-m-d H:i:s' ); 3470 $result = DB_change( $_TABLES['blocks'], 'rdfupdated', $update, 3471 'bid', $bid ); 3472 3473 if( empty( $LANG_CHARSET )) 3474 { 3475 $charset = $_CONF['default_charset']; 3476 if( empty( $charset )) 3477 { 3478 $charset = 'iso-8859-1'; 3479 } 3480 } 3481 else 3482 { 3483 $charset = $LANG_CHARSET; 3484 } 3485 3486 // format articles for display 3487 $readmax = min( $maxheadlines, count( $feed->articles )); 3488 for( $i = 0; $i < $readmax; $i++ ) 3489 { 3490 if( empty( $feed->articles[$i]['title'] )) 3491 { 3492 $feed->articles[$i]['title'] = $LANG21[61]; 3493 } 3494 3495 if( $charset == 'utf-8' ) 3496 { 3497 $title = $feed->articles[$i]['title']; 3498 } 3499 else 3500 { 3501 $title = utf8_decode( $feed->articles[$i]['title'] ); 3502 } 3503 $content = '<a href="' . $feed->articles[$i]['link'] . '">' 3504 . $title . '</a>'; 3505 $articles[] = $content; 3506 } 3507 3508 // build a list 3509 $content = COM_makeList( $articles, 'list-feed' ); 3510 $content = preg_replace( "/(\015\012)|(\015)|(\012)/", '', $content ); 3511 3512 // Standard theme based function to put it in the block 3513 $result = DB_change( $_TABLES['blocks'], 'content', 3514 addslashes( $content ), 'bid', $bid ); 3515 } 3516 else 3517 { 3518 // failed to aquire info, 0 out the block and log an error 3519 COM_errorLog( "Unable to aquire feed reader for $rdfurl", 1 ); 3520 COM_errorLog( $factory->errorStatus[0] . ' ' . 3521 $factory->errorStatus[1] . ' ' . 3522 $factory->errorStatus[2] ); 3523 $result = DB_change( $_TABLES['blocks'], 'content', 3524 addslashes( $LANG21[4] ), 'bid', $bid ); 3525 } 3526 } 3527 3528 3529 /** 3530 * Returns what HTML is allowed in content 3531 * 3532 * Returns what HTML tags the system allows to be used inside content. 3533 * You can modify this by changing $_CONF['user_html'] in config.php 3534 * (for admins, see also $_CONF['admin_html']). 3535 * 3536 * @param string $permissions comma-separated list of rights which identify the current user as an "Admin" 3537 * @param boolean $list_only true = return only the list of HTML tags 3538 * @return string HTML <span> enclosed string 3539 * @see function COM_checkHTML 3540 */ 3541 function COM_allowedHTML( $permissions = 'story.edit', $list_only = false ) 3542 { 3543 global $_CONF, $LANG01; 3544 3545 $retval = ''; 3546 3547 if( isset( $_CONF['skip_html_filter_for_root'] ) && 3548 ( $_CONF['skip_html_filter_for_root'] == 1 ) && 3549 SEC_inGroup( 'Root' )) 3550 { 3551 if( !$list_only ) 3552 { 3553 $retval .= '<span class="warningsmall">' . $LANG01[123] . '</span>'; 3554 } 3555 3556 return $retval; 3557 } 3558 3559 if( !$list_only ) 3560 { 3561 $retval .= '<span class="warningsmall">' . $LANG01[31] . ' '; 3562 } 3563 3564 $allow_page_break = false; 3565 if( empty( $permissions ) || !SEC_hasRights( $permissions ) || 3566 empty( $_CONF['admin_html'] )) 3567 { 3568 $html = $_CONF['user_html']; 3569 } 3570 else 3571 { 3572 $html = array_merge_recursive( $_CONF['user_html'], 3573 $_CONF['admin_html'] ); 3574 if( $_CONF['allow_page_breaks'] == 1 ) 3575 { 3576 $perms = explode( ',', $permissions ); 3577 foreach( $perms as $p ) 3578 { 3579 if( substr( $p, 0, 6 ) == 'story.' ) 3580 { 3581 $allow_page_break = true; 3582 break; 3583 } 3584 } 3585 } 3586 } 3587 3588 foreach( $html as $tag => $attr ) 3589 { 3590 $retval .= '<' . $tag . '>, '; 3591 } 3592 3593 $retval .= '[code]'; 3594 3595 if( $allow_page_break ) 3596 { 3597 $retval .= ', [page_break]'; 3598 } 3599 3600 // list autolink tags 3601 $autotags = PLG_collectTags(); 3602 foreach( $autotags as $tag => $module ) 3603 { 3604 $retval .= ', [' . $tag . ':]'; 3605 } 3606 3607 if( !$list_only ) 3608 { 3609 $retval .= '</span>'; 3610 } 3611 3612 return $retval; 3613 } 3614 3615 /** 3616 * Return the password for the given username 3617 * 3618 * Fetches a password for the given user 3619 * 3620 * @param string $loginname username to get password for 3621 * @return string Password or '' 3622 * 3623 */ 3624 3625 function COM_getPassword( $loginname ) 3626 { 3627 global $_TABLES, $LANG01; 3628 3629 $result = DB_query( "SELECT passwd FROM {$_TABLES['users']} WHERE username='$loginname'" ); 3630 $tmp = DB_error(); 3631 $nrows = DB_numRows( $result ); 3632 3633 if(( $tmp == 0 ) && ( $nrows == 1 )) 3634 { 3635 $U = DB_fetchArray( $result ); 3636 return $U['passwd']; 3637 } 3638 else 3639 { 3640 $tmp = $LANG01[32] . ": '" . $loginname . "'"; 3641 COM_errorLog( $tmp, 1 ); 3642 } 3643 3644 return ''; 3645 } 3646 3647 3648 /** 3649 * Return the username or fullname for the passed member id (uid) 3650 * 3651 * Allows the siteAdmin to determine if loginname (username) or fullname 3652 * should be displayed. 3653 * 3654 * @param int $uid site member id 3655 * @param string $username Username, if this is set no lookup is done. 3656 * @param string $fullname Users full name. 3657 * @param string $service Remote login service. 3658 * @return string Username, fullname or username@Service 3659 * 3660 */ 3661 function COM_getDisplayName( $uid = '', $username='', $fullname='', $remoteusername='', $remoteservice='' ) 3662 { 3663 global $_CONF, $_TABLES, $_USER; 3664 3665 if ($uid == '') 3666 { 3667 if( empty( $_USER['uid'] ) || ( $_USER['uid'] <= 1 )) 3668 { 3669 $uid = 1; 3670 } 3671 else 3672 { 3673 $uid = $_USER['uid']; 3674 } 3675 } 3676 3677 if( empty( $username )) 3678 { 3679 $query = DB_query( "SELECT username, fullname, remoteusername, remoteservice FROM {$_TABLES['users']} WHERE uid='$uid'" ); 3680 list( $username, $fullname, $remoteusername, $remoteservice ) = DB_fetchArray( $query ); 3681 } 3682 3683 if( !empty( $fullname ) && ($_CONF['show_fullname'] == 1 )) 3684 { 3685 return $fullname; 3686 } 3687 else if( $_CONF['remoteauthentication'] && $_CONF['show_servicename'] && 3688 !empty( $remoteusername )) 3689 { 3690 return "$remoteusername@$remoteservice"; 3691 } 3692 3693 return $username; 3694 } 3695 3696 3697 /** 3698 * Adds a hit to the system 3699 * 3700 * This function is called in the footer of every page and is used to 3701 * track the number of hits to the Geeklog system. This information is 3702 * shown on stats.php 3703 * 3704 */ 3705 3706 function COM_hit() 3707 { 3708 global $_TABLES; 3709 3710 DB_query( "UPDATE {$_TABLES['vars']} SET value = value + 1 WHERE name = 'totalhits'" ); 3711 } 3712 3713 /** 3714 * This will email new stories in the topics that the user is interested in 3715 * 3716 * In account information the user can specify which topics for which they 3717 * will receive any new article for in a daily digest. 3718 * 3719 * @return void 3720 */ 3721 3722 function COM_emailUserTopics() 3723 { 3724 global $_CONF, $_TABLES, $LANG08, $LANG24; 3725 3726 $subject = strip_tags( $_CONF['site_name'] . $LANG08[30] . strftime( '%Y-%m-%d', time() )); 3727 3728 $authors = array(); 3729 3730 // Get users who want stories emailed to them 3731 $usersql = "SELECT username,email,etids,{$_TABLES['users']}.uid AS uuid " 3732 . "FROM {$_TABLES['users']}, {$_TABLES['userindex']} " 3733 . "WHERE {$_TABLES['users']}.uid > 1 AND {$_TABLES['userindex']}.uid = {$_TABLES['users']}.uid AND (etids <> '-' OR etids IS NULL) ORDER BY {$_TABLES['users']}.uid"; 3734 3735 $users = DB_query( $usersql ); 3736 $nrows = DB_numRows( $users ); 3737 3738 $lastrun = DB_getItem( $_TABLES['vars'], 'value', "name = 'lastemailedstories'" ); 3739 3740 // For each user, pull the stories they want and email it to them 3741 for( $x = 1; $x <= $nrows; $x++ ) 3742 { 3743 $U = DB_fetchArray( $users ); 3744 3745 $storysql = array(); 3746 $storysql['mysql'] = "SELECT sid,uid,date AS day,title,introtext,bodytext"; 3747 3748 $storysql['mssql'] = "SELECT sid,uid,date AS day,title,CAST(introtext AS text) AS introtext,CAST(bodytext AS text) AS introtext"; 3749 3750 $commonsql = " FROM {$_TABLES['stories']} WHERE draft_flag = 0 AND date <= NOW() AND date >= '{$lastrun}'"; 3751 3752 $topicsql = "SELECT tid FROM {$_TABLES['topics']}" 3753 . COM_getPermSQL( 'WHERE', $U['uuid'] ); 3754 $tresult = DB_query( $topicsql ); 3755 $trows = DB_numRows( $tresult ); 3756 3757 if( $trows == 0 ) 3758 { 3759 // this user doesn't seem to have access to any topics ... 3760 continue; 3761 } 3762 3763 $TIDS = array(); 3764 for( $i = 1; $i <= $trows; $i++ ) 3765 { 3766 $T = DB_fetchArray( $tresult ); 3767 $TIDS[] = $T['tid']; 3768 } 3769 3770 if( !empty( $U['etids'] )) 3771 { 3772 $ETIDS = explode( ' ', $U['etids'] ); 3773 $TIDS = array_intersect( $TIDS, $ETIDS ); 3774 } 3775 3776 if( sizeof( $TIDS ) > 0) 3777 { 3778 $commonsql .= " AND (tid IN ('" . implode( "','", $TIDS ) . "'))"; 3779 } 3780 3781 $commonsql .= COM_getPermSQL( 'AND', $U['uuid'] ); 3782 $commonsql .= ' ORDER BY featured DESC, date DESC'; 3783 3784 $storysql['mysql'] .= $commonsql; 3785 $storysql['mssql'] .= $commonsql; 3786 3787 $stories = DB_query( $storysql ); 3788 $nsrows = DB_numRows( $stories ); 3789 3790 if( $nsrows == 0 ) 3791 { 3792 // If no new stories where pulled for this user, continue with next 3793 continue; 3794 } 3795 3796 $mailtext = $LANG08[29] . strftime( $_CONF['shortdate'], time() ) . "\n"; 3797 3798 for( $y = 0; $y < $nsrows; $y++ ) 3799 { 3800 // Loop through stories building the requested email message 3801 $S = DB_fetchArray( $stories ); 3802 3803 $mailtext .= "\n------------------------------\n\n"; 3804 $mailtext .= "$LANG08[31]: " 3805 . COM_undoSpecialChars( stripslashes( $S['title'] )) . "\n"; 3806 if( $_CONF['contributedbyline'] == 1 ) 3807 { 3808 if( empty( $authors[$S['uid']] )) 3809 { 3810 $storyauthor = COM_getDisplayName ($S['uid']); 3811 $authors[$S['uid']] = $storyauthor; 3812 } 3813 else 3814 { 3815 $storyauthor = $authors[$S['uid']]; 3816 } 3817 $mailtext .= "$LANG24[7]: " . $storyauthor . "\n"; 3818 } 3819 3820 $mailtext .= "$LANG08[32]: " . strftime( $_CONF['date'], strtotime( $S['day' ])) . "\n\n"; 3821 3822 if( $_CONF['emailstorieslength'] > 0 ) 3823 { 3824 $storytext = COM_undoSpecialChars( strip_tags( PLG_replaceTags( stripslashes( $S['introtext'] )))); 3825 3826 if( $_CONF['emailstorieslength'] > 1 ) 3827 { 3828 $storytext = COM_truncate( $storytext, 3829 $_CONF['emailstorieslength'], '...' ); 3830 } 3831 3832 $mailtext .= $storytext . "\n\n"; 3833 } 3834 3835 $mailtext .= $LANG08[33] . ' ' . COM_buildUrl( $_CONF['site_url'] 3836 . '/article.php?story=' . $S['sid'] ) . "\n"; 3837 } 3838 3839 $mailtext .= "\n------------------------------\n"; 3840 $mailtext .= "\n$LANG08[34]\n"; 3841 $mailtext .= "\n------------------------------\n"; 3842 3843 $mailto = $U['username'] . ' <' . $U['email'] . '>'; 3844 3845 COM_mail( $mailto, $subject, $mailtext ); 3846 } 3847 3848 DB_query( "UPDATE {$_TABLES['vars']} SET value = NOW() WHERE name = 'lastemailedstories'" ); 3849 } 3850 3851 /** 3852 * Shows any new information in a block 3853 * 3854 * Return the HTML that shows any new stories, comments, etc 3855 * 3856 * @param string $help Help file for block 3857 * @param string $title Title used in block header 3858 * @return string Return the HTML that shows any new stories, comments, etc 3859 * 3860 */ 3861 3862 function COM_whatsNewBlock( $help = '', $title = '' ) 3863 { 3864 global $_CONF, $_TABLES, $_USER, $LANG01, $LANG_WHATSNEW, $page, $newstories; 3865 3866 $retval = COM_startBlock( $title, $help, 3867 COM_getBlockTemplate( 'whats_new_block', 'header' )); 3868 3869 $topicsql = ''; 3870 if(( $_CONF['hidenewstories'] == 0 ) || ( $_CONF['hidenewcomments'] == 0 ) 3871 || ( $_CONF['trackback_enabled'] 3872 && ( $_CONF['hidenewtrackbacks'] == 0 ))) 3873 { 3874 $topicsql = COM_getTopicSql ('AND', 0, $_TABLES['stories']); 3875 } 3876 3877 if( $_CONF['hidenewstories'] == 0 ) 3878 { 3879 $archsql = ''; 3880 $archivetid = DB_getItem( $_TABLES['topics'], 'tid', "archive_flag=1" ); 3881 if( !empty( $archivetid )) 3882 { 3883 $archsql = " AND (tid <> '" . addslashes( $archivetid ) . "')"; 3884 } 3885 3886 // Find the newest stories 3887 $sql = "SELECT COUNT(*) AS count FROM {$_TABLES['stories']} WHERE (date >= (date_sub(NOW(), INTERVAL {$_CONF['newstoriesinterval']} SECOND))) AND (date <= NOW()) AND (draft_flag = 0)" . $archsql . COM_getPermSQL( 'AND' ) . $topicsql . COM_getLangSQL( 'sid', 'AND' ); 3888 $result = DB_query( $sql ); 3889 $A = DB_fetchArray( $result ); 3890 $nrows = $A['count']; 3891 3892 if( empty( $title )) 3893 { 3894 $title = DB_getItem( $_TABLES['blocks'], 'title', "name='whats_new_block'" ); 3895 } 3896 3897 // Any late breaking news stories? 3898 $retval .= '<h3>' . $LANG01[99] . '</h3>'; 3899 3900 if( $nrows > 0 ) 3901 { 3902 $newmsg = COM_formatTimeString( $LANG_WHATSNEW['new_string'], 3903 $_CONF['newstoriesinterval'], $LANG01[11], $nrows); 3904 3905 if( $newstories && ( $page < 2 )) 3906 { 3907 $retval .= $newmsg . '<br>'; 3908 } 3909 else 3910 { 3911 $retval .= '<a href="' . $_CONF['site_url'] 3912 . '/index.php?display=new">' . $newmsg . '</a><br>'; 3913 } 3914 } 3915 else 3916 { 3917 $retval .= $LANG01[100] . '<br>'; 3918 } 3919 3920 if(( $_CONF['hidenewcomments'] == 0 ) || ( $_CONF['trackback_enabled'] 3921 && ( $_CONF['hidenewtrackbacks'] == 0 )) 3922 || ( $_CONF['hidenewplugins'] == 0 )) 3923 { 3924 $retval .= '<br>'; 3925 } 3926 } 3927 3928 if( $_CONF['hidenewcomments'] == 0 ) 3929 { 3930 // Go get the newest comments 3931 $retval .= '<h3>' . $LANG01[83] . ' <small>' 3932 . COM_formatTimeString( $LANG_WHATSNEW['new_last'], 3933 $_CONF['newcommentsinterval'] ) 3934 . '</small></h3>'; 3935 3936 $stwhere = ''; 3937 3938 if( !empty( $_USER['uid'] )) 3939 { 3940 $stwhere .= "({$_TABLES['stories']}.owner_id IS NOT NULL AND {$_TABLES['stories']}.perm_owner IS NOT NULL) OR "; 3941 $stwhere .= "({$_TABLES['stories']}.group_id IS NOT NULL AND {$_TABLES['stories']}.perm_group IS NOT NULL) OR "; 3942 $stwhere .= "({$_TABLES['stories']}.perm_members IS NOT NULL)"; 3943 } 3944 else 3945 { 3946 $stwhere .= "({$_TABLES['stories']}.perm_anon IS NOT NULL)"; 3947 } 3948 $sql = "SELECT DISTINCT COUNT(*) AS dups, type, {$_TABLES['stories']}.title, {$_TABLES['stories']}.sid, max({$_TABLES['comments']}.date) AS lastdate FROM {$_TABLES['comments']} LEFT JOIN {$_TABLES['stories']} ON (({$_TABLES['stories']}.sid = {$_TABLES['comments']}.sid)" . COM_getPermSQL( 'AND', 0, 2, $_TABLES['stories'] ) . " AND ({$_TABLES['stories']}.draft_flag = 0) AND ({$_TABLES['stories']}.commentcode = 0)" . $topicsql . COM_getLangSQL( 'sid', 'AND', $_TABLES['stories'] ) . ") WHERE ({$_TABLES['comments']}.date >= (DATE_SUB(NOW(), INTERVAL {$_CONF['newcommentsinterval']} SECOND))) AND ((({$stwhere}))) GROUP BY {$_TABLES['comments']}.sid,type, {$_TABLES['stories']}.title, {$_TABLES['stories']}.title, {$_TABLES['stories']}.sid ORDER BY 5 DESC LIMIT 15"; 3949 3950 $result = DB_query( $sql ); 3951 3952 $nrows = DB_numRows( $result ); 3953 3954 if( $nrows > 0 ) 3955 { 3956 $newcomments = array(); 3957 3958 for( $x = 0; $x < $nrows; $x++ ) 3959 { 3960 $A = DB_fetchArray( $result ); 3961 3962 if(( $A['type'] == 'article' ) || empty( $A['type'] )) 3963 { 3964 $urlstart = '<a href="' . COM_buildUrl( $_CONF['site_url'] 3965 . '/article.php?story=' . $A['sid'] ) . '#comments' . '"'; 3966 } 3967 3968 $title = COM_undoSpecialChars( stripslashes( $A['title'] )); 3969 $titletouse = COM_truncate( $title, $_CONF['title_trim_length'], 3970 '...' ); 3971 3972 if( $title != $titletouse ) 3973 { 3974 $urlstart .= ' title="' . htmlspecialchars( $title ) . '">'; 3975 } 3976 else 3977 { 3978 $urlstart .= '>'; 3979 } 3980 3981 $acomment = str_replace( '$', '$', $titletouse ); 3982 $acomment = str_replace( ' ', ' ', $acomment ); 3983 3984 if( $A['dups'] > 1 ) 3985 { 3986 $acomment .= ' [+' . $A['dups'] . ']'; 3987 } 3988 3989 $newcomments[] = $urlstart . $acomment . '</a>'; 3990 } 3991 3992 $retval .= COM_makeList( $newcomments, 'list-new-comments' ); 3993 } 3994 else 3995 { 3996 $retval .= $LANG01[86] . '<br>' . LB; 3997 } 3998 if(( $_CONF['hidenewplugins'] == 0 ) 3999 || ( $_CONF['trackback_enabled'] 4000 && ( $_CONF['hidenewtrackbacks'] == 0 ))) 4001 { 4002 $retval .= '<br>'; 4003 } 4004 } 4005 4006 if( $_CONF['trackback_enabled'] && ( $_CONF['hidenewtrackbacks'] == 0 )) 4007 { 4008 $retval .= '<h3>' . $LANG01[114] . ' <small>' 4009 . COM_formatTimeString( $LANG_WHATSNEW['new_last'], 4010 $_CONF['newtrackbackinterval'] ) 4011 . '</small></h3>'; 4012 4013 $sql = "SELECT DISTINCT COUNT(*) AS count,{$_TABLES['stories']}.title,t.sid,max(t.date) AS lastdate FROM {$_TABLES['trackback']} AS t,{$_TABLES['stories']} WHERE (t.type = 'article') AND (t.sid = {$_TABLES['stories']}.sid) AND (t.date >= (DATE_SUB(NOW(), INTERVAL {$_CONF['newtrackbackinterval']} SECOND)))" . COM_getPermSQL( 'AND', 0, 2, $_TABLES['stories'] ) . " AND ({$_TABLES['stories']}.draft_flag = 0) AND ({$_TABLES['stories']}.trackbackcode = 0)" . $topicsql . COM_getLangSQL( 'sid', 'AND', $_TABLES['stories'] ) . " GROUP BY t.sid, {$_TABLES['stories']}.title ORDER BY lastdate DESC LIMIT 15"; 4014 $result = DB_query( $sql ); 4015 4016 $nrows = DB_numRows( $result ); 4017 if( $nrows > 0 ) 4018 { 4019 $newcomments = array(); 4020 4021 for( $i = 0; $i < $nrows; $i++ ) 4022 { 4023 $A = DB_fetchArray( $result ); 4024 4025 $urlstart = '<a href="' . COM_buildUrl( $_CONF['site_url'] 4026 . '/article.php?story=' . $A['sid'] ) . '#trackback' . '"'; 4027 4028 $title = COM_undoSpecialChars( stripslashes( $A['title'] )); 4029 $titletouse = COM_truncate( $title, $_CONF['title_trim_length'], 4030 '...' ); 4031 4032 if( $title != $titletouse ) 4033 { 4034 $urlstart .= ' title="' . htmlspecialchars( $title ) . '">'; 4035 } 4036 else 4037 { 4038 $urlstart .= '>'; 4039 } 4040 4041 $acomment = str_replace( '$', '$', $titletouse ); 4042 $acomment = str_replace( ' ', ' ', $acomment ); 4043 4044 if( $A['count'] > 1 ) 4045 { 4046 $acomment .= ' [+' . $A['count'] . ']'; 4047 } 4048 4049 $newcomments[] = $urlstart . $acomment . '</a>'; 4050 } 4051 4052 $retval .= COM_makeList( $newcomments, 'list-new-trackbacks' ); 4053 } 4054 else 4055 { 4056 $retval .= $LANG01[115] . '<br>' . LB; 4057 } 4058 if( $_CONF['hidenewplugins'] == 0 ) 4059 { 4060 $retval .= '<br>'; 4061 } 4062 } 4063 4064 if( $_CONF['hidenewplugins'] == 0 ) 4065 { 4066 list( $headlines, $smallheadlines, $content ) = PLG_getWhatsNew(); 4067 $plugins = sizeof( $headlines ); 4068 if( $plugins > 0 ) 4069 { 4070 for( $i = 0; $i < $plugins; $i++ ) 4071 { 4072 $retval .= '<h3>' . $headlines[$i] . ' <small>' 4073 . $smallheadlines[$i] . '</small></h3>'; 4074 if( is_array( $content[$i] )) 4075 { 4076 $retval .= COM_makeList( $content[$i], 'list-new-plugins' ); 4077 } 4078 else 4079 { 4080 $retval .= $content[$i]; 4081 } 4082 4083 if( $i + 1 < $plugins ) 4084 { 4085 $retval .= '<br>'; 4086 } 4087 } 4088 } 4089 } 4090 4091 $retval .= COM_endBlock( COM_getBlockTemplate( 'whats_new_block', 'footer' )); 4092 4093 return $retval; 4094 } 4095 4096 /** 4097 * Creates the string that indicates the timespan in which new items were found 4098 * 4099 * @param string $time_string template string 4100 * @param int $time number of seconds in which results are found 4101 * @param string $type type (translated string) of new item 4102 * @param int $amount amount of things that have been found. 4103 */ 4104 function COM_formatTimeString( $time_string, $time, $type = '', $amount = 0 ) 4105 { 4106 global $LANG_WHATSNEW; 4107 4108 $retval = $time_string; 4109 4110 // This is the amount you have to divide the previous by to get the 4111 // different time intervals: hour, day, week, months 4112 $time_divider = array( 60, 60, 24, 7, 30 ); 4113 4114 // These are the respective strings to the numbers above. They have to match 4115 // the strings in $LANG_WHATSNEW (i.e. these are the keys for the array - 4116 // the actual text strings are taken from the language file). 4117 $time_description = array( 'minute', 'hour', 'day', 'week', 'month' ); 4118 $times_description = array( 'minutes', 'hours', 'days', 'weeks', 'months' ); 4119 4120 for( $s = 0; $s < count( $time_divider ); $s++ ) 4121 { 4122 $time = $time / $time_divider[$s]; 4123 if( $time < $time_divider[$s + 1] ) 4124 { 4125 if( $time == 1 ) 4126 { 4127 if( $s == 0 ) 4128 { 4129 $time_str = $time_description[$s]; 4130 } 4131 else // go back to the previous unit, e.g. 1 day -> 24 hours 4132 { 4133 $time_str = $times_description[$s - 1]; 4134 $time *= $time_divider[$s]; 4135 } 4136 } 4137 else 4138 { 4139 $time_str = $times_description[$s]; 4140 } 4141 $fields = array( '%n', '%i', '%t', '%s' ); 4142 $values = array( $amount, $type, $time, $LANG_WHATSNEW[$time_str] ); 4143 $retval = str_replace( $fields, $values, $retval ); 4144 break; 4145 } 4146 } 4147 4148 return $retval; 4149 } 4150 4151 4152 /** 4153 * Displays a message on the webpage 4154 * 4155 * Pulls $msg off the URL string and gets the corresponding message and returns 4156 * it for display on the calling page 4157 * 4158 * @param int $msg ID of message to show 4159 * @param string $plugin Optional Name of plugin to lookup plugin defined message 4160 * @return string HTML block with message 4161 */ 4162 4163 function COM_showMessage( $msg, $plugin='' ) 4164 { 4165 global $_CONF, $MESSAGE, $_IMAGE_TYPE; 4166 4167 $retval = ''; 4168 4169 if( $msg > 0 ) 4170 { 4171 if( !empty( $plugin )) 4172 { 4173 $var = 'PLG_' . $plugin . '_MESSAGE' . $msg; 4174 global $$var; 4175 if( isset( $$var )) 4176 { 4177 $message = $$var; 4178 } 4179 else 4180 { 4181 $message = sprintf( $MESSAGE[61], $plugin ); 4182 COM_errorLog ($MESSAGE[61]. ": " . $var,1); 4183 } 4184 } 4185 else 4186 { 4187 $message = $MESSAGE[$msg]; 4188 } 4189 4190 $timestamp = strftime( $_CONF['daytime'] ); 4191 $retval .= COM_startBlock( $MESSAGE[40] . ' - ' . $timestamp, '', 4192 COM_getBlockTemplate( '_msg_block', 'header' )) 4193 . '<p style="padding:5px"><img src="' . $_CONF['layout_url'] 4194 . '/images/sysmessage.' . $_IMAGE_TYPE . '" border="0" align="left"' 4195 . ' alt="" style="padding-right:5px; padding-bottom:3px">' 4196 . $message . '</p>' 4197 . COM_endBlock( COM_getBlockTemplate( '_msg_block', 'footer' )); 4198 } 4199 4200 return $retval; 4201 } 4202 4203 4204 /** 4205 * Prints Google(tm)-like paging navigation 4206 * 4207 * @param string $base_url base url to use for all generated links 4208 * @param int $curpage current page we are on 4209 * @param int $num_pages Total number of pages 4210 * @param string $page_str page-variable name AND '=' 4211 * @param bool $do_rewrite if true, url-rewriting is respected 4212 * @param string $msg to be displayed with the navigation 4213 * @param string $open_ended replace next/last links with this 4214 * @return string HTML formatted widget 4215 */ 4216 function COM_printPageNavigation( $base_url, $curpage, $num_pages, 4217 $page_str='page=', $do_rewrite=false, $msg='', 4218 $open_ended = '') 4219 { 4220 global $LANG05; 4221 4222 $retval = ''; 4223 4224 if( $num_pages < 2 ) 4225 { 4226 return; 4227 } 4228 4229 if( !$do_rewrite ) 4230 { 4231 $hasargs = strstr( $base_url, '?' ); 4232 if( $hasargs ) 4233 { 4234 $sep = '&'; 4235 } 4236 else 4237 { 4238 $sep = '?'; 4239 } 4240 } 4241 else 4242 { 4243 $sep = '/'; 4244 $page_str = ''; 4245 } 4246 4247 if( $curpage > 1 ) 4248 { 4249 $retval .= '<a href="' . $base_url . '">' . $LANG05[7] . '</a> | '; 4250 $pg = ''; 4251 if( ( $curpage - 1 ) > 1 ) 4252 { 4253 $pg = $sep . $page_str . ( $curpage - 1 ); 4254 } 4255 $retval .= '<a href="' . $base_url . $pg . '">' . $LANG05[6] 4256 . '</a> | '; 4257 } 4258 else 4259 { 4260 $retval .= $LANG05[7] . ' | ' ; 4261 $retval .= $LANG05[6] . ' | ' ; 4262 } 4263 4264 for( $pgcount = ( $curpage - 10 ); ( $pgcount <= ( $curpage + 9 )) AND ( $pgcount <= $num_pages ); $pgcount++ ) 4265 { 4266 if( $pgcount <= 0 ) 4267 { 4268 $pgcount = 1; 4269 } 4270 4271 if( $pgcount == $curpage ) 4272 { 4273 $retval .= '<b>' . $pgcount . '</b> '; 4274 } 4275 else 4276 { 4277 $pg = ''; 4278 if( $pgcount > 1 ) 4279 { 4280 $pg = $sep . $page_str . $pgcount; 4281 } 4282 $retval .= '<a href="' . $base_url . $pg . '">' . $pgcount 4283 . '</a> '; 4284 } 4285 } 4286 4287 if( !empty( $open_ended )) 4288 { 4289 $retval .= '| ' . $open_ended; 4290 } 4291 else if( $curpage == $num_pages ) 4292 { 4293 $retval .= '| ' . $LANG05[5] . ' '; 4294 $retval .= '| ' . $LANG05[8]; 4295 } 4296 else 4297 { 4298 $retval .= '| <a href="' . $base_url . $sep . $page_str 4299 . ( $curpage + 1 ) . '">' . $LANG05[5] . '</a> '; 4300 $retval .= '| <a href="' . $base_url . $sep . $page_str . $num_pages 4301 . '">' . $LANG05[8] . '</a>'; 4302 } 4303 4304 if( !empty( $retval )) 4305 { 4306 if( !empty( $msg )) 4307 { 4308 $msg .= ' '; 4309 } 4310 $retval = '<div class="pagenav">' . $msg . $retval . '</div>'; 4311 } 4312 4313 return $retval; 4314 } 4315 4316 /** 4317 * Returns formatted date/time for user 4318 * 4319 * This function COM_takes a date in either unixtimestamp or in english and 4320 * formats it to the users preference. If the user didn't specify a format 4321 * the format in the config file is used. This returns an array where array[0] 4322 * is the formatted date and array[1] is the unixtimestamp 4323 * 4324 * @param string $date date to format, otherwise we format current date/time 4325 * @return array array[0] is the formatted date and array[1] is the unixtimestamp. 4326 */ 4327 4328 function COM_getUserDateTimeFormat( $date='' ) 4329 { 4330 global $_TABLES, $_USER, $_CONF; 4331 4332 // Get display format for time 4333 4334 if( !empty( $_USER['uid'] ) && ( $_USER['uid'] > 1 )) 4335 { 4336 if( empty( $_USER['format'] )) 4337 { 4338 $dateformat = $_CONF['date']; 4339 } 4340 else 4341 { 4342 $dateformat = $_USER['format']; 4343 } 4344 } 4345 else 4346 { 4347 $dateformat = $_CONF['date']; 4348 } 4349 4350 if( empty( $date )) 4351 { 4352 // Date is empty, get current date/time 4353 $stamp = time(); 4354 } 4355 else if( is_numeric( $date )) 4356 { 4357 // This is a timestamp 4358 $stamp = $date; 4359 } 4360 else 4361 { 4362 // This is a string representation of a date/time 4363 $stamp = strtotime( $date ); 4364 } 4365 4366 // Format the date 4367 4368 $date = strftime( $dateformat, $stamp ); 4369 4370 return array( $date, $stamp ); 4371 } 4372 4373 /** 4374 * Returns user-defined cookie timeout 4375 * 4376 * In account preferences users can specify when their long-term cookie expires. 4377 * This function returns that value. 4378 * 4379 * @return int Cookie time out value in seconds 4380 */ 4381 4382 function COM_getUserCookieTimeout() 4383 { 4384 global $_TABLES, $_USER, $_CONF; 4385 4386 if( empty( $_USER )) 4387 { 4388 return; 4389 } 4390 4391 $timeoutvalue = DB_getItem( $_TABLES['users'], 'cookietimeout', "uid = {$_USER['uid']}" ); 4392 4393 if( empty( $timeoutvalue )) 4394 { 4395 $timeoutvalue = 0; 4396 } 4397 4398 return $timeoutvalue; 4399 } 4400 4401 /** 4402 * Shows who is online in slick little block 4403 * @return string HTML string of online users seperated by line breaks. 4404 */ 4405 4406 function phpblock_whosonline() 4407 { 4408 global $_CONF, $_TABLES, $_USER, $LANG01, $_IMAGE_TYPE; 4409 4410 $retval = ''; 4411 4412 $expire_time = time() - $_CONF['whosonline_threshold']; 4413 4414 $byname = 'username'; 4415 if( $_CONF['show_fullname'] == 1 ) 4416 { 4417 $byname .= ',fullname'; 4418 } 4419 if( $_CONF['remoteauthentication'] ) 4420 { 4421 $byname .= ',remoteusername,remoteservice'; 4422 } 4423 4424 $result = DB_query( "SELECT DISTINCT {$_TABLES['sessions']}.uid,{$byname},photo,showonline FROM {$_TABLES['sessions']},{$_TABLES['users']},{$_TABLES['userprefs']} WHERE {$_TABLES['users']}.uid = {$_TABLES['sessions']}.uid AND {$_TABLES['users']}.uid = {$_TABLES['userprefs']}.uid AND start_time >= $expire_time AND {$_TABLES['sessions']}.uid <> 1 ORDER BY {$byname}" ); 4425 $nrows = DB_numRows( $result ); 4426 4427 $num_anon = 0; 4428 $num_reg = 0; 4429 4430 for( $i = 0; $i < $nrows; $i++ ) 4431 { 4432 $A = DB_fetchArray( $result ); 4433 4434 if( $A['showonline'] == 1 ) 4435 { 4436 $fullname = ''; 4437 if( $_CONF['show_fullname'] == 1 ) 4438 { 4439 $fullname = $A['fullname']; 4440 } 4441 if( $_CONF['remoteauthentication'] ) 4442 { 4443 $username = COM_getDisplayName( $A['uid'], $A['username'], 4444 $fullname, $A['remoteusername'], $A['remoteservice'] ); 4445 } 4446 else 4447 { 4448 $username = COM_getDisplayName( $A['uid'], $A['username'], 4449 $fullname ); 4450 } 4451 $retval .= '<a href="' . $_CONF['site_url'] 4452 . '/users.php?mode=profile&uid=' . $A['uid'] . '">' 4453 . $username . '</a>'; 4454 4455 if( !empty( $A['photo'] ) AND $_CONF['allow_user_photo'] == 1) 4456 { 4457 $retval .= ' <a href="' . $_CONF['site_url'] 4458 . '/users.php?mode=profile&uid=' . $A['uid'] 4459 . '"><img src="' . $_CONF['layout_url'] 4460 . '/images/smallcamera.' . $_IMAGE_TYPE 4461 . '" border="0" alt=""></a>'; 4462 } 4463 $retval .= '<br>'; 4464 $num_reg++; 4465 } 4466 else 4467 { 4468 // this user does not want to show up in Who's Online 4469 $num_anon++; // count as anonymous 4470 } 4471 } 4472 4473 $result = DB_query( "SELECT DISTINCT uid,remote_ip FROM {$_TABLES['sessions']} WHERE uid = 1" ); 4474 $num_anon += DB_numRows( $result ); 4475 4476 if(( $_CONF['whosonline_anonymous'] == 1 ) && 4477 ( empty( $_USER['uid'] ) || ( $_USER['uid'] == 1 ))) 4478 { 4479 // note that we're overwriting the contents of $retval here 4480 if( $num_reg > 0 ) 4481 { 4482 $retval = $LANG01[112] . ': ' . $num_reg . '<br>'; 4483 } 4484 else 4485 { 4486 $retval = ''; 4487 } 4488 } 4489 4490 if( $num_anon > 0 ) 4491 { 4492 $retval .= $LANG01[41] . ': ' . $num_anon . '<br>'; 4493 } 4494 4495 return $retval; 4496 } 4497 4498 /** 4499 * Gets the <option> values for calendar months 4500 * 4501 * @param string $selected Selected month 4502 * @see function COM_getDayFormOptions 4503 * @see function COM_getYearFormOptions 4504 * @see function COM_getHourFormOptions 4505 * @see function COM_getMinuteFormOptions 4506 * @return string HTML Months as option values 4507 */ 4508 4509 function COM_getMonthFormOptions( $selected = '' ) 4510 { 4511 global $LANG_MONTH; 4512 4513 $month_options = ''; 4514 4515 for( $i = 1; $i <= 12; $i++ ) 4516 { 4517 $mval = $i; 4518 $month_options .= '<option value="' . $mval . '"'; 4519 4520 if( $i == $selected ) 4521 { 4522 $month_options .= ' selected="selected"'; 4523 } 4524 4525 $month_options .= '>' . $LANG_MONTH[$mval] . '</option>'; 4526 } 4527 4528 return $month_options; 4529 } 4530 4531 /** 4532 * Gets the <option> values for calendar days 4533 * 4534 * @param string $selected Selected day 4535 * @see function COM_getMonthFormOptions 4536 * @see function COM_getYearFormOptions 4537 * @see function COM_getHourFormOptions 4538 * @see function COM_getMinuteFormOptions 4539 * @return string HTML days as option values 4540 */ 4541 4542 function COM_getDayFormOptions( $selected = '' ) 4543 { 4544 $day_options = ''; 4545 4546 for( $i = 1; $i <= 31; $i++ ) 4547 { 4548 if( $i < 10 ) 4549 { 4550 $dval = '0' . $i; 4551 } 4552 else 4553 { 4554 $dval = $i; 4555 } 4556 4557 $day_options .= '<option value="' . $dval . '"'; 4558 4559 if( $i == $selected ) 4560 { 4561 $day_options .= ' selected="selected"'; 4562 } 4563 4564 $day_options .= '>' . $dval . '</option>'; 4565 } 4566 4567 return $day_options; 4568 } 4569 4570 /** 4571 * Gets the <option> values for calendar years 4572 * 4573 * Returns Option list Containing 5 years starting with current 4574 * unless @selected is < current year then starts with @selected 4575 * 4576 * @param string $selected Selected year 4577 * @see function COM_getMonthFormOptions 4578 * @see function COM_getDayFormOptions 4579 * @see function COM_getHourFormOptions 4580 * @see function COM_getMinuteFormOptions 4581 * @return string HTML years as option values 4582 */ 4583 4584 function COM_getYearFormOptions( $selected = '' ) 4585 { 4586 $year_options = ''; 4587 $cur_year = date( 'Y', time() ); 4588 $start_year = $cur_year; 4589 4590 if( !empty( $selected )) 4591 { 4592 if( $selected < $cur_year ) 4593 { 4594 $start_year = $selected; 4595 } 4596 } 4597 4598 for( $i = $start_year - 1; $i <= $cur_year + 5; $i++ ) 4599 { 4600 $year_options .= '<option value="' . $i . '"'; 4601 4602 if( $i == $selected ) 4603 { 4604 $year_options .= ' selected="selected"'; 4605 } 4606 4607 $year_options .= '>' . $i . '</option>'; 4608 } 4609 4610 return $year_options; 4611 } 4612 4613 /** 4614 * Gets the <option> values for clock hours 4615 * 4616 * @param string $selected Selected hour 4617 * @param int $mode 12 or 24 hour mode 4618 * @return string HTML string of options 4619 * @see function COM_getMonthFormOptions 4620 * @see function COM_getDayFormOptions 4621 * @see function COM_getYearFormOptions 4622 * @see function COM_getMinuteFormOptions 4623 */ 4624 4625 function COM_getHourFormOptions( $selected = '', $mode = 12 ) 4626 { 4627 $hour_options = ''; 4628 4629 if( $mode == 12 ) 4630 { 4631 for( $i = 1; $i <= 11; $i++ ) 4632 { 4633 if( $i < 10 ) 4634 { 4635 $hval = '0' . $i; 4636 } 4637 else 4638 { 4639 $hval = $i; 4640 } 4641 4642 if( $i == 1 ) 4643 { 4644 $hour_options .= '<option value="12"'; 4645 4646 if( $selected == 12 ) 4647 { 4648 $hour_options .= ' selected="selected"'; 4649 } 4650 4651 $hour_options .= '>12</option>'; 4652 } 4653 4654 $hour_options .= '<option value="' . $hval . '"'; 4655 4656 if( $selected == $i ) 4657 { 4658 $hour_options .= ' selected="selected"'; 4659 } 4660 4661 $hour_options .= '>' . $i . '</option>'; 4662 } 4663 } 4664 else // if( $mode == 24 ) 4665 { 4666 for( $i = 0; $i < 24; $i++ ) 4667 { 4668 if( $i < 10 ) 4669 { 4670 $hval = '0' . $i; 4671 } 4672 else 4673 { 4674 $hval = $i; 4675 } 4676 4677 $hour_options .= '<option value="' . $hval . '"'; 4678 4679 if( $selected == $i ) 4680 { 4681 $hour_options .= ' selected="selected"'; 4682 } 4683 4684 $hour_options .= '>' . $i . '</option>'; 4685 } 4686 } 4687 4688 return $hour_options; 4689 } 4690 4691 /** 4692 * Gets the <option> values for clock minutes 4693 * 4694 * @param string $selected Selected minutes 4695 * @param integer $step number of minutes between options, e.g. 15 4696 * @see function COM_getMonthFormOptions 4697 * @see function COM_getDayFormOptions 4698 * @see function COM_getHourFormOptions 4699 * @see function COM_getYearFormOptions 4700 * @return string HTML of option minutes 4701 */ 4702 4703 function COM_getMinuteFormOptions( $selected = '', $step = 1 ) 4704 { 4705 $minute_options = ''; 4706 4707 if(( $step < 1 ) || ( $step > 30 )) 4708 { 4709 $step = 1; 4710 } 4711 4712 for( $i = 0; $i <= 59; $i += $step ) 4713 { 4714 if( $i < 10 ) 4715 { 4716 $mval = '0' . $i; 4717 } 4718 else 4719 { 4720 $mval = $i; 4721 } 4722 4723 $minute_options .= '<option value="' . $mval . '"'; 4724 4725 if( $selected == $i ) 4726 { 4727 $minute_options .= ' selected="selected"'; 4728 } 4729 4730 $minute_options .= '>' . $mval . '</option>'; 4731 } 4732 4733 return $minute_options; 4734 } 4735 4736 /** 4737 * for backward compatibility only 4738 * - this function should always have been called COM_getMinuteFormOptions 4739 * 4740 */ 4741 function COM_getMinuteOptions( $selected = '', $step = 1 ) 4742 { 4743 return COM_getMinuteFormOptions( $selected, $step ); 4744 } 4745 4746 /** 4747 * Create an am/pm selector dropdown menu 4748 * 4749 * @param string $name name of the <select> 4750 * @param string $selected preselection: 'am' or 'pm' 4751 * @return string HTML for the dropdown; empty string in 24 hour mode 4752 * 4753 */ 4754 function COM_getAmPmFormSelection( $name, $selected = '' ) 4755 { 4756 global $_CONF; 4757 4758 $retval = ''; 4759 4760 if( isset( $_CONF['hour_mode'] ) && ( $_CONF['hour_mode'] == 24 )) 4761 { 4762 $retval = ''; 4763 } 4764 else 4765 { 4766 if( empty( $selected )) 4767 { 4768 $selected = date( 'a' ); 4769 } 4770 4771 $retval .= '<select name="' . $name . '">' . LB; 4772 $retval .= '<option value="am"'; 4773 if( $selected == 'am' ) 4774 { 4775 $retval .= ' selected="selected"'; 4776 } 4777 $retval .= '>am</option>' . LB . '<option value="pm"'; 4778 if( $selected == 'pm' ) 4779 { 4780 $retval .= ' selected="selected"'; 4781 } 4782 $retval .= '>pm</option>' . LB . '</select>' . LB; 4783 } 4784 4785 return $retval; 4786 } 4787 4788 /** 4789 * Creates an HTML unordered list from the given array. 4790 * It formats one list item per array element, using the list.thtml 4791 * and listitem.thtml templates. 4792 * 4793 * @param array $listofitems Items to list out 4794 * @return string HTML unordered list of array items 4795 */ 4796 4797 function COM_makeList( $listofitems, $classname = '' ) 4798 { 4799 global $_CONF; 4800 4801 $list = new Template( $_CONF['path_layout'] ); 4802 $list->set_file( array( 'list' => 'list.thtml', 4803 'listitem' => 'listitem.thtml' )); 4804 $list->set_var( 'site_url', $_CONF['site_url'] ); 4805 $list->set_var( 'layout_url', $_CONF['layout_url'] ); 4806 if( empty( $classname )) 4807 { 4808 $list->set_var( 'list_class', '' ); 4809 $list->set_var( 'list_class_name', '' ); 4810 } 4811 else 4812 { 4813 $list->set_var( 'list_class', 'class="' . $classname . '"' ); 4814 $list->set_var( 'list_class_name', $classname ); 4815 } 4816 4817 foreach( $listofitems as $oneitem ) 4818 { 4819 $list->set_var( 'list_item', $oneitem ); 4820 $list->parse( 'list_items', 'listitem', true ); 4821 } 4822 4823 $list->parse( 'newlist', 'list', true ); 4824 4825 return $list->finish( $list->get_var( 'newlist' )); 4826 } 4827 4828 /** 4829 * Check if speed limit applies for current IP address. 4830 * 4831 * @param type string type of speed limit to check, e.g. 'submit', 'comment' 4832 * @param max int max number of allowed tries within speed limit 4833 * @return int 0 = does not apply, else: seconds since last post 4834 */ 4835 function COM_checkSpeedlimit( $type = 'submit', $max = 1 ) 4836 { 4837 global $_TABLES; 4838 4839 $last = 0; 4840 4841 $res = DB_query( "SELECT date FROM {$_TABLES['speedlimit']} WHERE (type = '$type') AND (ipaddress = '{$_SERVER['REMOTE_ADDR']}') ORDER BY date ASC" ); 4842 4843 // If the number of allowed tries has not been reached, 4844 // return 0 (didn't hit limit) 4845 if( DB_numRows( $res ) < $max ) 4846 { 4847 return $last; 4848 } 4849 4850 list( $date ) = DB_fetchArray( $res ); 4851 4852 if( !empty( $date )) 4853 { 4854 $last = time() - $date; 4855 if( $last == 0 ) 4856 { 4857 // just in case someone manages to submit something in < 1 sec. 4858 $last = 1; 4859 } 4860 } 4861 4862 return $last; 4863 } 4864 4865 /** 4866 * Store post info for current IP address. 4867 * 4868 * @param type string type of speed limit, e.g. 'submit', 'comment' 4869 * 4870 */ 4871 function COM_updateSpeedlimit( $type = 'submit' ) 4872 { 4873 global $_TABLES; 4874 4875 DB_save( $_TABLES['speedlimit'], 'ipaddress,date,type', 4876 "'{$_SERVER['REMOTE_ADDR']}',unix_timestamp(),'$type'" ); 4877 } 4878 4879 /** 4880 * Clear out expired speed limits, i.e. entries older than 'x' seconds 4881 * 4882 * @param speedlimit int number of seconds 4883 * @param type string type of speed limit, e.g. 'submit', 'comment' 4884 * 4885 */ 4886 function COM_clearSpeedlimit( $speedlimit = 60, $type = '' ) 4887 { 4888 global $_TABLES; 4889 4890 $sql = "DELETE FROM {$_TABLES['speedlimit']} WHERE "; 4891 if( !empty( $type )) 4892 { 4893 $sql .= "(type = '$type') AND "; 4894 } 4895 $sql .= "(date < unix_timestamp() - $speedlimit)"; 4896 DB_query( $sql ); 4897 } 4898 4899 /** 4900 * Wrapper function for URL class so as to not confuse people as this will 4901 * eventually get used all over the place 4902 * 4903 * This function returns a crawler friendly URL (if possible) 4904 * 4905 * @param string $url URL to try to build crawler friendly URL for 4906 * @return string Rewritten URL 4907 */ 4908 4909 function COM_buildURL( $url ) 4910 { 4911 global $_URL; 4912 4913 return $_URL->buildURL( $url ); 4914 } 4915 4916 /** 4917 * Wrapper function for URL class so as to not confuse people 4918 * 4919 * This function sets the name of the arguments found in url 4920 * 4921 * @param array $names Names of arguments in query string to assign to values 4922 * @return boolean True if successful 4923 */ 4924 4925 function COM_setArgNames( $names ) 4926 { 4927 global $_URL; 4928 4929 return $_URL->setArgNames( $names ); 4930 } 4931 4932 /** 4933 * Wrapper function for URL class 4934 * 4935 * returns value for specified argument 4936 * 4937 * @param string $name argument to get value for 4938 * @return string Argument value 4939 */ 4940 4941 function COM_getArgument( $name ) 4942 { 4943 global $_URL; 4944 4945 return $_URL->getArgument( $name ); 4946 } 4947 4948 /** 4949 * Occurences / time 4950 * 4951 * This will take a number of occurrences, and number of seconds for the time span and return 4952 * the smallest #/time interval 4953 * 4954 * @param int $occurrences how many occurrences during time interval 4955 * @param int $timespan time interval in seconds 4956 * @return int Seconds per interval 4957 */ 4958 4959 function COM_getRate( $occurrences, $timespan ) 4960 { 4961 // want to define some common time words (yes, dirk, i need to put this in LANG) 4962 // time words and their value in seconds 4963 // week is 7 * day, month is 30 * day, year is 365.25 * day 4964 4965 $common_time = array( 4966 "second" => 1, 4967 "minute" => 60, 4968 "hour" => 3600, 4969 "day" => 86400, 4970 "week" => 604800, 4971 "month" => 2592000, 4972 "year" => 31557600 4973 ); 4974 4975 if( $occurrences != 0 ) 4976 { 4977 $rate = ( int )( $timespan / $occurrences ); 4978 $adjustedRate = $occurrences + 1; 4979 $time_unit = 'second'; 4980 4981 $found_one = false; 4982 4983 foreach( $common_time as $unit=>$seconds ) 4984 { 4985 if( $rate > $seconds ) 4986 { 4987 $foo = ( int )(( $rate / $seconds ) + .5 ); 4988 4989 if(( $foo < $occurrences ) && ( $foo > 0 )) 4990 { 4991 $adjustedRate = $foo; 4992 $time_unit = $unit; 4993 } 4994 } 4995 } 4996 4997 $singular = '1 shout every ' . $adjustedRate . ' ' . $time_unit; 4998 4999 if( $adjustedRate > 1 ) 5000 { 5001 $singular .= 's'; 5002 } 5003 } 5004 else 5005 { 5006 $singular = 'No events'; 5007 } 5008 5009 return $singular; 5010 } 5011 5012 /** 5013 * Return SQL expression to check for permissions. 5014 * 5015 * Creates part of an SQL expression that can be used to request items with the 5016 * standard set of Geeklog permissions. 5017 * 5018 * @param string $type part of the SQL expr. e.g. 'WHERE', 'AND' 5019 * @param int $u_id user id or 0 = current user 5020 * @param int $access access to check for (2=read, 3=r&write) 5021 * @param string $table table name if ambiguous (e.g. in JOINs) 5022 * @return string SQL expression string (may be empty) 5023 * 5024 */ 5025 function COM_getPermSQL( $type = 'WHERE', $u_id = 0, $access = 2, $table = '' ) 5026 { 5027 global $_USER, $_GROUPS; 5028 5029 if( !empty( $table )) 5030 { 5031 $table .= '.'; 5032 } 5033 if( $u_id <= 0) 5034 { 5035 if( empty( $_USER['uid'] )) 5036 { 5037 $uid = 1; 5038 } 5039 else 5040 { 5041 $uid = $_USER['uid']; 5042 } 5043 } 5044 else 5045 { 5046 $uid = $u_id; 5047 } 5048 5049 $UserGroups = array(); 5050 if(( empty( $_USER['uid'] ) && ( $uid == 1 )) || ( $uid == $_USER['uid'] )) 5051 { 5052 if( empty( $_GROUPS )) 5053 { 5054 $_GROUPS = SEC_getUserGroups( $uid ); 5055 } 5056 $UserGroups = $_GROUPS; 5057 } 5058 else 5059 { 5060 $UserGroups = SEC_getUserGroups( $uid ); 5061 } 5062 5063 if( empty( $UserGroups )) 5064 { 5065 // this shouldn't really happen, but if it does, handle user 5066 // like an anonymous user 5067 $uid = 1; 5068 } 5069 5070 if( SEC_inGroup( 'Root', $uid )) 5071 { 5072 return ''; 5073 } 5074 5075 $sql = ' ' . $type . ' ('; 5076 5077 if( $uid > 1 ) 5078 { 5079 $sql .= "(({$table}owner_id = '{$uid}') AND ({$table}perm_owner >= $access)) OR "; 5080 5081 $sql .= "(({$table}group_id IN (" . implode( ',', $UserGroups ) 5082 . ")) AND ({$table}perm_group >= $access)) OR "; 5083 $sql .= "({$table}perm_members >= $access)"; 5084 } 5085 else 5086 { 5087 $sql .= "{$table}perm_anon >= $access"; 5088 } 5089 5090 $sql .= ')'; 5091 5092 return $sql; 5093 } 5094 5095 /** 5096 * Return SQL expression to check for allowed topics. 5097 * 5098 * Creates part of an SQL expression that can be used to only request stories 5099 * from topics to which the user has access to. 5100 * 5101 * Note that this function does an SQL request, so you should cache 5102 * the resulting SQL expression if you need it more than once. 5103 * 5104 * @param string $type part of the SQL expr. e.g. 'WHERE', 'AND' 5105 * @param int $u_id user id or 0 = current user 5106 * @param string $table table name if ambiguous (e.g. in JOINs) 5107 * @return string SQL expression string (may be empty) 5108 * 5109 */ 5110 function COM_getTopicSQL( $type = 'WHERE', $u_id = 0, $table = '' ) 5111 { 5112 global $_TABLES, $_USER, $_GROUPS; 5113 5114 $topicsql = ' ' . $type . ' '; 5115 5116 if( !empty( $table )) 5117 { 5118 $table .= '.'; 5119 } 5120 5121 $UserGroups = array(); 5122 if(( $u_id <= 0 ) || ( $u_id == $_USER['uid'] )) 5123 { 5124 if( isset( $_USER['uid'] )) 5125 { 5126 $uid = $_USER['uid']; 5127 } 5128 else 5129 { 5130 $uid = 1; 5131 } 5132 $UserGroups = $_GROUPS; 5133 } 5134 else 5135 { 5136 $uid = $u_id; 5137 $UserGroups = SEC_getUserGroups( $uid ); 5138 } 5139 5140 if( empty( $UserGroups )) 5141 { 5142 // this shouldn't really happen, but if it does, handle user 5143 // like an anonymous user 5144 $uid = 1; 5145 } 5146 5147 if( SEC_inGroup( 'Root', $uid )) 5148 { 5149 return ''; 5150 } 5151 5152 $result = DB_query( "SELECT tid FROM {$_TABLES['topics']}" 5153 . COM_getPermSQL( 'WHERE', $uid )); 5154 $tids = array(); 5155 while( $T = DB_fetchArray( $result )) 5156 { 5157 $tids[] = $T['tid']; 5158 } 5159 5160 if( sizeof( $tids ) > 0 ) 5161 { 5162 $topicsql .= "({$table}tid IN ('" . implode( "','", $tids ) . "'))"; 5163 } 5164 else 5165 { 5166 $topicsql .= '0'; 5167 } 5168 5169 return $topicsql; 5170 } 5171 5172 /** 5173 * Strip slashes from a string only when magic_quotes_gpc = on. 5174 * 5175 * @param string $text The text 5176 * @return string The text, possibly without slashes. 5177 */ 5178 function COM_stripslashes( $text ) 5179 { 5180 if( get_magic_quotes_gpc() == 1 ) 5181 { 5182 return( stripslashes( $text )); 5183 } 5184 5185 return( $text ); 5186 } 5187 5188 /** 5189 * Filter parameters passed per GET (URL) or POST. 5190 * 5191 * @param string $parameter the parameter to test 5192 * @param boolean $isnumeric true if $parameter is supposed to be numeric 5193 * @return string the filtered parameter (may now be empty or 0) 5194 * 5195 */ 5196 function COM_applyFilter( $parameter, $isnumeric = false ) 5197 { 5198 $log_manipulation = false; // set to true to log when the filter applied 5199 5200 $p = COM_stripslashes( $parameter ); 5201 $p = strip_tags( $p ); 5202 $p = COM_killJS( $p ); // doesn't help a lot right now, but still ... 5203 5204 if( $isnumeric ) 5205 { 5206 // Note: PHP's is_numeric() accepts values like 4e4 as numeric 5207 if( !is_numeric( $p ) || ( preg_match( '/^-?\d+$/', $p ) == 0 )) 5208 { 5209 $p = 0; 5210 } 5211 } 5212 else 5213 { 5214 $p = preg_replace( '/\/\*.*/', '', $p ); 5215 $pa = explode( "'", $p ); 5216 $pa = explode( '"', $pa[0] ); 5217 $pa = explode( '`', $pa[0] ); 5218 $pa = explode( ';', $pa[0] ); 5219 $pa = explode( ',', $pa[0] ); 5220 $pa = explode( '\\', $pa[0] ); 5221 $p = $pa[0]; 5222 } 5223 5224 if( $log_manipulation ) 5225 { 5226 if( strcmp( $p, $parameter ) != 0 ) 5227 { 5228 COM_errorLog( "Filter applied: >> $parameter << filtered to $p [IP {$_SERVER['REMOTE_ADDR']}]", 1); 5229 } 5230 } 5231 5232 return $p; 5233 } 5234 5235 /** 5236 * Sanitize a URL 5237 * 5238 * @param string $url URL to sanitized 5239 * @param array $allowed_protocols array of allowed protocols 5240 * @param string $default_protocol replacement protocol (default: http) 5241 * @return string sanitized URL 5242 * 5243 */ 5244 function COM_sanitizeUrl( $url, $allowed_protocols = '', $default_protocol = '' ) 5245 { 5246 global $_CONF; 5247 5248 if( empty( $allowed_protocols )) 5249 { 5250 $allowed_protocols = $_CONF['allowed_protocols']; 5251 } 5252 else if( !is_array( $allowed_protocols )) 5253 { 5254 $allowed_protocols = array( $allowed_protocols ); 5255 } 5256 5257 if( empty( $default_protocol )) 5258 { 5259 $default_protocol = 'http:'; 5260 } 5261 else if( substr( $default_protocol, -1 ) != ':' ) 5262 { 5263 $default_protocol .= ':'; 5264 } 5265 5266 $url = strip_tags( $url ); 5267 if( !empty( $url )) 5268 { 5269 $pos = MBYTE_strpos( $url, ':' ); 5270 if( $pos === false ) 5271 { 5272 $url = $default_protocol . '//' . $url; 5273 } 5274 else 5275 { 5276 $protocol = MBYTE_substr( $url, 0, $pos + 1 ); 5277 $found_it = false; 5278 foreach( $allowed_protocols as $allowed ) 5279 { 5280 if( substr( $allowed, -1 ) != ':' ) 5281 { 5282 $allowed .= ':'; 5283 } 5284 if( $protocol == $allowed ) 5285 { 5286 $found_it = true; 5287 break; 5288 } 5289 } 5290 if( !$found_it ) 5291 { 5292 $url = $default_protocol . MBYTE_substr( $url, $pos + 1 ); 5293 } 5294 } 5295 } 5296 5297 return $url; 5298 } 5299 5300 /** 5301 * Detect links in a plain-ascii text and turn them into clickable links. 5302 * Will detect links starting with "http:", "https:", "ftp:", and "www.". 5303 * 5304 * Derived from a newsgroup posting by Andreas Schwarz in 5305 * news:de.comp.lang.php <aieq4p$12jn2i$3@ID-16486.news.dfncis.de> 5306 * 5307 * @param string $text the (plain-ascii) text string 5308 * @return string the same string, with links enclosed in <a>...</a> tags 5309 * 5310 */ 5311 function COM_makeClickableLinks( $text ) 5312 { 5313 $text = preg_replace( '/([^"]?)((((ht|f)tps?):(\/\/)|www\.)[a-z0-9%&_\-\+,;=:@~#\/.\?\[\]]+(\/|[+0-9a-z]))/is', '\\1<a href="\\2">\\2</a>', $text ); 5314 $text = str_replace( '<a href="www', '<a href="http://www', $text ); 5315 5316 return $text; 5317 } 5318 5319 /** 5320 * Undo the conversion of URLs to clickable links (in plain text posts), 5321 * e.g. so that we can present the user with the post as they entered them. 5322 * 5323 * @param string $txt story text 5324 * @param string story text without links 5325 * 5326 */ 5327 function COM_undoClickableLinks( $text ) 5328 { 5329 $text = preg_replace( '/<a href="[^"]*">([^<]*)<\/a>/', '\1', $text ); 5330 5331 return $text; 5332 } 5333 5334 /** 5335 * Highlight the words from a search query in a given text string. 5336 * 5337 * @param string $text the text 5338 * @param string $query the search query 5339 * @return string the text with highlighted search words 5340 * 5341 */ 5342 function COM_highlightQuery( $text, $query ) 5343 { 5344 $query = str_replace( '+', ' ', $query ); 5345 5346 // escape all the other PCRE special characters 5347 $query = preg_quote( $query ); 5348 5349 // ugly workaround: 5350 // Using the /e modifier in preg_replace will cause all double quotes to 5351 // be returned as \" - so we replace all \" in the result with unescaped 5352 // double quotes. Any actual \" in the original text therefore have to be 5353 // turned into \\" first ... 5354 $text = str_replace( '\\"', '\\\\"', $text ); 5355 5356 $mywords = explode( ' ', $query ); 5357 foreach( $mywords as $searchword ) 5358 { 5359 if( !empty( $searchword )) 5360 { 5361 $searchword = preg_quote( str_replace( "'", "\'", $searchword )); 5362 $text = preg_replace( '/(\>(((?>[^><]+)|(?R))*)\<)/ie', "preg_replace('/(?>$searchword+)/i','<span class=\"highlight\">$searchword</span>','\\0')", '<!-- x -->' . $text . '<!-- x -->' ); 5363 } 5364 } 5365 5366 // ugly workaround, part 2 5367 $text = str_replace( '\\"', '"', $text ); 5368 5369 return $text; 5370 } 5371 5372 /** 5373 * Determines the difference between two dates. 5374 * 5375 * This will takes either unixtimestamps or English dates as input and will 5376 * automatically do the date diff on the more recent of the two dates (e.g. the 5377 * order of the two dates given doesn't matter). 5378 * 5379 * @author Tony Bibbs <tony.bibbs@iowa.gov 5380 * @access public 5381 * @param string $interval Can be: 5382 * y = year 5383 * m = month 5384 * w = week 5385 * h = hours 5386 * i = minutes 5387 * s = seconds 5388 * @param string|int $date1 English date (e.g. 10 Dec 2004) or unixtimestamp 5389 * @param string|int $date2 English date (e.g. 10 Dec 2004) or unixtimestamp 5390 * @return int Difference of the two dates in the unit of time indicated by the interval 5391 * 5392 */ 5393 function COM_dateDiff( $interval, $date1, $date2 ) 5394 { 5395 // Convert dates to timestamps, if needed. 5396 if( !is_numeric( $date1 )) 5397 { 5398 $date1 = strtotime( $date1 ); 5399 } 5400 5401 if( !is_numeric( $date2 )) 5402 { 5403 $date2 = strtotime( $date2 ); 5404 } 5405 5406 // Function roughly equivalent to the ASP "DateDiff" function 5407 if( $date2 > $date1 ) 5408 { 5409 $seconds = $date2 - $date1; 5410 } 5411 else 5412 { 5413 $seconds = $date1 - $date2; 5414 } 5415 5416 switch( $interval ) 5417 { 5418 case "y": 5419 list($year1, $month1, $day1) = split('-', date('Y-m-d', $date1)); 5420 list($year2, $month2, $day2) = split('-', date('Y-m-d', $date2)); 5421 $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1)); 5422 $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2)); 5423 $diff = $year2 - $year1; 5424 if($month1 > $month2) { 5425 $diff -= 1; 5426 } elseif($month1 == $month2) { 5427 if($day1 > $day2) { 5428 $diff -= 1; 5429 } elseif($day1 == $day2) { 5430 if($time1 > $time2) { 5431 $diff -= 1; 5432 } 5433 } 5434 } 5435 break; 5436 case "m": 5437 list($year1, $month1, $day1) = split('-', date('Y-m-d', $date1)); 5438 list($year2, $month2, $day2) = split('-', date('Y-m-d', $date2)); 5439 $time1 = (date('H',$date1)*3600) + (date('i',$date1)*60) + (date('s',$date1)); 5440 $time2 = (date('H',$date2)*3600) + (date('i',$date2)*60) + (date('s',$date2)); 5441 $diff = ($year2 * 12 + $month2) - ($year1 * 12 + $month1); 5442 if($day1 > $day2) { 5443 $diff -= 1; 5444 } elseif($day1 == $day2) { 5445 if($time1 > $time2) { 5446 $diff -= 1; 5447 } 5448 } 5449 break; 5450 case "w": 5451 // Only simple seconds calculation needed from here on 5452 $diff = floor($seconds / 604800); 5453 break; 5454 case "d": 5455 $diff = floor($seconds / 86400); 5456 break; 5457 case "h": 5458 $diff = floor($seconds / 3600); 5459 break; 5460 case "i": 5461 $diff = floor($seconds / 60); 5462 break; 5463 case "s": 5464 $diff = $seconds; 5465 break; 5466 } 5467 5468 return $diff; 5469 } 5470 5471 /** 5472 * Try to figure out our current URL, including all parameters. 5473 * 5474 * This is an ugly hack since there's no single variable that returns what 5475 * we want and the variables used here may not be available on all servers 5476 * and / or setups. 5477 * 5478 * Seems to work on Apache (1.3.x and 2.x), IIS, and Zeus ... 5479 * 5480 * @return string complete URL, e.g. 'http://www.example.com/blah.php?foo=bar' 5481 * 5482 */ 5483 function COM_getCurrentURL() 5484 { 5485 global $_CONF; 5486 5487 $thisUrl = ''; 5488 5489 if( empty( $_SERVER['SCRIPT_URI'] )) 5490 { 5491 if( !empty( $_SERVER['DOCUMENT_URI'] )) 5492 { 5493 $thisUrl = $_SERVER['DOCUMENT_URI']; 5494 } 5495 } 5496 else 5497 { 5498 $thisUrl = $_SERVER['SCRIPT_URI']; 5499 } 5500 if( !empty( $thisUrl ) && !empty( $_SERVER['QUERY_STRING'] )) 5501 { 5502 $thisUrl .= '?' . $_SERVER['QUERY_STRING']; 5503 } 5504 if( empty( $thisUrl )) 5505 { 5506 $requestUri = $_SERVER['REQUEST_URI']; 5507 if( empty( $_SERVER['REQUEST_URI'] )) 5508 { 5509 // on a Zeus webserver, prefer PATH_INFO over SCRIPT_NAME 5510 if( empty( $_SERVER['PATH_INFO'] )) 5511 { 5512 $requestUri = $_SERVER['SCRIPT_NAME']; 5513 } 5514 else 5515 { 5516 $requestUri = $_SERVER['PATH_INFO']; 5517 } 5518 if( !empty( $_SERVER['QUERY_STRING'] )) 5519 { 5520 $requestUri .= '?' . $_SERVER['QUERY_STRING']; 5521 } 5522 } 5523 5524 $firstslash = strpos( $_CONF['site_url'], '/' ); 5525 if( $firstslash === false ) 5526 { 5527 // special case - assume it's okay 5528 $thisUrl = $_CONF['site_url'] . $requestUri; 5529 } 5530 else if( $firstslash + 1 == strrpos( $_CONF['site_url'], '/' )) 5531 { 5532 // site is in the document root 5533 $thisUrl = $_CONF['site_url'] . $requestUri; 5534 } 5535 else 5536 { 5537 // extract server name first 5538 $pos = strpos( $_CONF['site_url'], '/', $firstslash + 2 ); 5539 $thisUrl = substr( $_CONF['site_url'], 0, $pos ) . $requestUri; 5540 } 5541 } 5542 5543 return $thisUrl; 5544 } 5545 5546 /** 5547 * Check if we're on Geeklog's index page. 5548 * 5549 * See if we're on the main index page (first page, no topics selected). 5550 * 5551 * @return bool true = we're on the frontpage, false = we're not 5552 * 5553 */ 5554 function COM_onFrontpage() 5555 { 5556 global $_CONF, $topic, $page, $newstories; 5557 5558 // Note: We can't use $PHP_SELF here since the site may not be in the 5559 // DocumentRoot 5560 $onFrontpage = false; 5561 5562 // on a Zeus webserver, prefer PATH_INFO over SCRIPT_NAME 5563 if( empty( $_SERVER['PATH_INFO'] )) 5564 { 5565 $scriptName = $_SERVER['SCRIPT_NAME']; 5566 } 5567 else 5568 { 5569 $scriptName = $_SERVER['PATH_INFO']; 5570 } 5571 5572 preg_match( '/\/\/[^\/]*(.*)/', $_CONF['site_url'], $pathonly ); 5573 if(( $scriptName == $pathonly[1] . '/index.php' ) && 5574 empty( $topic ) && ( $page == 1 ) && !$newstories ) 5575 { 5576 $onFrontpage = true; 5577 } 5578 5579 return $onFrontpage; 5580 } 5581 5582 /** 5583 * Check if we're on Geeklog's index page [deprecated] 5584 * 5585 * Note that this function returns FALSE when we're on the index page. Due to 5586 * the inverted return values, it has been deprecated and is only provided for 5587 * backward compatibility - use COM_onFrontpage() instead. 5588 * 5589 * @see COM_onFrontpage 5590 * 5591 */ 5592 function COM_isFrontpage() 5593 { 5594 return !COM_onFrontpage(); 5595 } 5596 5597 /** 5598 * Ensure an ID contains only alphanumeric characters, dots, dashes, or underscores 5599 * 5600 * @param string $id the ID to sanitize 5601 * @param boolean $new_id true = create a new ID in case we end up with an empty string 5602 * @return string the sanitized ID 5603 */ 5604 function COM_sanitizeID( $id, $new_id = true ) 5605 { 5606 $id = str_replace( ' ', '', $id ); 5607 $id = str_replace( array( '/', '\\', ':', '+' ), '-', $id ); 5608 $id = preg_replace( '/[^a-zA-Z0-9\-_\.]/', '', $id ); 5609 if( empty( $id ) && $new_id ) 5610 { 5611 $id = COM_makesid(); 5612 } 5613 5614 return $id; 5615 } 5616 5617 /** Converts a number for output into a formatted number with thousands- 5618 * separator, comma-separator and fixed decimals if necessary 5619 * 5620 * @param float $number Number that will be formatted 5621 * @return string formatted number 5622 */ 5623 function COM_numberFormat( $number ) 5624 { 5625 global $_CONF; 5626 5627 if( $number - abs( $number ) > 0 ) // number has decimals 5628 { 5629 $dc = $_CONF['decimal_count']; 5630 } 5631 else 5632 { 5633 $dc = 0; 5634 } 5635 $ts = $_CONF['thousand_separator']; 5636 $ds = $_CONF['decimal_separator']; 5637 5638 return number_format( $number, $dc, $ds, $ts ); 5639 } 5640 5641 /** 5642 * Convert a text based date YYYY-MM-DD to a unix timestamp integer value 5643 * 5644 * @param string $date Date in the format YYYY-MM-DD 5645 * @param string $time Option time in the format HH:MM::SS 5646 * @return int UNIX Timestamp 5647 */ 5648 function COM_convertDate2Timestamp( $date, $time = '' ) 5649 { 5650 $atoks = array(); 5651 $btoks = array(); 5652 5653 // Breakup the string using either a space, fwd slash, dash, bkwd slash or 5654 // colon as a delimiter 5655 $atok = strtok( $date, ' /-\\:' ); 5656 while( $atok !== FALSE ) 5657 { 5658 $atoks[] = $atok; 5659 $atok = strtok( ' /-\\:' ); // get the next token 5660 } 5661 5662 for( $i = 0; $i < 3; $i++ ) 5663 { 5664 if( !isset( $atoks[$i] ) || !is_numeric( $atoks[$i] )) 5665 { 5666 $atoks[$i] = 0; 5667 } 5668 } 5669 5670 if( $time == '' ) 5671 { 5672 $timestamp = mktime( 0, 0, 0, $atoks[1], $atoks[2], $atoks[0] ); 5673 } 5674 else 5675 { 5676 $btok = strtok( $time, ' /-\\:' ); 5677 while( $btok !== FALSE ) 5678 { 5679 $btoks[] = $btok; 5680 $btok = strtok( ' /-\\:' ); 5681 } 5682 5683 for( $i = 0; $i < 3; $i++ ) 5684 { 5685 if( !isset( $btoks[$i] ) || !is_numeric( $btoks[$i] )) 5686 { 5687 $btoks[$i] = 0; 5688 } 5689 } 5690 5691 $timestamp = mktime( $btoks[0], $btoks[1], $btoks[2], 5692 $atoks[1], $atoks[2], $atoks[0] ); 5693 } 5694 5695 return $timestamp; 5696 } 5697 5698 /** 5699 * Get the HTML for an image with height & width 5700 * 5701 * @param string $file full path to the file 5702 * @return string html that will be included in the img-tag 5703 */ 5704 function COM_getImgSizeAttributes( $file ) 5705 { 5706 $sizeattributes = ''; 5707 5708 if( file_exists( $file )) 5709 { 5710 $dimensions = getimagesize( $file ); 5711 if( !empty( $dimensions[0] ) AND !empty( $dimensions[1] )) 5712 { 5713 $sizeattributes = 'width="' . $dimensions[0] 5714 . '" height="' . $dimensions[1] . '" '; 5715 } 5716 } 5717 5718 return $sizeattributes; 5719 } 5720 5721 /** 5722 * Display a message and abort 5723 * 5724 * @param int $msg message number 5725 * @param string $plugin plugin name, if applicable 5726 * @param int $http_status HTTP status code to send with the message 5727 * @param string $http_text Textual version of the HTTP status code 5728 * 5729 * @note Displays the message and aborts the script. 5730 * 5731 */ 5732 function COM_displayMessageAndAbort( $msg, $plugin = '', $http_status = 200, $http_text = 'OK') 5733 { 5734 $display = COM_siteHeader( 'menu' ) 5735 . COM_showMessage( $msg, $plugin ) 5736 . COM_siteFooter( true ); 5737 5738 if( $http_status != 200 ) 5739 { 5740 header( "HTTP/1.1 $http_status $http_text" ); 5741 header( "Status: $http_status $http_text" ); 5742 } 5743 echo $display; 5744 exit; 5745 } 5746 5747 /** 5748 * Return full URL of a topic icon 5749 * 5750 * @param string $imageurl (relative) topic icon URL 5751 * @return string Full URL 5752 * 5753 */ 5754 function COM_getTopicImageUrl( $imageurl ) 5755 { 5756 global $_CONF, $_THEME_URL; 5757 5758 $iconurl = ''; 5759 5760 if( !empty( $imageurl )) 5761 { 5762 if( isset( $_THEME_URL )) 5763 { 5764 $iconurl = $_THEME_URL . $imageurl; 5765 } 5766 else 5767 { 5768 $stdImageLoc = true; 5769 if( !strstr( $_CONF['path_images'], $_CONF['path_html'] )) 5770 { 5771 $stdImageLoc = false; 5772 } 5773 5774 if( $stdImageLoc ) 5775 { 5776 $iconurl = $_CONF['site_url'] . $imageurl; 5777 } 5778 else 5779 { 5780 $t = explode( '/', $imageurl ); 5781 $topicicon = $t[count( $t ) - 1]; 5782 $iconurl = $_CONF['site_url'] 5783 . '/getimage.php?mode=topics&image=' . $topicicon; 5784 } 5785 } 5786 } 5787 5788 return $iconurl; 5789 } 5790 5791 /** 5792 * Try to determine the user's preferred language by looking at the 5793 * "Accept-Language" header sent by their browser (assuming they bothered 5794 * to select a preferred language there). 5795 * 5796 * @return string name of the language file to use or an empty string 5797 * 5798 * Bugs: Does not take the quantity ('q') parameter into account, but only 5799 * looks at the order of language codes. 5800 * 5801 * Sample header: Accept-Language: en-us,en;q=0.7,de-de;q=0.3 5802 * 5803 */ 5804 function COM_getLanguageFromBrowser() 5805 { 5806 global $_CONF; 5807 5808 $retval = ''; 5809 5810 if( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] )) 5811 { 5812 $accept = explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'] ); 5813 foreach( $accept as $l ) 5814 { 5815 $l = explode( ';', trim( $l )); 5816 $l = $l[0]; 5817 if( array_key_exists( $l, $_CONF['language_files'] )) 5818 { 5819 $retval = $_CONF['language_files'][$l]; 5820 break; 5821 } 5822 else 5823 { 5824 $l = explode( '-', $l ); 5825 $l = $l[0]; 5826 if( array_key_exists( $l, $_CONF['language_files'] )) 5827 { 5828 $retval = $_CONF['language_files'][$l]; 5829 break; 5830 } 5831 } 5832 } 5833 5834 } 5835 5836 return $retval; 5837 } 5838 5839 /** 5840 * Determine current language 5841 * 5842 * @return string name of the language file (minus the '.php' extension) 5843 * 5844 */ 5845 function COM_getLanguage() 5846 { 5847 global $_CONF, $_USER; 5848 5849 $langfile = ''; 5850 5851 if( !empty( $_USER['language'] )) 5852 { 5853 $langfile = $_USER['language']; 5854 } 5855 else if( !empty( $_COOKIE[$_CONF['cookie_language']] )) 5856 { 5857 $langfile = $_COOKIE[$_CONF['cookie_language']]; 5858 } 5859 else 5860 { 5861 $langfile = COM_getLanguageFromBrowser(); 5862 } 5863 5864 $langfile = preg_replace( '/[^a-z0-9\-_]/', '', $langfile ); 5865 if( !empty( $langfile )) 5866 { 5867 if( is_file( $_CONF['path_language'] . $langfile . '.php' )) 5868 { 5869 return $langfile; 5870 } 5871 } 5872 5873 // if all else fails, return the default language 5874 return $_CONF['language']; 5875 } 5876 5877 /** 5878 * Determine the ID to use for the current language 5879 * 5880 * The $_CONF['language_files'] array maps language IDs to language file names. 5881 * This function returns the language ID for a certain language file, to be 5882 * used in language-dependent URLs. 5883 * 5884 * @param string $language current language file name (optional) 5885 * @return string language ID, e.g 'en'; empty string on error 5886 * 5887 */ 5888 function COM_getLanguageId( $language = '' ) 5889 { 5890 global $_CONF; 5891 5892 if( empty( $language )) 5893 { 5894 $language = COM_getLanguage(); 5895 } 5896 5897 $lang_id = array_search( $language, $_CONF['language_files'] ); 5898 if( $lang_id === false) 5899 { 5900 // that looks like a misconfigured $_CONF['language_files'] array ... 5901 COM_errorLog( 'Language "' . $language . '" not found in $_CONF[\'language_files\'] array!' ); 5902 5903 $lang_id = ''; // not much we can do here ... 5904 } 5905 5906 return $lang_id; 5907 } 5908 5909 /** 5910 * Return SQL expression to request language-specific content 5911 * 5912 * Creates part of an SQL expression that can be used to request items in the 5913 * current language only. 5914 * 5915 * @param string $field name of the "id" field, e.g. 'sid' for stories 5916 * @param string $type part of the SQL expression, e.g. 'WHERE', 'AND' 5917 * @param string $table table name if ambiguous, e.g. in JOINs 5918 * @return string SQL expression string (may be empty) 5919 * 5920 */ 5921 function COM_getLangSQL( $field, $type = 'WHERE', $table = '' ) 5922 { 5923 global $_CONF; 5924 5925 $sql = ''; 5926 5927 if( isset( $_CONF['languages'] ) && isset( $_CONF['language_files'] )) 5928 { 5929 if( !empty( $table )) 5930 { 5931 $table .= '.'; 5932 } 5933 5934 $lang_id = COM_getLanguageId(); 5935 5936 if( !empty( $lang_id )) 5937 { 5938 $sql = ' ' . $type . " ({$table}$field LIKE '%_$lang_id')"; 5939 } 5940 } 5941 5942 return $sql; 5943 } 5944 5945 /** 5946 * Provides a drop-down menu (or simple link, if you only have two languages) 5947 * to switch languages. This can be used as a PHP block or called from within 5948 * your theme's header.thtml: <?php print phpblock_switch_language(); ?> 5949 * 5950 * @return string HTML for drop-down or link to switch languages 5951 * 5952 */ 5953 function phpblock_switch_language() 5954 { 5955 global $_CONF; 5956 5957 $retval = ''; 5958 5959 if( !isset( $_CONF['languages'] ) || !isset( $_CONF['language_files'] ) || 5960 ( count( $_CONF['languages'] ) != count( $_CONF['language_files'] ))) 5961 { 5962 return $retval; 5963 } 5964 5965 $lang = COM_getLanguage(); 5966 $langId = COM_getLanguageId( $lang ); 5967 5968 if( count( $_CONF['languages'] ) == 2 ) 5969 { 5970 foreach( $_CONF['languages'] as $key => $value ) 5971 { 5972 if( $key != $langId ) 5973 { 5974 $newLang = $value; 5975 $newLangId = $key; 5976 break; 5977 } 5978 } 5979 5980 $switchUrl = COM_buildUrl( $_CONF['site_url'] . '/switchlang.php?lang=' 5981 . $newLangId ); 5982 $retval .= '<a href="' . $switchUrl . '">' . $newLang . '</a>'; 5983 } 5984 else 5985 { 5986 $retval .= '<form name="change" action="'. $_CONF['site_url'] 5987 . '/switchlang.php" method="GET">' . LB; 5988 $retval .= '<input type="hidden" name="oldlang" value="' . $langId 5989 . '">' . LB; 5990 5991 $retval .= '<select onchange="change.submit()" name="lang">'; 5992 foreach( $_CONF['languages'] as $key => $value ) 5993 { 5994 if( $lang == $_CONF['language_files'][$key] ) 5995 { 5996 $selected = ' selected="selected"'; 5997 } 5998 else 5999 { 6000 $selected = ''; 6001 } 6002 $retval .= '<option value="' . $key . '"' . $selected . '>' 6003 . $value . '</option>' . LB; 6004 } 6005 $retval .= '</select>' . LB; 6006 $retval .= '</form>' . LB; 6007 } 6008 6009 return $retval; 6010 } 6011 6012 /** 6013 * Switch locale settings 6014 * 6015 * When multi-language support is enabled, allow overwriting the default locale 6016 * settings with language-specific settings (date format, etc.). So in addition 6017 * to $_CONF['date'] you can have a $_CONF['date_en'], $_CONF['date_de'], etc. 6018 * 6019 */ 6020 function COM_switchLocaleSettings() 6021 { 6022 global $_CONF; 6023 6024 if( isset( $_CONF['languages'] ) && isset( $_CONF['language_files'] )) 6025 { 6026 $overridables = array 6027 ( 6028 'locale', 6029 'date', 'daytime', 'shortdate', 'dateonly', 'timeonly', 6030 'week_start', 'hour_mode', 6031 'thousand_separator', 'decimal_separator' 6032 ); 6033 6034 $langId = COM_getLanguageId(); 6035 foreach( $overridables as $option ) 6036 { 6037 if( isset( $_CONF[$option . '_' . $langId] )) 6038 { 6039 $_CONF[$option] = $_CONF[$option . '_' . $langId]; 6040 } 6041 } 6042 } 6043 } 6044 6045 /** 6046 * Truncate a string 6047 * 6048 * Truncates a string to a max. length and optionally adds a filler string, 6049 * e.g. '...', to indicate the truncation. 6050 * This function is multi-byte string aware, based on a patch by Yusuke Sakata. 6051 * 6052 * @param string $text the text string to truncate 6053 * @param int $maxlen max. number of characters in the truncated string 6054 * @param string $filler optional filler string, e.g. '...' 6055 * @return string truncated string 6056 * 6057 * @note The truncated string may be shorter but will never be longer than 6058 * $maxlen characters, i.e. the $filler string is taken into account. 6059 * 6060 */ 6061 function COM_truncate( $text, $maxlen, $filler = '' ) 6062 { 6063 $newlen = $maxlen - MBYTE_strlen( $filler ); 6064 $len = MBYTE_strlen( $text ); 6065 if( $len > $maxlen ) 6066 { 6067 $text = MBYTE_substr( $text, 0, $newlen ) . $filler; 6068 } 6069 6070 return $text; 6071 } 6072 6073 /** 6074 * Handle errors. 6075 * 6076 * This function will handle all PHP errors thrown at it, without exposing 6077 * paths, and hopefully, providing much more information to Root Users than 6078 * the default white error page. 6079 * 6080 * This function will call out to CUSTOM_handleError if it exists, but, be 6081 * advised, only override this function with a very, very stable function. I'd 6082 * suggest one that outputs some static, basic HTML. 6083 * 6084 * The PHP feature that allows us to do so is documented here: 6085 * http://uk2.php.net/manual/en/function.set-error-handler.php 6086 * 6087 * @param int $errno Error Number. 6088 * @param string $errstr Error Message. 6089 * @param string $errfile The file the error was raised in. 6090 * @param int $errline The line of the file that the error was raised at. 6091 * @param array $errcontext An array that points to the active symbol table at the point the error occurred. 6092 */ 6093 function COM_handleError($errno, $errstr, $errfile='', $errline=0, $errcontext='') 6094 { 6095 global $_CONF, $_USER; 6096 6097 // Handle @ operator 6098 if( error_reporting() == 0 ) 6099 { 6100 return; 6101 } 6102 6103 /* If in PHP4, then respect error_reporting */ 6104 if( (PHP_VERSION < 5) && (($errno & error_reporting()) == 0) ) return; 6105 6106 /* 6107 * If we have a root user, then output detailed error message: 6108 */ 6109 if( ( is_array($_USER) && function_exists('SEC_inGroup') ) || $_CONF['rootdebug'] ) 6110 { 6111 if($_CONF['rootdebug'] || SEC_inGroup('Root')) 6112 { 6113 echo(" 6114 An error has occurred:<br/> 6115 $errno - $errstr @ $errfile line $errline<br/> 6116 <pre>"); 6117 ob_start(); 6118 var_dump($errcontext); 6119 $errcontext = htmlspecialchars(ob_get_contents()); 6120 ob_end_clean(); 6121 echo("$errcontext</pre> 6122 (This text is only displayed to users in the group 'Root') 6123 "); 6124 exit; 6125 } 6126 } 6127 6128 /* If there is a custom error handler, fail over to that, but only 6129 * if the error wasn't in lib-custom.php 6130 */ 6131 if( is_array($_CONF) && !(strstr($errfile, 'lib-custom.php'))) 6132 { 6133 if( array_key_exists('path_system', $_CONF) ) 6134 { 6135 require_once($_CONF['path_system'].'lib-custom.php'); 6136 if( function_exists('CUSTOM_handleError') ) 6137 { 6138 CUSTOM_handleError($errno, $errstr, $errfile, $errline, $errcontext); 6139 exit; 6140 } 6141 } 6142 } 6143 6144 /* Does the theme implement an error message html file? */ 6145 if(file_exists($_CONF['path_layout'].'errormessage.html')) 6146 { 6147 // NOTE: NOT A TEMPLATE! JUST HTML! 6148 include($_CONF['path_layout'].'errormessage.html'); 6149 } else { 6150 /* Otherwise, display simple error message */ 6151 echo(" 6152 <html> 6153 <head> 6154 <title>{$_CONF['site_name']} - An Error Occurred</title> 6155 </head> 6156 <body> 6157 <div style=\"width: 100%; text-align: center;\"> 6158 Unfortunately, an error has occurred rendering this page. Please try 6159 again later. 6160 </div> 6161 </body> 6162 </html> 6163 "); 6164 } 6165 6166 exit; 6167 } 6168 6169 // Now include all plugin functions 6170 foreach( $_PLUGINS as $pi_name ) 6171 { 6172 require_once( $_CONF['path'] . 'plugins/' . $pi_name . '/functions.inc' ); 6173 } 6174 6175 // Check and see if any plugins (or custom functions) 6176 // have scheduled tasks to perform 6177 if( $_CONF['cron_schedule_interval'] > 0 ) 6178 { 6179 if(( DB_getItem( $_TABLES['vars'], 'value', "name='last_scheduled_run'" ) 6180 + $_CONF['cron_schedule_interval'] ) <= time()) 6181 { 6182 DB_query( "UPDATE {$_TABLES['vars']} SET value=UNIX_TIMESTAMP() WHERE name='last_scheduled_run'" ); 6183 PLG_runScheduledTask(); 6184 } 6185 } 6186 6187 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Wed Nov 21 12:27:40 2007 | par Balluche grâce à PHPXref 0.7 |
|