[ 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: functions.php 5829 2012-05-22 10:48:03Z Tomm $ 10 */ 11 12 /** 13 * Logs an administrator action taking any arguments as log data. 14 */ 15 function log_admin_action() 16 { 17 global $db, $mybb; 18 19 $data = func_get_args(); 20 21 if(count($data) == 1 && is_array($data[0])) 22 { 23 $data = $data[0]; 24 } 25 26 if(!is_array($data)) 27 { 28 $data = array($data); 29 } 30 31 $log_entry = array( 32 "uid" => $mybb->user['uid'], 33 "ipaddress" => $db->escape_string(get_ip()), 34 "dateline" => TIME_NOW, 35 "module" => $db->escape_string($mybb->input['module']), 36 "action" => $db->escape_string($mybb->input['action']), 37 "data" => $db->escape_string(@serialize($data)) 38 ); 39 40 $db->insert_query("adminlog", $log_entry); 41 } 42 43 /** 44 * Redirects the current user to a specified URL. 45 * 46 * @param string The URL to redirect to 47 */ 48 function admin_redirect($url) 49 { 50 if(!headers_sent()) 51 { 52 $url = str_replace("&", "&", $url); 53 header("Location: $url"); 54 } 55 else 56 { 57 echo "<meta http-equiv=\"refresh\" content=\"0; url={$url}\">"; 58 } 59 exit; 60 } 61 62 /** 63 * Updates an administration session data array. 64 * 65 * @param string The name of the item in the data session to update 66 * @param mixed The value 67 */ 68 function update_admin_session($name, $value) 69 { 70 global $db, $admin_session; 71 72 $admin_session['data'][$name] = $value; 73 $updated_session = array( 74 "data" => $db->escape_string(@serialize($admin_session['data'])) 75 ); 76 $db->update_query("adminsessions", $updated_session, "sid='{$admin_session['sid']}'"); 77 } 78 79 /** 80 * Saves a "flash message" for the current user to be shown on their next page visit. 81 * 82 * @param string The message to show 83 * @param string The type of message to be shown (success|error) 84 */ 85 function flash_message($message, $type='') 86 { 87 $flash = array('message' => $message, 'type' => $type); 88 update_admin_session('flash_message', $flash); 89 } 90 91 /** 92 * Draw pagination for pages in the Admin CP. 93 * 94 * @param int The current page we're on 95 * @param int The number of items per page 96 * @param int The total number of items in this collection 97 * @param string The URL for pagination of this collection 98 * @return string The built pagination 99 */ 100 function draw_admin_pagination($page, $per_page, $total_items, $url) 101 { 102 global $mybb, $lang; 103 104 if($total_items <= $per_page) 105 { 106 return; 107 } 108 109 $pages = ceil($total_items / $per_page); 110 111 $pagination = "<div class=\"pagination\"><span class=\"pages\">{$lang->pages}: </span>\n"; 112 113 if($page > 1) 114 { 115 $prev = $page-1; 116 $prev_page = fetch_page_url($url, $prev); 117 $pagination .= "<a href=\"{$prev_page}\" class=\"pagination_previous\">« {$lang->previous}</a> \n"; 118 } 119 120 // Maximum number of "page bits" to show 121 if(!$mybb->settings['maxmultipagelinks']) 122 { 123 $mybb->settings['maxmultipagelinks'] = 5; 124 } 125 126 $max_links = $mybb->settings['maxmultipagelinks']; 127 128 $from = $page-floor($mybb->settings['maxmultipagelinks']/2); 129 $to = $page+floor($mybb->settings['maxmultipagelinks']/2); 130 131 if($from <= 0) 132 { 133 $from = 1; 134 $to = $from+$max_links-1; 135 } 136 137 if($to > $pages) 138 { 139 $to = $pages; 140 $from = $pages-$max_links+1; 141 if($from <= 0) 142 { 143 $from = 1; 144 } 145 } 146 147 if($to == 0) 148 { 149 $to = $pages; 150 } 151 152 153 if($from > 2) 154 { 155 $first = fetch_page_url($url, 1); 156 $pagination .= "<a href=\"{$first}\" title=\"{$lang->page} 1\" class=\"pagination_first\">1</a> ... "; 157 } 158 159 for($i = $from; $i <= $to; ++$i) 160 { 161 $page_url = fetch_page_url($url, $i); 162 if($page == $i) 163 { 164 $pagination .= "<span class=\"pagination_current\">{$i}</span> \n"; 165 } 166 else 167 { 168 $pagination .= "<a href=\"{$page_url}\" title=\"{$lang->page} {$i}\">{$i}</a> \n"; 169 } 170 } 171 172 if($to < $pages) 173 { 174 $last = fetch_page_url($url, $pages); 175 $pagination .= "... <a href=\"{$last}\" title=\"{$lang->page} {$pages}\" class=\"pagination_last\">{$pages}</a>"; 176 } 177 178 if($page < $pages) 179 { 180 $next = $page+1; 181 $next_page = fetch_page_url($url, $next); 182 $pagination .= " <a href=\"{$next_page}\" class=\"pagination_next\">{$lang->next} »</a>\n"; 183 } 184 $pagination .= "</div>\n"; 185 return $pagination; 186 } 187 188 /** 189 * Builds a CSV parent list for a particular forum. 190 * 191 * @param int The forum ID 192 * @param string Optional separator - defaults to comma for CSV list 193 * @return string The built parent list 194 */ 195 function make_parent_list($fid, $navsep=",") 196 { 197 global $pforumcache, $db; 198 199 if(!$pforumcache) 200 { 201 $query = $db->simple_select("forums", "name, fid, pid", "", array("order_by" => "disporder, pid")); 202 while($forum = $db->fetch_array($query)) 203 { 204 $pforumcache[$forum['fid']][$forum['pid']] = $forum; 205 } 206 } 207 208 reset($pforumcache); 209 reset($pforumcache[$fid]); 210 211 foreach($pforumcache[$fid] as $key => $forum) 212 { 213 if($fid == $forum['fid']) 214 { 215 if($pforumcache[$forum['pid']]) 216 { 217 $navigation = make_parent_list($forum['pid'], $navsep).$navigation; 218 } 219 220 if($navigation) 221 { 222 $navigation .= $navsep; 223 } 224 $navigation .= $forum['fid']; 225 } 226 } 227 return $navigation; 228 } 229 230 function save_quick_perms($fid) 231 { 232 global $db, $inherit, $canview, $canpostthreads, $canpostreplies, $canpostpolls, $canpostattachments, $cache; 233 234 $permission_fields = array(); 235 236 $field_list = $db->show_fields_from("forumpermissions"); 237 foreach($field_list as $field) 238 { 239 if(strpos($field['Field'], 'can') !== false) 240 { 241 $permission_fields[$field['Field']] = 1; 242 } 243 } 244 245 // "Can Only View Own Threads" permission is a forum permission only option 246 $usergroup_permission_fields = $permission_fields; 247 unset($usergroup_permission_fields['canonlyviewownthreads']); 248 249 $query = $db->simple_select("usergroups", "gid"); 250 while($usergroup = $db->fetch_array($query)) 251 { 252 $query2 = $db->simple_select("forumpermissions", $db->escape_string(implode(',', array_keys($permission_fields))), "fid='{$fid}' AND gid='{$usergroup['gid']}'", array('limit' => 1)); 253 $existing_permissions = $db->fetch_array($query2); 254 255 if(!$existing_permissions) 256 { 257 $query2 = $db->simple_select("usergroups", $db->escape_string(implode(',', array_keys($usergroup_permission_fields))), "gid='{$usergroup['gid']}'", array('limit' => 1)); 258 $existing_permissions = $db->fetch_array($query2); 259 } 260 261 // Delete existing permissions 262 $db->delete_query("forumpermissions", "fid='{$fid}' AND gid='{$usergroup['gid']}'"); 263 264 // Only insert the new ones if we're using custom permissions 265 if($inherit[$usergroup['gid']] != 1) 266 { 267 if($canview[$usergroup['gid']] == 1) 268 { 269 $pview = 1; 270 } 271 else 272 { 273 $pview = 0; 274 } 275 276 if($canpostthreads[$usergroup['gid']] == 1) 277 { 278 $pthreads = 1; 279 } 280 else 281 { 282 $pthreads = 0; 283 } 284 285 if($canpostreplies[$usergroup['gid']] == 1) 286 { 287 $preplies = 1; 288 } 289 else 290 { 291 $preplies = 0; 292 } 293 294 if($canpostpolls[$usergroup['gid']] == 1) 295 { 296 $ppolls = 1; 297 } 298 else 299 { 300 $ppolls = 0; 301 } 302 303 if(!$preplies && !$pthreads) 304 { 305 $ppost = 0; 306 } 307 else 308 { 309 $ppost = 1; 310 } 311 312 $insertquery = array( 313 "fid" => intval($fid), 314 "gid" => intval($usergroup['gid']), 315 "canview" => intval($pview), 316 "canpostthreads" => intval($pthreads), 317 "canpostreplys" => intval($preplies), 318 "canpostpolls" => intval($ppolls), 319 ); 320 321 foreach($permission_fields as $field => $value) 322 { 323 if(array_key_exists($field, $insertquery)) 324 { 325 continue; 326 } 327 328 $insertquery[$db->escape_string($field)] = intval($existing_permissions[$field]); 329 } 330 331 $db->insert_query("forumpermissions", $insertquery); 332 } 333 } 334 $cache->update_forumpermissions(); 335 } 336 337 /** 338 * Checks if a particular user has the necessary permissions to access a particular page. 339 * 340 * @param array Array containing module and action to check for 341 */ 342 function check_admin_permissions($action, $error = true) 343 { 344 global $mybb, $page, $lang, $modules_dir; 345 346 if(is_super_admin($mybb->user['uid'])) 347 { 348 return true; 349 } 350 351 require_once $modules_dir."/".$action['module']."/module_meta.php"; 352 if(function_exists($action['module']."_admin_permissions")) 353 { 354 $func = $action['module']."_admin_permissions"; 355 $permissions = $func(); 356 if($permissions['permissions'][$action['action']] && $mybb->admin['permissions'][$action['module']][$action['action']] != 1) 357 { 358 if($error) 359 { 360 $page->output_header($lang->access_denied); 361 $page->add_breadcrumb_item($lang->access_denied, "index.php?module=home-index"); 362 $page->output_error("<b>{$lang->access_denied}</b><ul><li style=\"list-style-type: none;\">{$lang->access_denied_desc}</li></ul>"); 363 $page->output_footer(); 364 exit; 365 } 366 else 367 { 368 return false; 369 } 370 } 371 } 372 373 return true; 374 } 375 376 /** 377 * Fetches the list of administrator permissions for a particular user or group 378 * 379 * @param int The user ID to fetch permissions for 380 * @param int The (optional) group ID to fetch permissions for 381 * @return array Array of permissions for specified user or group 382 */ 383 function get_admin_permissions($get_uid="", $get_gid="") 384 { 385 global $db, $mybb; 386 387 // Set UID and GID if none 388 $uid = $get_uid; 389 $gid = $get_gid; 390 391 $gid_array = array(); 392 393 if($uid === "") 394 { 395 $uid = $mybb->user['uid']; 396 } 397 398 if(!$gid) 399 { 400 // Prepare user's groups since the group isn't specified 401 $gid_array[] = (-1) * intval($mybb->user['usergroup']); 402 403 if($mybb->user['additionalgroups']) 404 { 405 $additional_groups = explode(',', $mybb->user['additionalgroups']); 406 407 if(!empty($additional_groups)) 408 { 409 // Make sure gids are negative 410 foreach($additional_groups as $g) 411 { 412 $gid_array[] = (-1) * abs($g); 413 } 414 } 415 } 416 } 417 else 418 { 419 // Group is specified 420 // Make sure gid is negative 421 $gid_array[] = (-1) * abs($gid); 422 } 423 424 // What are we trying to find? 425 if($get_gid && !$get_uid) 426 { 427 // A group only 428 429 $options = array( 430 "order_by" => "uid", 431 "order_dir" => "ASC", 432 "limit" => "1" 433 ); 434 $query = $db->simple_select("adminoptions", "permissions", "(uid='-{$get_gid}' OR uid='0') AND permissions != ''", $options); 435 return unserialize($db->fetch_field($query, "permissions")); 436 } 437 else 438 { 439 // A user and/or group 440 441 $options = array( 442 "order_by" => "uid", 443 "order_dir" => "DESC" 444 ); 445 446 // Prepare user's groups into SQL format 447 $group_sql = ''; 448 foreach($gid_array as $gid) 449 { 450 $group_sql .= " OR uid='{$gid}'"; 451 } 452 453 $perms_group = array(); 454 $query = $db->simple_select("adminoptions", "permissions, uid", "(uid='{$uid}'{$group_sql}) AND permissions != ''", $options); 455 while($perm = $db->fetch_array($query)) 456 { 457 $perm['permissions'] = unserialize($perm['permissions']); 458 459 // Sorting out which permission is which 460 if($perm['uid'] > 0) 461 { 462 $perms_user = $perm; 463 return $perms_user['permissions']; 464 } 465 elseif($perm['uid'] < 0) 466 { 467 $perms_group[] = $perm['permissions']; 468 } 469 else 470 { 471 $perms_def = $perm['permissions']; 472 } 473 } 474 475 // Figure out group permissions...ugh. 476 foreach($perms_group as $gperms) 477 { 478 if(!isset($final_group_perms)) 479 { 480 // Use this group as the base for admin group permissions 481 $final_group_perms = $gperms; 482 continue; 483 } 484 485 // Loop through each specific permission to find the highest permission 486 foreach($gperms as $perm_name => $perm_value) 487 { 488 if($final_group_perms[$perm_name] != '1' && $perm_value == '1') 489 { 490 $final_group_perms[$perm_name] = '1'; 491 } 492 } 493 } 494 495 // Send specific user, or group permissions before default. 496 // If user's permission are explicitly set, they've already been returned above. 497 if(isset($final_group_perms)) 498 { 499 return $final_group_perms; 500 } 501 else 502 { 503 return $perms_def; 504 } 505 } 506 } 507 508 /** 509 * Fetch the iconv/mb encoding for a particular MySQL encoding 510 * 511 * @param string The MySQL encoding 512 * @return string The iconv/mb encoding 513 */ 514 function fetch_iconv_encoding($mysql_encoding) 515 { 516 $mysql_encoding = explode("_", $mysql_encoding); 517 switch($mysql_encoding[0]) 518 { 519 case "utf8": 520 return "utf-8"; 521 break; 522 case "latin1": 523 return "iso-8859-1"; 524 break; 525 default: 526 return $mysql_encoding[0]; 527 } 528 } 529 530 /** 531 * Adds/Updates a Page/Tab to the permissions array in the adminoptions table 532 * 533 * @param string The name of the tab that is being affected 534 * @param string The name of the page being affected (optional - if not specified, will affect everything under the specified tab) 535 * @param integer Default permissions for the page (1 for allowed - 0 for disallowed - -1 to remove) 536 */ 537 function change_admin_permission($tab, $page="", $default=1) 538 { 539 global $db; 540 541 $query = $db->simple_select("adminoptions", "uid, permissions", "permissions != ''"); 542 while($adminoption = $db->fetch_array($query)) 543 { 544 $adminoption['permissions'] = unserialize($adminoption['permissions']); 545 546 if($default == -1) 547 { 548 if(!empty($page)) 549 { 550 unset($adminoption['permissions'][$tab][$page]); 551 } 552 else 553 { 554 unset($adminoption['permissions'][$tab]); 555 } 556 } 557 else 558 { 559 if(!empty($page)) 560 { 561 if($adminoption['uid'] == 0) 562 { 563 $adminoption['permissions'][$tab][$page] = 0; 564 } 565 else 566 { 567 $adminoption['permissions'][$tab][$page] = $default; 568 } 569 } 570 else 571 { 572 if($adminoption['uid'] == 0) 573 { 574 $adminoption['permissions'][$tab]['tab'] = 0; 575 } 576 else 577 { 578 $adminoption['permissions'][$tab]['tab'] = $default; 579 } 580 } 581 } 582 583 $db->update_query("adminoptions", array('permissions' => $db->escape_string(serialize($adminoption['permissions']))), "uid='{$adminoption['uid']}'"); 584 } 585 } 586 587 /** 588 * Checks if we have had too many attempts at logging into the ACP 589 * 590 * @param integer The uid of the admin to check 591 * @param boolean Return an array of the number of attempts and expiry time? (default false) 592 * @return mixed Return an array if the second parameter is true, boolean otherwise. 593 */ 594 function login_attempt_check_acp($uid=0, $return_num=false) 595 { 596 global $db, $mybb; 597 598 $attempts['loginattempts'] = 0; 599 600 if($uid > 0) 601 { 602 $query = $db->simple_select("adminoptions", "loginattempts, loginlockoutexpiry", "uid='".intval($uid)."'", 1); 603 $attempts = $db->fetch_array($query); 604 } 605 606 if($attempts['loginattempts'] <= 0) 607 { 608 return false; 609 } 610 611 if($mybb->settings['maxloginattempts'] > 0 && $attempts['loginattempts'] >= $mybb->settings['maxloginattempts']) 612 { 613 // Has the expiry dateline been set yet? 614 if($attempts['loginlockoutexpiry'] == 0 && $return_num == false) 615 { 616 $db->update_query("adminoptions", array("loginlockoutexpiry" => TIME_NOW+(intval($mybb->settings['loginattemptstimeout'])*60)), "uid='".intval($uid)."'", 1); 617 } 618 619 // Are we returning the # of login attempts? 620 if($return_num == true) 621 { 622 return $attempts; 623 } 624 // Otherwise are we still locked out? 625 else if($attempts['loginlockoutexpiry'] > TIME_NOW) 626 { 627 return true; 628 } 629 } 630 631 return false; 632 } 633 634 /** 635 * Checks whether there are any 'security' issues in templates via complex syntax 636 * 637 * @param string The template to be scanned 638 * @return boolean A true/false depending on if an issue was detected 639 */ 640 function check_template($template) 641 { 642 // Check to see if our database password is in the template 643 if(preg_match("#database'?\\s*\]\\s*\[\\s*'?password#", $template)) 644 { 645 return true; 646 } 647 648 // System calls via backtick 649 if(preg_match('#\$\s*\{#', $template)) 650 { 651 return true; 652 } 653 654 // Any other malicious acts? 655 // Courtesy of ZiNgA BuRgA 656 if(preg_match("~\\{\\$.+?\\}~s", preg_replace('~\\{\\$+[a-zA-Z_][a-zA-Z_0-9]*((?:-\\>|\\:\\:)\\$*[a-zA-Z_][a-zA-Z_0-9]*|\\[\s*\\$*([\'"]?)[a-zA-Z_ 0-9 ]+\\2\\]\s*)*\\}~', '', $template))) 657 { 658 return true; 659 } 660 661 return false; 662 } 663 664 /** 665 * Provides a function to entirely delete a user's posts, and find the threads attached to them 666 * 667 * @param integer The uid of the user 668 * @param int A UNIX timestamp to delete posts that are older 669 * @return array An array of threads to delete, threads/forums to recount 670 */ 671 function delete_user_posts($uid, $date) 672 { 673 global $db, $cache; 674 $uid = intval($uid); 675 676 // Build an array of posts to delete 677 $postcache = array(); 678 $query = $db->simple_select("posts", "pid", "uid = '".$uid."' AND dateline < '".$date."'"); 679 while($post = $db->fetch_array($query)) 680 { 681 $postcache[] = $post['pid']; 682 } 683 684 if(!$db->num_rows($query)) 685 { 686 return false; 687 } 688 elseif(!empty($postcache)) 689 { 690 // Let's start deleting posts 691 $user_posts = implode(",", $postcache); 692 $query = $db->query(" 693 SELECT p.pid, p.visible, f.usepostcounts, t.tid AS thread, t.firstpost, t.fid AS forum 694 FROM ".TABLE_PREFIX."posts p 695 LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid) 696 LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid) 697 WHERE p.pid IN ({$user_posts}) 698 "); 699 700 $post_count = 0; // Collect the post number to deduct from the user's postcount 701 $thread_list = array(); 702 $forum_list = array(); 703 $delete_thread_list = array(); 704 if(!$db->num_rows($query)) 705 { 706 return false; 707 } 708 else 709 { 710 while($post = $db->fetch_array($query)) 711 { 712 if($post['usepostcounts'] != 0 && $post['visible'] != 0) 713 { 714 ++$post_count; 715 } 716 717 if($post['pid'] == $post['firstpost']) 718 { 719 $delete_thread_list[] = $post['thread']; 720 } 721 722 if(!in_array($post['thread'], $thread_list) && !in_array($post['thread'], $delete_thread_list)) 723 { 724 $thread_list[] = $post['thread']; // Threads that have been affected by this action, that aren't marked to be deleted 725 } 726 if(!in_array($post['forum'], $forum_list)) 727 { 728 $forum_list[] = $post['forum']; // Forums that have been affected, too 729 } 730 731 // Remove the attachments to this post, then delete the post 732 remove_attachments($post['pid']); 733 $db->delete_query("posts", "pid = '".$post['pid']."'"); 734 $db->delete_query("pollvotes", "pid = '".$post['pid']."'"); // Delete pollvotes attached to this post 735 } 736 737 $db->update_query("users", array("postnum" => "postnum-".$post_count.""), "uid='".$uid."'", 1, true); 738 739 $to_return = array( 740 'to_delete' => $delete_thread_list, 741 'thread_update' => $thread_list, 742 'forum_update' => $forum_list 743 ); 744 745 return $to_return; 746 } 747 } 748 } 749 ?>
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 |