[ Index ] |
PHP Cross Reference of MyBB |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * MyBB 1.6 4 * Copyright 2010 MyBB Group, All Rights Reserved 5 * 6 * Website: http://mybb.com 7 * License: http://mybb.com/about/license 8 * 9 * $Id$ 10 */ 11 12 // Disallow direct access to this file for security reasons 13 if(!defined("IN_MYBB")) 14 { 15 die("Direct initialization of this file is not allowed.<br /><br />Please make sure IN_MYBB is defined."); 16 } 17 18 // Neat trick for caching our custom template(s) 19 // Basically, when we include this from class_plugins.php we can do stuff in init.php, which is before we cache our templates 20 // So we won't need an extra call to cache it. 21 22 if(my_strpos($_SERVER['PHP_SELF'], 'showthread.php')) 23 { 24 global $templatelist; 25 if(isset($templatelist)) 26 { 27 $templatelist .= ','; 28 } 29 $templatelist .= 'akismet_postbit_spam'; 30 } 31 32 $plugins->add_hook("datahandler_post_insert_thread", "akismet_verify"); 33 $plugins->add_hook("datahandler_post_insert_thread_post", "akismet_verify"); 34 $plugins->add_hook("datahandler_post_insert_post", "akismet_verify"); 35 $plugins->add_hook("datahandler_post_validate_post", "akismet_fake_draft"); 36 $plugins->add_hook("datahandler_post_validate_thread", "akismet_fake_draft"); 37 $plugins->add_hook("newreply_do_newreply_end", "akismet_redirect_thread"); 38 $plugins->add_hook("newthread_do_newthread_end", "akismet_redirect_forum"); 39 $plugins->add_hook("moderation_start", "akismet_moderation_start"); 40 $plugins->add_hook("postbit", "akismet_postbit"); 41 42 $plugins->add_hook("admin_forum_menu", "akismet_admin_nav"); 43 $plugins->add_hook("admin_forum_permissions", "akismet_admin_permissions"); 44 $plugins->add_hook("admin_load", "akismet_admin"); 45 $plugins->add_hook("admin_forum_action_handler", "akismet_action_handler"); 46 $plugins->add_hook("admin_config_plugins_activate_commit", "akismet_key"); 47 48 function akismet_info() 49 { 50 global $lang; 51 52 $lang->load("forum_akismet", false, true); 53 54 return array( 55 "name" => $lang->akismet, 56 "description" => $lang->akismet_desc, 57 "website" => "http://mybb.com", 58 "author" => "MyBB Group", 59 "authorsite" => "http://mybb.com", 60 "version" => "1.2.2", 61 "guid" => "e57a80dbe7ff85083596a1a3b7da3ce7", 62 "compatibility" => "16*", 63 ); 64 } 65 66 /** 67 * ADDITIONAL PLUGIN INSTALL/UNINSTALL ROUTINES 68 * 69 * _install(): 70 * Called whenever a plugin is installed by clicking the "Install" button in the plugin manager. 71 * If no install routine exists, the install button is not shown and it assumed any work will be 72 * performed in the _activate() routine. 73 * 74 * function hello_install() 75 * { 76 * } 77 * 78 * _is_installed(): 79 * Called on the plugin management page to establish if a plugin is already installed or not. 80 * This should return TRUE if the plugin is installed (by checking tables, fields etc) or FALSE 81 * if the plugin is not installed. 82 * 83 * function hello_is_installed() 84 * { 85 * global $db; 86 * if($db->table_exists("hello_world")) 87 * { 88 * return true; 89 * } 90 * return false; 91 * } 92 * 93 * _uninstall(): 94 * Called whenever a plugin is to be uninstalled. This should remove ALL traces of the plugin 95 * from the installation (tables etc). If it does not exist, uninstall button is not shown. 96 * 97 * function hello_uninstall() 98 * { 99 * } 100 * 101 * _activate(): 102 * Called whenever a plugin is activated via the Admin CP. This should essentially make a plugin 103 * "visible" by adding templates/template changes, language changes etc. 104 * 105 * function hello_activate() 106 * { 107 * } 108 * 109 * _deactivate(): 110 * Called whenever a plugin is deactivated. This should essentially "hide" the plugin from view 111 * by removing templates/template changes etc. It should not, however, remove any information 112 * such as tables, fields etc - that should be handled by an _uninstall routine. When a plugin is 113 * uninstalled, this routine will also be called before _uninstall() if the plugin is active. 114 * 115 * function hello_deactivate() 116 * { 117 * } 118 */ 119 120 function akismet_install() 121 { 122 global $db, $mybb, $lang; 123 124 if($db->field_exists('akismetstopped', "users")) 125 { 126 $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP akismetstopped"); 127 } 128 129 // DELETE ALL SETTINGS TO AVOID DUPLICATES 130 $db->write_query("DELETE FROM ".TABLE_PREFIX."settings WHERE name IN( 131 'akismetswitch', 132 'akismetnumtillban', 133 'akismetfidsignore', 134 'akismetuidsignore', 135 'akismetuserstoignore' 136 )"); 137 $db->delete_query("settinggroups", "name = 'akismet'"); 138 $db->delete_query("datacache", "title = 'akismet_update_check'"); 139 140 $query = $db->simple_select("settinggroups", "COUNT(*) as rows"); 141 $rows = $db->fetch_field($query, "rows"); 142 143 $insertarray = array( 144 'name' => 'akismet', 145 'title' => 'Akismet', 146 'description' => 'Options on how to configure and personalize Akismet', 147 'disporder' => $rows+1, 148 'isdefault' => 0 149 ); 150 $group['gid'] = $db->insert_query("settinggroups", $insertarray); 151 $mybb->akismet_insert_gid = $group['gid']; 152 153 $insertarray = array( 154 'name' => 'akismetswitch', 155 'title' => 'Akismet Main Switch', 156 'description' => 'Turns on or off Akismet.', 157 'optionscode' => 'onoff', 158 'value' => 1, 159 'disporder' => 0, 160 'gid' => $group['gid'] 161 ); 162 $db->insert_query("settings", $insertarray); 163 164 $insertarray = array( 165 'name' => 'akismetapikey', 166 'title' => 'API Key to use for Akismet', 167 'description' => $db->escape_string('The API Key used to connect to Akismet. Please check here for more details: <a href="http://wordpress.com/api-keys/" target="_blank">http://wordpress.com/api-keys/</a>'), 168 'optionscode' => 'text', 169 'value' => '', 170 'disporder' => 1, 171 'gid' => $group['gid'] 172 ); 173 $db->insert_query("settings", $insertarray); 174 175 $insertarray = array( 176 'name' => 'akismetnumtillban', 177 'title' => 'Spam messages until ban', 178 'description' => 'The number of spam messages detected by Akismet until the user gets banned (set to 0 to disable).', 179 'optionscode' => 'text', 180 'value' => '3', 181 'disporder' => 2, 182 'gid' => $group['gid'] 183 ); 184 $db->insert_query("settings", $insertarray); 185 186 $insertarray = array( 187 'name' => 'akismetfidsignore', 188 'title' => 'Forums to Ignore', 189 'description' => 'Forums, separated by a comma, to ignore. Use the forum id, <strong>not the name</strong>.', 190 'optionscode' => 'text', 191 'value' => '', 192 'disporder' => 3, 193 'gid' => $group['gid'] 194 ); 195 $db->insert_query("settings", $insertarray); 196 197 $insertarray = array( 198 'name' => 'akismetuidsignore', 199 'title' => 'Usergroups to Ignore', 200 'description' => 'Usergroups, separated by a comma, to ignore. Use the usergroup id, <strong>not the name</strong>.', 201 'optionscode' => 'text', 202 'value' => '6,4,3', 203 'disporder' => 4, 204 'gid' => $group['gid'] 205 ); 206 $db->insert_query("settings", $insertarray); 207 208 $insertarray = array( 209 'name' => 'akismetuserstoignore', 210 'title' => 'Users to Ignore', 211 'description' => 'Users, separated by a comma, to ignore. Use the user id, <strong>not the name</strong>.', 212 'optionscode' => 'text', 213 'value' => '', 214 'disporder' => 6, 215 'gid' => $group['gid'] 216 ); 217 $db->insert_query("settings", $insertarray); 218 219 $db->write_query("ALTER TABLE ".TABLE_PREFIX."users ADD akismetstopped int NOT NULL default 0"); 220 221 rebuild_settings(); 222 } 223 224 function akismet_is_installed() 225 { 226 global $db; 227 228 if($db->field_exists('akismetstopped', "users")) 229 { 230 return true; 231 } 232 233 return false; 234 } 235 236 function akismet_activate() 237 { 238 global $db, $mybb; 239 240 include MYBB_ROOT."/inc/adminfunctions_templates.php"; 241 242 find_replace_templatesets("postbit", "#".preg_quote('{$post[\'button_spam\']}')."#i", '', 0); 243 find_replace_templatesets("postbit_classic", "#".preg_quote('{$post[\'button_spam\']}')."#i", '', 0); 244 245 $db->delete_query("templates", "title = 'akismet_postbit_spam'"); 246 247 find_replace_templatesets("postbit", "#".preg_quote('{$post[\'button_edit\']}')."#i", '{$post[\'button_spam\']}{$post[\'button_edit\']}'); 248 find_replace_templatesets("postbit_classic", "#".preg_quote('{$post[\'button_edit\']}')."#i", '{$post[\'button_spam\']}{$post[\'button_edit\']}'); 249 250 $insert_array = array( 251 'title' => 'akismet_postbit_spam', 252 'template' => $db->escape_string('<a href="{$mybb->settings[\'bburl\']}/moderation.php?action=mark_as_spam&pid={$post[\'pid\']}&fid={$post[\'fid\']}"><img src="{$theme[\'imglangdir\']}/postbit_spam.gif" alt="{$lang->spam}" /></a>'), 253 'sid' => '-1', 254 'version' => '', 255 'dateline' => TIME_NOW 256 ); 257 258 $db->insert_query("templates", $insert_array); 259 260 change_admin_permission('forum', 'akismet'); 261 } 262 263 function akismet_deactivate() 264 { 265 global $db, $mybb; 266 267 include MYBB_ROOT."/inc/adminfunctions_templates.php"; 268 269 find_replace_templatesets("postbit", "#".preg_quote('{$post[\'button_spam\']}')."#i", '', 0); 270 find_replace_templatesets("postbit_classic", "#".preg_quote('{$post[\'button_spam\']}')."#i", '', 0); 271 272 $db->delete_query("templates", "title = 'akismet_postbit_spam'"); 273 274 change_admin_permission('forum', 'akismet', -1); 275 } 276 277 function akismet_uninstall() 278 { 279 global $db; 280 281 if($db->field_exists('akismetstopped', "users")) 282 { 283 $db->write_query("ALTER TABLE ".TABLE_PREFIX."users DROP akismetstopped"); 284 } 285 286 // DELETE ALL SETTINGS TO AVOID DUPLICATES 287 $db->write_query("DELETE FROM ".TABLE_PREFIX."settings WHERE name IN( 288 'akismetswitch', 289 'akismetapikey', 290 'akismetnumtillban', 291 'akismetfidsignore', 292 'akismetuidsignore', 293 'akismetuserstoignore' 294 )"); 295 $db->delete_query("settinggroups", "name = 'akismet'"); 296 $db->delete_query("datacache", "title = 'akismet_update_check'"); 297 rebuild_settings(); 298 } 299 300 function akismet_key() 301 { 302 global $installed, $mybb; 303 304 if($installed == false && $mybb->input['plugin'] == "akismet") 305 { 306 global $message; 307 308 flash_message($message, 'success'); 309 admin_redirect("index.php?module=config-settings&action=change&gid=".intval($mybb->akismet_insert_gid)."#row_setting_akismetapikey"); 310 } 311 } 312 313 314 function akismet_show_confirm_page() 315 { 316 global $mybb, $lang, $theme, $pid, $fid, $db, $headerinclude, $header, $footer; 317 318 $pid = intval($pid); 319 $fid = intval($fid); 320 321 $query = $db->simple_select("posts", "subject", "pid='{$pid}'", 1); 322 $post = $db->fetch_array($query); 323 $post['subject'] = htmlspecialchars_uni($post['subject']); 324 325 if(!$post) 326 { 327 error("Invalid Post ID."); 328 } 329 330 output_page("<html> 331 <head> 332 <title>{$mybb->settings['bbname']} - {$lang->mark_as_spam}</title> 333 {$headerinclude} 334 </head> 335 <body> 336 {$header} 337 <form action=\"moderation.php\" method=\"post\"> 338 <input type=\"hidden\" name=\"my_post_key\" value=\"{$mybb->post_code}\" /> 339 <table border=\"0\" cellspacing=\"{$theme['borderwidth']}\" cellpadding=\"{$theme['tablespace']}\" class=\"tborder\"> 340 <tr> 341 <td class=\"thead\" colspan=\"2\"><strong>{$post['subject']} - {$lang->mark_as_spam}</strong></td> 342 </tr> 343 <tr> 344 <td class=\"trow1\" colspan=\"2\" align=\"center\">{$lang->confirm_mark_as_spam}</td> 345 </tr> 346 {$loginbox} 347 </table> 348 <br /> 349 <div align=\"center\"><input type=\"submit\" class=\"button\" name=\"submit\" value=\"{$lang->mark_as_spam}\" /></div> 350 <input type=\"hidden\" name=\"action\" value=\"mark_as_spam\" /> 351 <input type=\"hidden\" name=\"pid\" value=\"{$pid}\" /> 352 <input type=\"hidden\" name=\"fid\" value=\"{$fid}\" /> 353 </form> 354 {$footer} 355 </body> 356 </html>"); 357 exit; 358 } 359 360 function akismet_moderation_start() 361 { 362 global $mybb, $db, $akismet, $lang, $cache, $fid, $pid; 363 364 if(!$mybb->settings['akismetswitch'] || $mybb->input['action'] != 'mark_as_spam') 365 { 366 return; 367 } 368 369 $lang->load("akismet", false, true); 370 371 if(!$mybb->input['pid']) 372 { 373 error("No Post ID specified."); 374 } 375 376 $pid = intval($mybb->input['pid']); 377 378 if(!$mybb->input['fid']) 379 { 380 error("No Forum ID specified."); 381 } 382 383 $fid = intval($mybb->input['fid']); 384 385 if(!is_moderator($fid)) 386 { 387 error("No Permissions to do this action."); 388 } 389 390 $query = $db->query(" 391 SELECT p.uid, p.username, u.email, u.website, u.akismetstopped, p.message, p.ipaddress, p.tid, p.replyto, p.fid, f.usepostcounts 392 FROM ".TABLE_PREFIX."posts p 393 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) 394 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) 395 WHERE p.pid = '{$pid}' 396 "); 397 $post = $db->fetch_array($query); 398 399 if(!$post) 400 { 401 error("Invalid Post ID."); 402 } 403 404 if(!$mybb->input['my_post_key'] || $mybb->request_method != "post") 405 { 406 akismet_show_confirm_page(); 407 } 408 409 verify_post_check($mybb->input['my_post_key']); 410 411 $akismet_array = array( 412 'type' => 'post', 413 'username' => $post['username'], 414 'email' => $post['email'], 415 'website' => $post['website'], 416 'message' => $post['message'], 417 'user_ip' => $post['ipaddress'] 418 ); 419 420 if($post['replyto'] == 0) 421 { 422 $db->update_query("threads", array('visible' => '-4'), "tid = '{$post['tid']}'"); 423 $db->update_query("posts", array('visible' => '-4'), "tid = '{$post['tid']}'"); 424 $snippit = "thread"; 425 } 426 else 427 { 428 $db->update_query("posts", array('visible' => '-4'), "pid = '{$pid}'"); 429 $snippit = "post"; 430 } 431 432 if(!$akismet) 433 { 434 $akismet = new Akismet($mybb->settings['bburl'], $mybb->settings['akismetapikey'], $akismet_array); 435 } 436 437 $akismet->submit_spam(); 438 439 $numakismetthread = $numakismetpost = 0; 440 441 if($snippit == "thread") 442 { 443 $query = $db->query(" 444 SELECT p.uid, u.usergroup 445 FROM ".TABLE_PREFIX."posts p 446 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) 447 WHERE p.tid = '{$post['tid']}' 448 "); 449 while($post2 = $db->fetch_array($query)) 450 { 451 ++$numakismetpost; 452 453 if($post['usepostcounts'] != 0) 454 { 455 $db->write_query("UPDATE ".TABLE_PREFIX."users SET postnum=postnum-1 WHERE uid = '{$post2['uid']}'"); 456 } 457 458 if($mybb->settings['akismetuidsignore']) 459 { 460 $akismet_uids_ignore = explode(',', $mybb->settings['akismetuidsignore']); 461 if(in_array($post2['usergroup'], $akismet_uids_ignore) || is_super_admin($post2['uid'])) 462 { 463 continue; 464 } 465 } 466 467 if(is_super_admin($post2['uid'])) 468 { 469 continue; 470 } 471 472 $db->write_query("UPDATE ".TABLE_PREFIX."users SET akismetstopped=akismetstopped+1 WHERE uid = '{$post2['uid']}'"); 473 $query1 = $db->simple_select("users", "akismetstopped", "uid = '{$post2['uid']}'"); 474 $akismetstopped = $db->fetch_field($query1, 'akismetstopped'); 475 476 // Check if the person should be banned 477 if($mybb->settings['akismetnumtillban'] > 0 && $akismetstopped >= $mybb->settings['akismetnumtillban']) 478 { 479 $banned_user = array( 480 "uid" => $post2['uid'], 481 "admin" => 0, 482 "gid" => 7, 483 "oldgroup" => $post2['usergroup'], 484 "dateline" => TIME_NOW, 485 "bantime" => 'perm', 486 "lifted" => 'perm', 487 "reason" => "Automatically banned by the Akismet system for spamming.", 488 "oldadditionalgroups" => '' 489 ); 490 $db->insert_query("banned", $banned_user); 491 492 $db->update_query("users", array('usergroup' => 7), "uid = '{$post2['uid']}'"); 493 494 $cache->update_moderators(); 495 } 496 } 497 498 ++$numakismetthread; 499 } 500 else 501 { 502 $db->write_query("UPDATE ".TABLE_PREFIX."users SET akismetstopped=akismetstopped+1 WHERE uid = '{$post['uid']}'"); 503 $query = $db->simple_select("users", "akismetstopped, usergroup", "uid = '{$post['uid']}'"); 504 $akismetstopped = $db->fetch_field($query, 'akismetstopped'); 505 $usergroup = $db->fetch_field($query, 'usergroup'); 506 507 if($mybb->settings['akismetuidsignore']) 508 { 509 $akismet_uids_ignore = explode(',', $mybb->settings['akismetuidsignore']); 510 if(in_array($usergroup, $akismet_uids_ignore)) 511 { 512 continue; 513 } 514 } 515 516 if(is_super_admin($post['uid'])) 517 { 518 continue; 519 } 520 521 // Check if the person should be banned 522 if($mybb->settings['akismetnumtillban'] > 0 && $akismetstopped >= $mybb->settings['akismetnumtillban']) 523 { 524 $banned_user = array( 525 "uid" => $post['uid'], 526 "admin" => 0, 527 "gid" => 7, 528 "oldgroup" => $usergroup, 529 "dateline" => TIME_NOW, 530 "bantime" => 'perm', 531 "lifted" => 'perm', 532 "reason" => "Automatically banned by the Akismet system for spamming.", 533 "oldadditionalgroups" => '' 534 ); 535 $db->insert_query("banned", $banned_user); 536 537 $db->update_query("users", array('usergroup' => 7), "uid = '{$post['uid']}'"); 538 539 $cache->update_moderators(); 540 } 541 542 ++$numakismetpost; 543 544 if($post['usepostcounts'] != 0) 545 { 546 $db->write_query("UPDATE ".TABLE_PREFIX."users SET postnum=postnum-1 WHERE uid = '{$post['uid']}'"); 547 } 548 } 549 550 update_thread_counters($post['tid'], array('replies' => '-'.$numakismetpost)); 551 update_forum_counters($post['fid'], array('threads' => '-'.$numakismetthread, 'posts' => '-'.$numakismetpost)); 552 553 if($snippit == "thread") 554 { 555 redirect(get_forum_link($post['fid']), $lang->thread_spam_success); 556 } 557 else 558 { 559 redirect(get_thread_link($post['tid']), $lang->post_spam_success); 560 } 561 } 562 563 function akismet_postbit(&$post) 564 { 565 global $templates, $mybb, $theme, $lang; 566 567 if(!$mybb->settings['akismetswitch'] || !is_moderator($post['fid'])) 568 { 569 return; 570 } 571 572 if($mybb->settings['akismetuidsignore']) 573 { 574 $akismet_uids_ignore = explode(',', $mybb->settings['akismetuidsignore']); 575 if(in_array($usergroup, $akismet_uids_ignore)) 576 { 577 return; 578 } 579 } 580 581 if(is_super_admin($post['uid'])) 582 { 583 return; 584 } 585 586 $lang->load("akismet", false, true); 587 588 eval("\$post['button_spam'] = \"".$templates->get("akismet_postbit_spam")."\";"); 589 } 590 591 function akismet_verify(&$post) 592 { 593 global $mybb, $isspam, $akismet; 594 595 if($isspam == true && $mybb->settings['akismetswitch'] == 1) 596 { 597 if(isset($post->thread_insert_data)) 598 { 599 $post->thread_insert_data['visible'] = '-4'; 600 } 601 602 $post->post_insert_data['visible'] = '-4'; 603 } 604 } 605 606 function akismet_fake_draft(&$post) 607 { 608 global $mybb, $isspam, $akismet, $cache; 609 610 $exclude_array = explode(',', $mybb->settings['akismetuserstoignore']); 611 612 if(!$mybb->settings['akismetswitch'] || in_array($mybb->user['uid'], $exclude_array) || is_super_admin($mybb->user['uid'])) 613 { 614 return; 615 } 616 617 if($mybb->settings['akismetfidsignore']) 618 { 619 $akismet_fids_ignore = explode(',', $mybb->settings['akismetfidsignore']); 620 if(in_array($post->data['fid'], $akismet_fids_ignore)) 621 { 622 return; 623 } 624 } 625 626 if($mybb->settings['akismetuidsignore']) 627 { 628 $akismet_uids_ignore = explode(',', $mybb->settings['akismetuidsignore']); 629 if(in_array($mybb->user['usergroup'], $akismet_uids_ignore)) 630 { 631 return; 632 } 633 } 634 635 $akismet_array = array( 636 'type' => 'post', 637 'username' => $post->data['username'], 638 'email' => $mybb->user['email'], 639 'website' => $mybb->user['website'], 640 'message' => $post->data['message'], 641 'user_ip' => $mybb->user['ipaddress'] 642 ); 643 644 if(!$akismet) 645 { 646 $akismet = new Akismet($mybb->settings['bburl'], $mybb->settings['akismetapikey'], $akismet_array); 647 } 648 649 if($akismet->check()) 650 { 651 global $db; 652 653 $isspam = true; 654 655 // Update our spam count attempts 656 ++$mybb->user['akismetstopped']; 657 $db->update_query("users", array('akismetstopped' => $mybb->user['akismetstopped']), "uid = '{$mybb->user['uid']}'"); 658 659 // Check if the person should be banned 660 if($mybb->settings['akismetnumtillban'] > 0 && $mybb->user['akismetstopped'] >= $mybb->settings['akismetnumtillban']) 661 { 662 $banned_user = array( 663 "uid" => $mybb->user['uid'], 664 "admin" => 0, 665 "gid" => 7, 666 "oldgroup" => $mybb->user['usergroup'], 667 "dateline" => TIME_NOW, 668 "bantime" => 'perm', 669 "lifted" => 'perm', 670 "reason" => "Automatically banned by the Akismet system for spamming.", 671 "oldadditionalgroups" => '' 672 ); 673 $db->insert_query("banned", $banned_user); 674 675 $db->update_query("users", array('usergroup' => 7), "uid = '{$mybb->user['uid']}'"); 676 677 $cache->update_moderators(); 678 679 // We better do this..otherwise they have dodgy permissions 680 $mybb->user['banoldgroup'] = $mybb->user['usergroup']; 681 $mybb->user['usergroup'] = 7; 682 683 global $mybbgroups; 684 685 $mybbgroups = $mybb->user['usergroup']; 686 if($mybb->user['additionalgroups']) 687 { 688 $mybbgroups .= ','.$mybb->user['additionalgroups']; 689 } 690 } 691 692 // Fake visibility 693 // Essentially because you can't modify the $visible variable we need to trick it 694 // into thinking its saving a draft so it won't modify the users lastpost and postcount 695 // In akismet_verify, its set back to -4 so we can still uniquely verify that this is a spam message 696 // before it's inserted into the database. 697 $post->data['savedraft'] = 1; 698 } 699 } 700 701 function akismet_redirect_thread() 702 { 703 global $isspam, $url, $lang, $thread, $mybb; 704 705 if($isspam && $mybb->settings['akismetswitch'] == 1) 706 { 707 $lang->load("akismet", false, true); 708 709 $url = get_thread_link($thread['tid']); 710 $url2 = get_forum_link($thread['fid']); 711 712 error("<div align=\"center\">".$lang->redirect_newreply."<br /><br />".$lang->sprintf($lang->redirect_return_forum, $url, $url2)."</div>", $lang->akismet_error); 713 } 714 } 715 716 function akismet_redirect_forum() 717 { 718 global $isspam, $url, $lang, $fid, $mybb; 719 720 if($isspam && $mybb->settings['akismetswitch'] == 1) 721 { 722 $lang->load("akismet", false, true); 723 724 $url = get_forum_link($fid); 725 726 error("<div align=\"center\">".$lang->redirect_newthread."<br /><br />".$lang->sprintf($lang->redirect_return_forum, $url)."</div>", $lang->akismet_error); 727 } 728 } 729 730 function akismet_action_handler(&$action) 731 { 732 $action['akismet'] = array('active' => 'akismet', 'file' => ''); 733 } 734 735 function akismet_admin_nav(&$sub_menu) 736 { 737 global $mybb, $lang; 738 739 if($mybb->settings['akismetswitch'] == 1) 740 { 741 $lang->load("forum_akismet", false, true); 742 743 end($sub_menu); 744 $key = (key($sub_menu))+10; 745 746 if(!$key) 747 { 748 $key = '50'; 749 } 750 751 $sub_menu[$key] = array('id' => 'akismet', 'title' => $lang->akismet, 'link' => "index.php?module=forum-akismet"); 752 } 753 } 754 755 function akismet_admin_permissions(&$admin_permissions) 756 { 757 global $db, $mybb; 758 759 if($mybb->settings['akismetswitch'] == 1) 760 { 761 global $lang; 762 763 $lang->load("forum_akismet", false, true); 764 765 $admin_permissions['akismet'] = $lang->can_manage_akismet; 766 } 767 } 768 769 function akismet_admin() 770 { 771 global $mybb, $db, $page, $lang; 772 773 if($page->active_action != "akismet") 774 { 775 return; 776 } 777 778 $page->add_breadcrumb_item($lang->akismet); 779 780 if($mybb->input['delete_all'] && $mybb->request_method == "post") 781 { 782 // User clicked no 783 if($mybb->input['no']) 784 { 785 admin_redirect("index.php?module=forum-akismet"); 786 } 787 788 if($mybb->request_method == "post") 789 { 790 // Delete the template 791 $db->delete_query("posts", "visible = '-4'"); 792 793 // Log admin action 794 log_admin_action(); 795 796 flash_message($lang->success_deleted_spam, 'success'); 797 admin_redirect("index.php?module=forum-akismet"); 798 } 799 else 800 { 801 $page->output_confirm_action("index.php?module=forum-akismet&delete_all=1", $lang->confirm_spam_deletion); 802 } 803 } 804 805 if($mybb->input['unmark'] && $mybb->request_method == "post") 806 { 807 $unmark = $mybb->input['akismet']; 808 809 if(empty($unmark)) 810 { 811 flash_message($lang->error_unmark, 'error'); 812 admin_redirect("index.php?module=forum-akismet"); 813 } 814 815 $posts_in = ''; 816 $comma = ''; 817 foreach($unmark as $key => $val) 818 { 819 $posts_in .= $comma.intval($key); 820 $comma = ','; 821 } 822 823 $query = $db->simple_select("posts", "pid, tid", "pid IN ({$posts_in}) AND replyto = '0'"); 824 while($post = $db->fetch_array($query)) 825 { 826 $threadp[] = $post['tid']; 827 } 828 829 if(!is_array($threadp)) 830 { 831 $threadp = array(); 832 } 833 834 $thread_list = implode(',', $threadp); 835 836 $query = $db->query(" 837 SELECT p.tid, f.usepostcounts, p.uid, p.fid, p.dateline, p.replyto, t.lastpost, t.lastposter, t.lastposteruid, t.subject 838 FROM ".TABLE_PREFIX."posts p 839 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 840 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) 841 WHERE p.pid IN ({$posts_in}) AND p.visible = '-4' 842 "); 843 while($post = $db->fetch_array($query)) 844 { 845 // Fetch the last post for this forum 846 $query2 = $db->query(" 847 SELECT tid, lastpost, lastposter, lastposteruid, subject 848 FROM ".TABLE_PREFIX."threads 849 WHERE fid='{$post['fid']}' AND visible='1' AND closed NOT LIKE 'moved|%' 850 ORDER BY lastpost DESC 851 LIMIT 0, 1 852 "); 853 $lastpost = $db->fetch_array($query2); 854 855 if($post['lastpost'] > $lastpost['lastpost']) 856 { 857 $lastpost['lastpost'] = $post['lastpost']; 858 $lastpost['lastposter'] = $post['lastposter']; 859 $lastpost['lastposteruid'] = $post['lastposteruid']; 860 $lastpost['subject'] = $post['subject']; 861 $lastpost['tid'] = $post['tid']; 862 } 863 864 $update_count = array( 865 "lastpost" => intval($lastpost['lastpost']), 866 "lastposter" => $db->escape_string($lastpost['lastposter']), 867 "lastposteruid" => intval($lastpost['lastposteruid']), 868 "lastposttid" => intval($lastpost['tid']), 869 "lastpostsubject" => $db->escape_string($lastpost['subject']) 870 ); 871 872 $db->update_query("forums", $update_count, "fid='{$post['fid']}'"); 873 874 $query2 = $db->query(" 875 SELECT u.uid, u.username, p.username AS postusername, p.dateline 876 FROM ".TABLE_PREFIX."posts p 877 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) 878 WHERE p.tid='{$post['tid']}' AND p.visible='1' OR p.pid = '{$post['pid']}' 879 ORDER BY p.dateline DESC 880 LIMIT 1" 881 ); 882 $lastpost = $db->fetch_array($query2); 883 884 $query2 = $db->query(" 885 SELECT u.uid, u.username, p.username AS postusername, p.dateline 886 FROM ".TABLE_PREFIX."posts p 887 LEFT JOIN ".TABLE_PREFIX."users u ON (u.uid=p.uid) 888 WHERE p.tid='{$post['tid']}' 889 ORDER BY p.dateline ASC 890 LIMIT 0,1 891 "); 892 $firstpost = $db->fetch_array($query2); 893 894 if(!$firstpost['username']) 895 { 896 $firstpost['username'] = $firstpost['postusername']; 897 } 898 if(!$lastpost['username']) 899 { 900 $lastpost['username'] = $lastpost['postusername']; 901 } 902 903 if(!$lastpost['dateline']) 904 { 905 $lastpost['username'] = $firstpost['username']; 906 $lastpost['uid'] = $firstpost['uid']; 907 $lastpost['dateline'] = $firstpost['dateline']; 908 } 909 910 $lastpost['username'] = $db->escape_string($lastpost['username']); 911 $firstpost['username'] = $db->escape_string($firstpost['username']); 912 913 $query2 = $db->simple_select("users", "akismetstopped", "uid='{$post['uid']}'"); 914 $akismetstopped = $db->fetch_field($query2, "akismetstopped")-1; 915 916 if($akismetstopped < 0) 917 { 918 $akismetstopped = 0; 919 } 920 $db->update_query("users", array('akismetstopped' => $akismetstopped), "uid='{$post['uid']}'"); 921 922 $update_array = array( 923 'username' => $firstpost['username'], 924 'uid' => intval($firstpost['uid']), 925 'lastpost' => intval($lastpost['dateline']), 926 'lastposter' => $lastpost['username'], 927 'lastposteruid' => intval($lastpost['uid']), 928 ); 929 $db->update_query("threads", $update_array, "tid='{$post['tid']}'"); 930 931 if($post['usepostcounts'] != 0) 932 { 933 $db->write_query("UPDATE ".TABLE_PREFIX."users SET postnum=postnum+1 WHERE uid = '{$post['uid']}'"); 934 } 935 936 $newthreads = $newreplies = 0; 937 938 if($post['replyto'] == 0) 939 { 940 ++$newthreads; 941 } 942 else 943 { 944 ++$newreplies; 945 } 946 947 update_thread_counters($post['tid'], array('replies' => '+'.$newreplies)); 948 update_forum_counters($post['fid'], array('threads' => '+'.$newthreads, 'posts' => '+1')); 949 } 950 951 $approve = array( 952 "visible" => 1, 953 ); 954 955 if($thread_list) 956 { 957 $db->update_query("threads", $approve, "tid IN ({$thread_list})"); 958 } 959 960 $db->update_query("posts", $approve, "pid IN ({$posts_in})"); 961 962 // Log admin action 963 log_admin_action(); 964 965 flash_message($lang->success_unmarked, 'success'); 966 admin_redirect("index.php?module=forum-akismet"); 967 } 968 969 if($mybb->input['delete'] && $mybb->request_method == "post") 970 { 971 $deletepost = $mybb->input['akismet']; 972 973 if(empty($deletepost)) 974 { 975 flash_message($lang->error_deletepost, 'error'); 976 admin_redirect("index.php?module=forum-akismet"); 977 } 978 979 $posts_in = ''; 980 $comma = ''; 981 foreach($deletepost as $key => $val) 982 { 983 $posts_in .= $comma.intval($key); 984 $comma = ','; 985 } 986 987 $query = $db->simple_select("posts", "pid, tid", "pid IN ({$posts_in}) AND replyto = '0'"); 988 while($post = $db->fetch_array($query)) 989 { 990 $threadp[$post['pid']] = $post['tid']; 991 } 992 993 if(!is_array($threadp)) 994 { 995 $threadp = array(); 996 } 997 998 require_once MYBB_ROOT."inc/functions_upload.php"; 999 1000 foreach($deletepost as $pid => $val) 1001 { 1002 if(array_key_exists($pid, $threadp)) 1003 { 1004 $db->delete_query("posts", "pid IN ({$posts_in})"); 1005 $db->delete_query("attachments", "pid IN ({$posts_in})"); 1006 1007 // Get thread info 1008 $query = $db->simple_select("threads", "poll", "tid='".$threadp[$pid]."'"); 1009 $poll = $db->fetch_field($query, 'poll'); 1010 1011 // Delete threads, redirects, favorites, polls, and poll votes 1012 $db->delete_query("threads", "tid='".$threadp[$pid]."'"); 1013 $db->delete_query("threads", "closed='moved|".$threadp[$pid]."'"); 1014 $db->delete_query("threadsubscriptions", "tid='".$threadp[$pid]."'"); 1015 $db->delete_query("polls", "tid='".$threadp[$pid]."'"); 1016 $db->delete_query("pollvotes", "pid='{$poll}'"); 1017 } 1018 1019 // Remove attachments 1020 remove_attachments($pid); 1021 1022 // Delete the post 1023 $db->delete_query("posts", "pid='{$pid}'"); 1024 } 1025 1026 // Log admin action 1027 log_admin_action(); 1028 1029 flash_message($lang->success_spam_deleted, 'success'); 1030 admin_redirect("index.php?module=forum-akismet"); 1031 } 1032 1033 if(!$mybb->input['action']) 1034 { 1035 require MYBB_ROOT."inc/class_parser.php"; 1036 $parser = new postParser; 1037 1038 $page->output_header($lang->akismet); 1039 1040 $form = new Form("index.php?module=forum-akismet", "post"); 1041 1042 $table = new Table; 1043 $table->construct_header($form->generate_check_box("checkall", 1, '', array('class' => 'checkall')), array('width' => '5%')); 1044 $table->construct_header("Title / Username / Post", array('class' => 'align_center')); 1045 1046 $mybb->input['page'] = intval($mybb->input['page']); 1047 1048 if($mybb->input['page'] > 0) 1049 { 1050 $start = $mybb->input['page'] * 20; 1051 } 1052 else 1053 { 1054 $start = 0; 1055 } 1056 1057 $query = $db->simple_select("posts", "COUNT(pid) as spam", "visible = '-4'"); 1058 $total_rows = $db->fetch_field($query, 'spam'); 1059 1060 if($start > $total_rows) 1061 { 1062 $start = $total_rows - 20; 1063 } 1064 1065 if($start < 0) 1066 { 1067 $start = 0; 1068 } 1069 1070 $query = $db->simple_select("posts", "*", "visible = '-4'", array('limit_start' => $start, 'limit' => '20', 'order_by' => 'dateline', 'order_dir' => 'desc')); 1071 while($post = $db->fetch_array($query)) 1072 { 1073 if($post['uid'] != 0) 1074 { 1075 $username = "<a href=\"../".str_replace("{uid}", $post['uid'], PROFILE_URL)."\" target=\"_blank\">".format_name($post['username'], $post['usergroup'], $post['displaygroup'])."</a>"; 1076 } 1077 else 1078 { 1079 $username = $post['username']; 1080 } 1081 1082 $table->construct_cell($form->generate_check_box("akismet[{$post['pid']}]", 1, '')); 1083 $table->construct_cell("<span style=\"float: right;\">{$lang->username} {$username}</span> <span style=\"float: left;\">{$lang->title}: ".htmlspecialchars_uni($post['subject'])." <strong>(".my_date($mybb->settings['dateformat'], $post['dateline']).", ".my_date($mybb->settings['timeformat'], $post['dateline']).")</strong></span>"); 1084 $table->construct_row(); 1085 1086 $parser_options = array( 1087 "allow_html" => 0, 1088 "allow_mycode" => 0, 1089 "allow_smilies" => 0, 1090 "allow_imgcode" => 0, 1091 "me_username" => $post['username'], 1092 "filter_badwords" => 1 1093 ); 1094 $post['message'] = $parser->parse_message($post['message'], $parser_options); 1095 1096 $table->construct_cell($post['message'], array("colspan" => 2)); 1097 $table->construct_row(); 1098 } 1099 1100 $num_rows = $table->num_rows(); 1101 1102 if($num_rows == 0) 1103 { 1104 $table->construct_cell($lang->no_spam_found, array("class" => "align_center", "colspan" => 2)); 1105 $table->construct_row(); 1106 } 1107 1108 $table->output($lang->detected_spam_messages); 1109 1110 echo "<br />".draw_admin_pagination($mybb->input['page'], 20, $total_rows, "index.php?module=forum-akismet&page={page}"); 1111 1112 $buttons[] = $form->generate_submit_button($lang->unmark_selected, array('name' => 'unmark')); 1113 $buttons[] = $form->generate_submit_button($lang->deleted_selected, array('name' => 'delete')); 1114 1115 if($num_rows > 0) 1116 { 1117 $buttons[] = $form->generate_submit_button($lang->delete_all, array('name' => 'delete_all', 'onclick' => "return confirm('{$lang->confirm_spam_deletion}');")); 1118 } 1119 1120 $form->output_submit_wrapper($buttons); 1121 1122 $form->end(); 1123 1124 $page->output_footer(); 1125 } 1126 1127 exit; 1128 } 1129 1130 /** 1131 * This class is Copyright 2009 Ryan Gordon (Tikitiki) 1132 * Built to communicate with the akismet server 1133 */ 1134 1135 class Akismet { 1136 1137 /** 1138 * The array of required server keys when building a query string 1139 * 1140 * @var array 1141 */ 1142 var $required = array( 1143 'HTTP_REFERRER', 1144 'HTTP_ACCEPT_CHARSET', 1145 'SERVERNAME', 1146 'SERVER_ADDR', 1147 'REMOTE_ADDR', 1148 'HTTP_USER_AGENT' 1149 ); 1150 1151 /** 1152 * The array of a post to validate against Akismet. 1153 * 1154 * @var array 1155 */ 1156 var $post = array(); 1157 1158 /** 1159 * The port to use to connect to the Akismet servers 1160 * 1161 * @var integer 1162 */ 1163 var $port = 80; 1164 1165 /** 1166 * The address to use to connect to the Akismet servers 1167 * 1168 * @var string 1169 */ 1170 var $host = "rest.akismet.com"; 1171 1172 /** 1173 * The version of Akismet being used 1174 * 1175 * @var integer 1176 */ 1177 var $version = "1.1"; 1178 1179 /** 1180 * The API key used to validate your use of Akismet 1181 * 1182 * @var string 1183 */ 1184 var $key = false; 1185 1186 /** 1187 * The main page of your forum 1188 * 1189 * @var string 1190 */ 1191 var $site = false; 1192 1193 /** 1194 * The object of the Akismet connection 1195 * 1196 * @var object 1197 */ 1198 var $connection; 1199 1200 /** 1201 * Errors (uh oh) 1202 * 1203 * @var array 1204 */ 1205 var $errors = array(); 1206 1207 /** 1208 * Initilize the Akismet class 1209 * 1210 * @param string The board url. 1211 * @param int The API Key used to validate your use of Akismet. 1212 * @param array Array of the post that is going to be validated by Akismet. 1213 */ 1214 function Akismet($url, $api_key, $post) 1215 { 1216 // Set option stuff 1217 $this->url = $url; 1218 $this->api_key = $api_key; 1219 1220 $this->post = $post; 1221 1222 $this->format_post(); 1223 1224 if(!isset($this->post['user_ip'])) 1225 { 1226 if($_SERVER['REMOTE_ADDR'] != getenv('SERVER_ADDR')) 1227 { 1228 $this->post['user_ip'] = $_SERVER['REMOTE_ADDR']; 1229 } 1230 else 1231 { 1232 $this->post['user_ip'] = getenv('HTTP_X_FORWARDED_FOR'); 1233 } 1234 } 1235 1236 if(!isset($this->post['permalink'])) 1237 { 1238 $this->post['permalink'] = $_SERVER['HTTP_REFERER']; 1239 } 1240 1241 if(!isset($this->post['user_agent'])) 1242 { 1243 $this->post['user_agent'] = $_SERVER['HTTP_USER_AGENT']; 1244 } 1245 1246 if(!isset($this->post['referrer'])) 1247 { 1248 $this->post['referrer'] = $_SERVER['HTTP_REFERER']; 1249 } 1250 1251 $this->post['blog'] = $url; 1252 1253 // Check if the API key is valid 1254 if(!$this->validate_api_key()) 1255 { 1256 $this->set_error("invalid_key"); 1257 } 1258 } 1259 1260 /** 1261 * Checks a post against the Akismet server 1262 * 1263 * @return boolean True if the comment passed spam validation. 1264 */ 1265 function check() 1266 { 1267 if($this->fetch_response($this->build_query_string(), 'comment-check') == "true") 1268 { 1269 // We have spam! 1270 return true; 1271 } 1272 1273 // Good! The check failed; We're all good to go! 1274 return false; 1275 } 1276 1277 /** 1278 * Submits a spam post to the Akismet server 1279 * 1280 */ 1281 function submit_spam() 1282 { 1283 $this->fetch_response($this->build_query_string(), 'submit-spam'); 1284 } 1285 1286 /** 1287 * Submits a ham post to the Akismet server 1288 * 1289 */ 1290 function submit_ham() 1291 { 1292 $this->fetch_response($this->build_query_string(), 'submit-ham'); 1293 } 1294 1295 /** 1296 * Validate a API Key against the Akismet server 1297 * 1298 * @return boolean True if the API Key passed. 1299 */ 1300 function validate_api_key() 1301 { 1302 if($this->fetch_response("key=".$this->api_key."&blog=".urlencode($this->url), 'verify-key') == "valid") 1303 { 1304 return true; 1305 } 1306 1307 return false; 1308 } 1309 1310 /** 1311 * Formats the comment array to the Akismet API Standards 1312 * 1313 */ 1314 function format_post() 1315 { 1316 $format = array( 1317 'type' => 'comment_type', 1318 'username' => 'comment_author', 1319 'email' => 'comment_author_email', 1320 'website' => 'comment_author_url', 1321 'message' => 'comment_content', 1322 ); 1323 1324 // Basically we're assigning $long to the comment array if $short in the comment array, is not null 1325 foreach($format as $short => $long) 1326 { 1327 if(isset($this->post[$short])) 1328 { 1329 $this->post[$long] = $this->post[$short]; 1330 unset($this->post[$short]); 1331 } 1332 } 1333 } 1334 1335 /** 1336 * Builds a query string to work with Akismet 1337 * 1338 * @return string The built query string 1339 */ 1340 function build_query_string() 1341 { 1342 foreach($_SERVER as $key => $value) 1343 { 1344 if(in_array($key, $this->required)) 1345 { 1346 if($key == 'REMOTE_ADDR') 1347 { 1348 $this->post[$key] = $this->post['user_ip']; 1349 } 1350 else 1351 { 1352 $this->post[$key] = $value; 1353 } 1354 } 1355 } 1356 1357 1358 $query_string = ''; 1359 foreach($this->post as $key => $data) 1360 { 1361 $query_string .= $key.'='.urlencode(stripslashes($data)).'&'; 1362 } 1363 1364 return $query_string; 1365 } 1366 1367 /** 1368 * Connects to the Akismet server 1369 * 1370 * @return boolean True on success. 1371 */ 1372 function connect() 1373 { 1374 $this->connection = @fsockopen($this->host, 80); 1375 if(!$this->connection) 1376 { 1377 $this->set_error("server_not_found"); 1378 return false; 1379 } 1380 1381 return true; 1382 } 1383 1384 /** 1385 * Sends a request to the Akismet server 1386 * 1387 * @param string The request uri. 1388 * @param string The path to what is being checked (e.x. 'comment-spam'). 1389 * @return mixed The response on success, false otherwise. 1390 */ 1391 function fetch_response($request, $path) 1392 { 1393 $this->connect(); 1394 1395 if($this->connection == true && !$this->errors['server_not_found']) 1396 { 1397 if(!empty($this->api_key)) 1398 { 1399 $api_key = $this->api_key."."; 1400 } 1401 else 1402 { 1403 $api_key = ""; 1404 } 1405 1406 $http_request = "POST /{$this->version}/{$path} HTTP/1.1\r\n"; 1407 $http_request .= "Host: {$api_key}{$this->host}\r\n"; 1408 $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n"; 1409 $http_request .= "Content-Length: ".strlen($request)."\r\n"; 1410 $http_request .= "User-Agent: MyBB/1.6 | Akismet/1.1\r\n"; 1411 $http_request .= "Connection: close\r\n"; 1412 $http_request .= "\r\n"; 1413 $http_request .= $request; 1414 1415 @fwrite($this->connection, $http_request); 1416 1417 $http_response = ""; 1418 while(feof($this->connection) === false) 1419 { 1420 $http_response .= @fgets($this->connection, 1160); 1421 } 1422 1423 $http_response = explode("\r\n\r\n", $http_response, 2); 1424 return $http_response[1]; 1425 } 1426 else 1427 { 1428 $this->set_error("response_failed"); 1429 return false; 1430 } 1431 1432 $this->disconnect(); 1433 } 1434 1435 /** 1436 * Disconnects from the Akismet server 1437 * 1438 */ 1439 function disconnect() 1440 { 1441 @fclose($this->connection); 1442 } 1443 1444 /** 1445 * Append an error onto the error array 1446 * 1447 * @param string The error message. 1448 * @param int The error code of the error. 1449 * @return boolean Always true. 1450 */ 1451 function set_error($error_code) 1452 { 1453 switch($error_code) 1454 { 1455 case "server_not_found": 1456 $message = "Could not connect to Akismet server."; 1457 break; 1458 case "response_failed": 1459 $message = "There was a problem retrieving the response."; 1460 break; 1461 case "invalid_key": 1462 $message = "Your Akismet API key does not appear to be valid."; 1463 break; 1464 default: 1465 $message = "Unkown error."; 1466 break; 1467 } 1468 $this->errors[$error_code] = $message; 1469 1470 return true; 1471 } 1472 1473 /** 1474 * Check if a specified error exists with the error array 1475 * 1476 * @param int The error code 1477 * @return boolean True if error exists. 1478 */ 1479 function error_exists($error_code) 1480 { 1481 if(isset($this->errors[$error_code])) 1482 { 1483 return true; 1484 } 1485 1486 return false; 1487 } 1488 1489 /** 1490 * Checks if there are any errors stored in the error array 1491 * 1492 * @return boolean True if there errors. 1493 */ 1494 function errors_exist() 1495 { 1496 if(count($this->errors) > 0) 1497 { 1498 return true; 1499 } 1500 1501 return false; 1502 } 1503 } 1504 1505 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Oct 8 19:19:50 2013 | Cross-referenced by PHPXref 0.7.1 |