| [ Index ] |
PHP Cross Reference of MantisBT |
[Summary view] [Print] [Text view]
1 <?php 2 # MantisBT - A PHP based bugtracking system 3 4 # MantisBT is free software: you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License as published by 6 # the Free Software Foundation, either version 2 of the License, or 7 # (at your option) any later version. 8 # 9 # MantisBT is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with MantisBT. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Configuration API 19 * 20 * @package CoreAPI 21 * @subpackage ConfigurationAPI 22 * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org 23 * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net 24 * @link http://www.mantisbt.org 25 * 26 * @uses authentication_api.php 27 * @uses constant_inc.php 28 * @uses database_api.php 29 * @uses error_api.php 30 * @uses helper_api.php 31 * @uses utility_api.php 32 */ 33 34 require_api( 'authentication_api.php' ); 35 require_api( 'constant_inc.php' ); 36 require_api( 'database_api.php' ); 37 require_api( 'error_api.php' ); 38 require_api( 'helper_api.php' ); 39 require_api( 'utility_api.php' ); 40 41 # cache for config variables 42 $g_cache_config = array(); 43 $g_cache_config_eval = array(); 44 $g_cache_config_access = array(); 45 $g_cache_bypass_lookup = array(); 46 $g_cache_filled = false; 47 $g_cache_can_set_in_database = ''; 48 49 # cache environment to speed up lookups 50 $g_cache_db_table_exists = false; 51 52 $g_cache_config_user = null; 53 $g_cache_config_project = null; 54 55 # ## Configuration API ### 56 # ------------------ 57 # Retrieves the value of a config option 58 # This function will return one of (in order of preference): 59 # 1. value from cache 60 # 2. value from database 61 # looks for specified config_id + current user + current project. 62 # if not found, config_id + current user + all_project 63 # if not found, config_id + default user + current project 64 # if not found, config_id + default user + all_project. 65 # 3.use GLOBAL[config_id] 66 function config_get( $p_option, $p_default = null, $p_user = null, $p_project = null ) { 67 global $g_cache_config, $g_cache_config_access, $g_cache_db_table_exists, $g_cache_filled; 68 global $g_cache_config_user, $g_cache_config_project, $g_project_override; 69 70 # @@ debug @@ echo "lu o=$p_option "; 71 # bypass table lookup for certain options 72 $t_bypass_lookup = !config_can_set_in_database( $p_option ); 73 74 # @@ debug @@ if ($t_bypass_lookup) { echo "bp=$p_option match=$t_match_pattern <br />"; } 75 76 if( !$t_bypass_lookup ) { 77 if( $g_project_override != null ) { 78 $p_project = $g_project_override; 79 } 80 # @@ debug @@ if ( ! db_is_connected() ) { echo "no db "; } 81 # @@ debug @@ echo "lu table=" . ( db_table_exists( $t_config_table ) ? "yes " : "no " ); 82 if( !$g_cache_db_table_exists ) { 83 $t_config_table = db_get_table( 'config' ); 84 $g_cache_db_table_exists = ( TRUE === db_is_connected() ) && db_table_exists( $t_config_table ); 85 } 86 87 if( $g_cache_db_table_exists ) { 88 89 # @@ debug @@ echo " lu db $p_option "; 90 # @@ debug @@ error_print_stack_trace(); 91 # prepare the user's list 92 $t_users = array(); 93 if( null === $p_user ) { 94 if( !isset( $g_cache_config_user ) ) { 95 $t_users[] = auth_is_user_authenticated() ? auth_get_current_user_id() : ALL_USERS; 96 if( !in_array( ALL_USERS, $t_users ) ) { 97 $t_users[] = ALL_USERS; 98 } 99 $g_cache_config_user = $t_users; 100 } else { 101 $t_users = $g_cache_config_user; 102 } 103 } else { 104 $t_users[] = $p_user; 105 if( !in_array( ALL_USERS, $t_users ) ) { 106 $t_users[] = ALL_USERS; 107 } 108 } 109 110 # prepare the projects list 111 $t_projects = array(); 112 if(( null === $p_project ) ) { 113 if( !isset( $g_cache_config_project ) ) { 114 $t_projects[] = auth_is_user_authenticated() ? helper_get_current_project() : ALL_PROJECTS; 115 if( !in_array( ALL_PROJECTS, $t_projects ) ) { 116 $t_projects[] = ALL_PROJECTS; 117 } 118 $g_cache_config_project = $t_projects; 119 } else { 120 $t_projects = $g_cache_config_project; 121 } 122 } else { 123 $t_projects[] = $p_project; 124 if( !in_array( ALL_PROJECTS, $t_projects ) ) { 125 $t_projects[] = ALL_PROJECTS; 126 } 127 } 128 129 # @@ debug @@ echo 'pr= '; var_dump($t_projects); 130 # @@ debug @@ echo 'u= '; var_dump($t_users); 131 132 if( !$g_cache_filled ) { 133 $t_config_table = db_get_table( 'config' ); 134 $query = "SELECT config_id, user_id, project_id, type, value, access_reqd FROM $t_config_table"; 135 $result = db_query_bound( $query ); 136 while( false <> ( $row = db_fetch_array( $result ) ) ) { 137 $t_config = $row['config_id']; 138 $t_user = $row['user_id']; 139 $t_project = $row['project_id']; 140 $g_cache_config[$t_config][$t_user][$t_project] = $row['type'] . ';' . $row['value']; 141 $g_cache_config_access[$t_config][$t_user][$t_project] = $row['access_reqd']; 142 } 143 $g_cache_filled = true; 144 } 145 146 if( isset( $g_cache_config[$p_option] ) ) { 147 $t_found = false; 148 reset( $t_users ); 149 while(( list(, $t_user ) = each( $t_users ) ) && !$t_found ) { 150 reset( $t_projects ); 151 while(( list(, $t_project ) = each( $t_projects ) ) && !$t_found ) { 152 if( isset( $g_cache_config[$p_option][$t_user][$t_project] ) ) { 153 $t_value = $g_cache_config[$p_option][$t_user][$t_project]; 154 $t_found = true; 155 156 # @@ debug @@ echo "clu found u=$t_user, p=$t_project, v=$t_value "; 157 } 158 } 159 } 160 161 if( $t_found ) { 162 list( $t_type, $t_raw_value ) = explode( ';', $t_value, 2 ); 163 164 switch( $t_type ) { 165 case CONFIG_TYPE_FLOAT: 166 $t_value = (float) $t_raw_value; 167 break; 168 case CONFIG_TYPE_INT: 169 $t_value = (int) $t_raw_value; 170 break; 171 case CONFIG_TYPE_COMPLEX: 172 $t_value = unserialize( $t_raw_value ); 173 break; 174 case CONFIG_TYPE_STRING: 175 default: 176 $t_value = config_eval( $t_raw_value ); 177 } 178 return $t_value; 179 } 180 } 181 } 182 } 183 return config_get_global( $p_option, $p_default ); 184 } 185 186 # ---------------------- 187 # force config variable from a global to avoid recursion 188 function config_get_global( $p_option, $p_default = null ) { 189 global $g_cache_config_eval; 190 if( isset( $GLOBALS['g_' . $p_option] ) ) { 191 if( !isset( $g_cache_config_eval['g_' . $p_option] ) ) { 192 $t_value = config_eval( $GLOBALS['g_' . $p_option] ); 193 $g_cache_config_eval['g_' . $p_option] = $t_value; 194 } else { 195 $t_value = $g_cache_config_eval['g_' . $p_option]; 196 } 197 return $t_value; 198 } else { 199 # unless we were allowing for the option not to exist by passing 200 # a default, trigger a WARNING 201 if( null === $p_default ) { 202 error_parameters( $p_option ); 203 trigger_error( ERROR_CONFIG_OPT_NOT_FOUND, WARNING ); 204 } 205 return $p_default; 206 } 207 } 208 209 # ------------------ 210 # Retrieves the access level needed to change a config value 211 function config_get_access( $p_option, $p_user = null, $p_project = null ) { 212 global $g_cache_config, $g_cache_config_access, $g_cache_filled; 213 214 # @@ debug @@ echo "lu o=$p_option "; 215 216 if( !$g_cache_filled ) { 217 $t = config_get( $p_option, -1, $p_user, $p_project ); 218 } 219 220 # prepare the user's list 221 $t_users = array(); 222 if(( null === $p_user ) && ( auth_is_user_authenticated() ) ) { 223 $t_users[] = auth_get_current_user_id(); 224 } 225 else if( !in_array( $p_user, $t_users ) ) { 226 $t_users[] = $p_user; 227 } 228 $t_users[] = ALL_USERS; 229 230 # prepare the projects list 231 $t_projects = array(); 232 if(( null === $p_project ) && ( auth_is_user_authenticated() ) ) { 233 $t_selected_project = helper_get_current_project(); 234 if( ALL_PROJECTS <> $t_selected_project ) { 235 $t_projects[] = $t_selected_project; 236 } 237 } 238 else if( !in_array( $p_project, $t_projects ) ) { 239 $t_projects[] = $p_project; 240 } 241 242 # @@ debug @@ echo 'pr= '; var_dump($t_projects); 243 # @@ debug @@ echo 'u= '; var_dump($t_users); 244 245 $t_found = false; 246 if( isset( $g_cache_config[$p_option] ) ) { 247 reset( $t_users ); 248 while(( list(, $t_user ) = each( $t_users ) ) && !$t_found ) { 249 reset( $t_projects ); 250 while(( list(, $t_project ) = each( $t_projects ) ) && !$t_found ) { 251 if( isset( $g_cache_config[$p_option][$t_user][$t_project] ) ) { 252 $t_access = $g_cache_config_access[$p_option][$t_user][$t_project]; 253 $t_found = true; 254 255 # @@ debug @@ echo "clua found u=$t_user, p=$t_project, a=$t_access "; 256 } 257 } 258 } 259 } 260 261 return $t_found ? $t_access : config_get_global( 'admin_site_threshold' ); 262 } 263 264 # ------------------ 265 # Returns true if the specified config option exists (ie. a 266 # value or default can be found), false otherwise 267 function config_is_set( $p_option, $p_user = null, $p_project = null ) { 268 global $g_cache_config, $g_cache_filled; 269 270 if( !$g_cache_filled ) { 271 $t = config_get( $p_option, -1, $p_user, $p_project ); 272 } 273 274 # prepare the user's list 275 $t_users = array( 276 ALL_USERS, 277 ); 278 if(( null === $p_user ) && ( auth_is_user_authenticated() ) ) { 279 $t_users[] = auth_get_current_user_id(); 280 } 281 else if( !in_array( $p_user, $t_users ) ) { 282 $t_users[] = $p_user; 283 } 284 $t_users[] = ALL_USERS; 285 286 # prepare the projects list 287 $t_projects = array( 288 ALL_PROJECTS, 289 ); 290 if(( null === $p_project ) && ( auth_is_user_authenticated() ) ) { 291 $t_selected_project = helper_get_current_project(); 292 if( ALL_PROJECTS <> $t_selected_project ) { 293 $t_projects[] = $t_selected_project; 294 } 295 } 296 else if( !in_array( $p_project, $t_projects ) ) { 297 $t_projects[] = $p_project; 298 } 299 300 $t_found = false; 301 reset( $t_users ); 302 while(( list(, $t_user ) = each( $t_users ) ) && !$t_found ) { 303 reset( $t_projects ); 304 while(( list(, $t_project ) = each( $t_projects ) ) && !$t_found ) { 305 if( isset( $g_cache_config[$p_option][$t_user][$t_project] ) ) { 306 $t_found = true; 307 } 308 } 309 } 310 311 if( $t_found ) { 312 return true; 313 } 314 315 return isset( $GLOBALS['g_' . $p_option] ); 316 } 317 318 # ------------------ 319 # Sets the value of the given config option to the given value 320 # If the config option does not exist, an ERROR is triggered 321 function config_set( $p_option, $p_value, $p_user = NO_USER, $p_project = ALL_PROJECTS, $p_access = DEFAULT_ACCESS_LEVEL ) { 322 if( $p_access == DEFAULT_ACCESS_LEVEL ) { 323 $p_access = config_get_global( 'admin_site_threshold' ); 324 } 325 if( is_array( $p_value ) || is_object( $p_value ) ) { 326 $t_type = CONFIG_TYPE_COMPLEX; 327 $c_value = serialize( $p_value ); 328 } else if( is_float( $p_value ) ) { 329 $t_type = CONFIG_TYPE_FLOAT; 330 $c_value = (float) $p_value; 331 } else if( is_int( $p_value ) || is_numeric( $p_value ) ) { 332 $t_type = CONFIG_TYPE_INT; 333 $c_value = db_prepare_int( $p_value ); 334 } else { 335 $t_type = CONFIG_TYPE_STRING; 336 $c_value = $p_value; 337 } 338 339 if( config_can_set_in_database( $p_option ) ) { 340 $c_option = $p_option; 341 $c_user = db_prepare_int( $p_user ); 342 $c_project = db_prepare_int( $p_project ); 343 $c_access = db_prepare_int( $p_access ); 344 345 $t_config_table = db_get_table( 'config' ); 346 $query = "SELECT COUNT(*) from $t_config_table 347 WHERE config_id = " . db_param() . " AND 348 project_id = " . db_param() . " AND 349 user_id = " . db_param(); 350 $result = db_query_bound( $query, Array( $c_option, $c_project, $c_user ) ); 351 352 $t_params = Array(); 353 if( 0 < db_result( $result ) ) { 354 $t_set_query = "UPDATE $t_config_table 355 SET value=" . db_param() . ", type=" . db_param() . ", access_reqd=" . db_param() . " 356 WHERE config_id = " . db_param() . " AND 357 project_id = " . db_param() . " AND 358 user_id = " . db_param(); 359 $t_params = Array( 360 $c_value, 361 $t_type, 362 $c_access, 363 $c_option, 364 $c_project, 365 $c_user, 366 ); 367 } else { 368 $t_set_query = "INSERT INTO $t_config_table 369 ( value, type, access_reqd, config_id, project_id, user_id ) 370 VALUES 371 (" . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ', ' . db_param() . ',' . db_param() . ' )'; 372 $t_params = Array( 373 $c_value, 374 $t_type, 375 $c_access, 376 $c_option, 377 $c_project, 378 $c_user, 379 ); 380 } 381 382 $result = db_query_bound( $t_set_query, $t_params ); 383 } 384 385 config_set_cache( $p_option, $c_value, $t_type, $p_user, $p_project, $p_access ); 386 387 return true; 388 } 389 390 # ------------------ 391 # Sets the value of the given config option in the global namespace. 392 # Does *not* persist the value between sessions. If override set to 393 # false, then the value will only be set if not already existent. 394 function config_set_global( $p_option, $p_value, $p_override = true ) { 395 global $g_cache_config_eval; 396 397 if( $p_override || !isset( $GLOBALS['g_' . $p_option] ) ) { 398 $GLOBALS['g_' . $p_option] = $p_value; 399 unset( $g_cache_config_eval['g_' . $p_option] ); 400 } 401 402 return true; 403 } 404 405 # ------------------ 406 # Sets the value of the given config option to the given value 407 # If the config option does not exist, an ERROR is triggered 408 function config_set_cache( $p_option, $p_value, $p_type, $p_user = NO_USER, $p_project = ALL_PROJECTS, $p_access = DEFAULT_ACCESS_LEVEL ) { 409 global $g_cache_config, $g_cache_config_access; 410 411 if( $p_access == DEFAULT_ACCESS_LEVEL ) { 412 $p_access = config_get_global( 'admin_site_threshold' ); 413 } 414 415 $g_cache_config[$p_option][$p_user][$p_project] = $p_type . ';' . $p_value; 416 $g_cache_config_access[$p_option][$p_user][$p_project] = $p_access; 417 418 return true; 419 } 420 421 # ------------------ 422 # Checks if the specific configuration option can be set in the database, otherwise it can only be set 423 # in the configuration file (config_inc.php / config_defaults_inc.php). 424 function config_can_set_in_database( $p_option ) { 425 global $g_cache_can_set_in_database, $g_cache_bypass_lookup; 426 427 if( isset( $g_cache_bypass_lookup[$p_option] ) ) { 428 return !$g_cache_bypass_lookup[$p_option]; 429 } 430 431 # bypass table lookup for certain options 432 if( $g_cache_can_set_in_database == '' ) { 433 $g_cache_can_set_in_database = '/' . implode( '|', config_get_global( 'global_settings' ) ) . '/'; 434 } 435 $t_bypass_lookup = ( 0 < preg_match( $g_cache_can_set_in_database, $p_option ) ); 436 437 $g_cache_bypass_lookup[$p_option] = $t_bypass_lookup; 438 439 return !$t_bypass_lookup; 440 } 441 442 # ------------------ 443 # Checks if the specific configuration option can be deleted from the database. 444 function config_can_delete( $p_option ) { 445 return( utf8_strtolower( $p_option ) != 'database_version' ); 446 } 447 448 # ------------------ 449 # delete the config entry 450 function config_delete( $p_option, $p_user = ALL_USERS, $p_project = ALL_PROJECTS ) { 451 global $g_cache_config, $g_cache_config_access; 452 453 # bypass table lookup for certain options 454 $t_bypass_lookup = !config_can_set_in_database( $p_option ); 455 456 # @@ debug @@ if ($t_bypass_lookup) { echo "bp=$p_option match=$t_match_pattern <br />"; } 457 # @@ debug @@ if ( ! db_is_connected() ) { echo "no db"; } 458 459 if(( !$t_bypass_lookup ) && ( TRUE === db_is_connected() ) && ( db_table_exists( db_get_table( 'config' ) ) ) ) { 460 if( !config_can_delete( $p_option ) ) { 461 return; 462 } 463 464 $t_config_table = db_get_table( 'config' ); 465 466 # @@ debug @@ echo "lu table=" . ( db_table_exists( $t_config_table ) ? "yes" : "no" ); 467 # @@ debug @@ error_print_stack_trace(); 468 469 $c_user = db_prepare_int( $p_user ); 470 $c_project = db_prepare_int( $p_project ); 471 $query = "DELETE FROM $t_config_table 472 WHERE config_id = " . db_param() . " AND 473 project_id=" . db_param() . " AND 474 user_id=" . db_param(); 475 476 $result = @db_query_bound( $query, Array( $p_option, $c_project, $c_user ) ); 477 } 478 479 config_flush_cache( $p_option, $p_user, $p_project ); 480 } 481 482 /** 483 * Delete the specified option for the specified user.across all projects. 484 * @param $p_option - The configuration option to be deleted. 485 * @param $p_user_id - The user id 486 */ 487 function config_delete_for_user( $p_option, $p_user_id ) { 488 if( !config_can_delete( $p_option ) ) { 489 return; 490 } 491 492 $t_config_table = db_get_table( 'config' ); 493 $c_user_id = db_prepare_int( $p_user_id ); 494 495 # Delete the corresponding bugnote texts 496 $query = "DELETE FROM $t_config_table 497 WHERE config_id=" . db_param() . " AND user_id=" . db_param(); 498 db_query_bound( $query, array( $p_option, $c_user_id ) ); 499 } 500 501 # ------------------ 502 # delete the config entry 503 function config_delete_project( $p_project = ALL_PROJECTS ) { 504 global $g_cache_config, $g_cache_config_access; 505 $t_config_table = db_get_table( 'config' ); 506 $c_project = db_prepare_int( $p_project ); 507 $query = "DELETE FROM $t_config_table 508 WHERE project_id=" . db_param(); 509 510 $result = @db_query_bound( $query, Array( $c_project ) ); 511 512 # flush cache here in case some of the deleted configs are in use. 513 config_flush_cache(); 514 } 515 516 # ------------------ 517 # delete the config entry from the cache 518 # @@@ to be used sparingly 519 function config_flush_cache( $p_option = '', $p_user = ALL_USERS, $p_project = ALL_PROJECTS ) { 520 global $g_cache_config, $g_cache_config_access, $g_cache_filled; 521 522 if( '' !== $p_option ) { 523 unset( $GLOBALS['g_cache_config'][$p_option][$p_user][$p_project] ); 524 unset( $GLOBALS['g_cache_config_access'][$p_option][$p_user][$p_project] ); 525 } else { 526 unset( $GLOBALS['g_cache_config'] ); 527 unset( $GLOBALS['g_cache_config_access'] ); 528 $g_cache_filled = false; 529 } 530 } 531 532 # ------------------ 533 # Checks if an obsolete configuration variable is still in use. If so, an error 534 # will be generated and the script will exit. This is called from admin_check.php. 535 function config_obsolete( $p_var, $p_replace ) { 536 537 # @@@ we could trigger a WARNING here, once we have errors that can 538 # have extra data plugged into them (we need to give the old and 539 # new config option names in the warning text) 540 541 if( config_is_set( $p_var ) ) { 542 $t_description = '<p><strong>Warning:</strong> The configuration option <tt>$g_' . $p_var . '</tt> is now obsolete</p>'; 543 if( is_array( $p_replace ) ) { 544 $t_info = 'please see the following options: <ul>'; 545 foreach( $p_replace as $t_option ) { 546 $t_info .= '<li>$g_' . $t_option . '</li>'; 547 } 548 $t_info .= '</ul>'; 549 } 550 else if( !is_blank( $p_replace ) ) { 551 $t_info = 'please use <tt>$g_' . $p_replace . '</tt> instead.'; 552 } else { 553 $t_info = ''; 554 } 555 556 print_test_warn_row( $t_description, false, $t_info ); 557 } 558 } 559 560 # ------------------ 561 # check for recursion in defining config variables 562 # If there is a %text% in the returned value, re-evaluate the "text" part and replace 563 # the string 564 function config_eval( $p_value ) { 565 $t_value = $p_value; 566 if( !empty( $t_value ) && is_string( $t_value ) && !is_numeric( $t_value ) ) { 567 if( 0 < preg_match_all( '/(?:^|[^\\\\])(%([^%]+)%)/U', $t_value, $t_matches ) ) { 568 $t_count = count( $t_matches[0] ); 569 for( $i = 0;$i < $t_count;$i++ ) { 570 571 # $t_matches[0][$i] is the matched string including the delimiters 572 # $t_matches[1][$i] is the target parameter string 573 $t_repl = config_get( $t_matches[2][$i] ); 574 $t_value = str_replace( $t_matches[1][$i], $t_repl, $t_value ); 575 } 576 } 577 $t_value = str_replace( '\\%', '%', $t_value ); 578 } 579 return $t_value; 580 } 581 582 # list of configuration variable which may expose webserver details and shouldn't be 583 # exposed to users or webservices 584 function config_is_private( $p_config_var ) { 585 switch( $p_config_var ) { 586 case 'hostname': 587 case 'db_username': 588 case 'db_password': 589 case 'database_name': 590 case 'db_schema': 591 case 'db_type': 592 case 'master_crypto_salt': 593 case 'smtp_host': 594 case 'smtp_username': 595 case 'smtp_password': 596 case 'smtp_connection_mode': 597 case 'smtp_port': 598 case 'email_send_using_cronjob': 599 case 'absolute_path': 600 case 'core_path': 601 case 'class_path': 602 case 'library_path': 603 case 'language_path': 604 case 'session_save_path': 605 case 'session_handler': 606 case 'session_validation': 607 case 'global_settings': 608 case 'system_font_folder': 609 case 'phpMailer_method': 610 case 'default_avatar': 611 case 'file_upload_ftp_server': 612 case 'file_upload_ftp_user': 613 case 'file_upload_ftp_pass': 614 case 'attachments_file_permissions': 615 case 'file_upload_method': 616 case 'absolute_path_default_upload_folder': 617 case 'ldap_server': 618 case 'plugin_path': 619 case 'ldap_root_dn': 620 case 'ldap_organization': 621 case 'ldap_uid_field': 622 case 'ldap_bind_dn': 623 case 'ldap_bind_passwd': 624 case 'use_ldap_email': 625 case 'ldap_protocol_version': 626 case 'login_method': 627 case 'cookie_path': 628 case 'cookie_domain': 629 case 'bottom_include_page': 630 case 'top_include_page': 631 case 'css_include_file': 632 case 'css_rtl_include_file': 633 case 'meta_include_file': 634 case 'log_level': 635 case 'log_destination': 636 case 'dot_tool': 637 case 'neato_tool': 638 case 'twitter_username': 639 case 'twitter_password': 640 return true; 641 } 642 643 return false; 644 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Jul 28 15:48:31 2011 | Cross-referenced by PHPXref 0.7 |