[ Index ]

PHP Cross Reference of MyBB 1.6.5

title

Body

[close]

/admin/inc/ -> functions.php (source)

   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 5544 2011-08-08 15:41:40Z 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("&amp;", "&", $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\">&laquo; {$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=\"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} &raquo;</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($canpostattachments[$usergroup['gid']] == 1)
 304              {
 305                  $pattachments = 1;
 306              }
 307              else
 308              {
 309                  $pattachments = 0;
 310              }
 311              
 312              if(!$preplies && !$pthreads)
 313              {
 314                  $ppost = 0;
 315              }
 316              else
 317              {
 318                  $ppost = 1;
 319              }
 320              
 321              $insertquery = array(
 322                  "fid" => intval($fid),
 323                  "gid" => intval($usergroup['gid']),
 324                  "canview" => intval($pview),
 325                  "canpostthreads" => intval($pthreads),
 326                  "canpostreplys" => intval($preplies),
 327                  "canpostattachments" => intval($pattachments),
 328                  "canpostpolls" => intval($ppolls),
 329              );
 330              
 331              foreach($permission_fields as $field => $value)
 332              {
 333                  if(array_key_exists($field, $insertquery))
 334                  {
 335                      continue;
 336                  }
 337                  
 338                  $insertquery[$db->escape_string($field)] = intval($existing_permissions[$field]);
 339              }
 340              
 341              $db->insert_query("forumpermissions", $insertquery);
 342          }
 343      }
 344      $cache->update_forumpermissions();
 345  }
 346  
 347  /**
 348   * Checks if a particular user has the necessary permissions to access a particular page.
 349   *
 350   * @param array Array containing module and action to check for
 351   */
 352  function check_admin_permissions($action, $error = true)
 353  {
 354      global $mybb, $page, $lang, $modules_dir;
 355      
 356      if(is_super_admin($mybb->user['uid']))
 357      {
 358          return true;
 359      }
 360      
 361      require_once $modules_dir."/".$action['module']."/module_meta.php";
 362      if(function_exists($action['module']."_admin_permissions"))
 363      {    
 364          $func = $action['module']."_admin_permissions";
 365          $permissions = $func();
 366          if($permissions['permissions'][$action['action']] && $mybb->admin['permissions'][$action['module']][$action['action']] != 1)
 367          {
 368              if($error)
 369              {
 370                  $page->output_header($lang->access_denied);
 371                  $page->add_breadcrumb_item($lang->access_denied, "index.php?module=home-index");
 372                  $page->output_error("<b>{$lang->access_denied}</b><ul><li style=\"list-style-type: none;\">{$lang->access_denied_desc}</li></ul>");
 373                  $page->output_footer();
 374                  exit;
 375              }
 376              else
 377              {
 378                  return false;
 379              }
 380          }
 381      }
 382      
 383      return true;
 384  }
 385  
 386  /**
 387   * Fetches the list of administrator permissions for a particular user or group
 388   *
 389   * @param int The user ID to fetch permissions for
 390   * @param int The (optional) group ID to fetch permissions for
 391   * @return array Array of permissions for specified user or group
 392   */
 393  function get_admin_permissions($get_uid="", $get_gid="")
 394  {
 395      global $db, $mybb;
 396      
 397      // Set UID and GID if none
 398      $uid = $get_uid;
 399      $gid = $get_gid;
 400      
 401      $gid_array = array();
 402      
 403      if($uid === "")
 404      {
 405          $uid = $mybb->user['uid'];
 406      }
 407      
 408      if(!$gid)
 409      {
 410          // Prepare user's groups since the group isn't specified
 411          $gid_array[] = (-1) * intval($mybb->user['usergroup']);
 412          
 413          if($mybb->user['additionalgroups'])
 414          {
 415              $additional_groups = explode(',', $mybb->user['additionalgroups']);
 416              
 417              if(!empty($additional_groups))
 418              {
 419                  // Make sure gids are negative
 420                  foreach($additional_groups as $g)
 421                  {
 422                      $gid_array[] = (-1) * abs($g);
 423                  }
 424              }
 425          }
 426      }
 427      else
 428      {
 429          // Group is specified
 430          // Make sure gid is negative
 431          $gid_array[] = (-1) * abs($gid);
 432      }
 433  
 434      // What are we trying to find?
 435      if($get_gid && !$get_uid)
 436      {
 437          // A group only
 438          
 439          $options = array(
 440              "order_by" => "uid",
 441              "order_dir" => "ASC",
 442              "limit" => "1"
 443          );
 444          $query = $db->simple_select("adminoptions", "permissions", "(uid='-{$get_gid}' OR uid='0') AND permissions != ''", $options);
 445          return unserialize($db->fetch_field($query, "permissions"));
 446      }
 447      else
 448      {        
 449          // A user and/or group
 450          
 451          $options = array(
 452              "order_by" => "uid",
 453              "order_dir" => "DESC"
 454          );
 455          
 456          // Prepare user's groups into SQL format
 457          $group_sql = '';
 458          foreach($gid_array as $gid)
 459          {
 460              $group_sql .= " OR uid='{$gid}'";
 461          }
 462          
 463          $perms_group = array();
 464          $query = $db->simple_select("adminoptions", "permissions, uid", "(uid='{$uid}'{$group_sql}) AND permissions != ''", $options);
 465          while($perm = $db->fetch_array($query))
 466          {
 467              $perm['permissions'] = unserialize($perm['permissions']);
 468              
 469              // Sorting out which permission is which
 470              if($perm['uid'] > 0)
 471              {
 472                  $perms_user = $perm;
 473                  return $perms_user['permissions'];
 474              }
 475              elseif($perm['uid'] < 0)
 476              {
 477                  $perms_group[] = $perm['permissions'];
 478              }
 479              else
 480              {
 481                  $perms_def = $perm['permissions'];
 482              }
 483          }
 484          
 485          // Figure out group permissions...ugh.
 486          foreach($perms_group as $gperms)
 487          {
 488              if(!isset($final_group_perms))
 489              {
 490                  // Use this group as the base for admin group permissions
 491                  $final_group_perms = $gperms;
 492                  continue;
 493              }
 494              
 495              // Loop through each specific permission to find the highest permission
 496              foreach($gperms as $perm_name => $perm_value)
 497              {
 498                  if($final_group_perms[$perm_name] != '1' && $perm_value == '1')
 499                  {
 500                      $final_group_perms[$perm_name] = '1';
 501                  }
 502              }
 503          }
 504  
 505          // Send specific user, or group permissions before default.
 506          // If user's permission are explicitly set, they've already been returned above.
 507          if(isset($final_group_perms))
 508          {
 509              return $final_group_perms;
 510          }
 511          else
 512          {
 513              return $perms_def;
 514          }
 515      }
 516  }
 517  
 518  /**
 519   * Fetch the iconv/mb encoding for a particular MySQL encoding
 520   *
 521   * @param string The MySQL encoding
 522   * @return string The iconv/mb encoding
 523   */
 524  function fetch_iconv_encoding($mysql_encoding)
 525  {
 526      $mysql_encoding = explode("_", $mysql_encoding);
 527      switch($mysql_encoding[0])
 528      {
 529          case "utf8":
 530              return "utf-8";
 531              break;
 532          case "latin1":
 533              return "iso-8859-1";
 534              break;
 535          default:
 536              return $mysql_encoding[0];
 537      }
 538  }
 539  
 540  /**
 541   * Adds/Updates a Page/Tab to the permissions array in the adminoptions table
 542   *
 543   * @param string The name of the tab that is being affected
 544   * @param string The name of the page being affected (optional - if not specified, will affect everything under the specified tab)
 545   * @param integer Default permissions for the page (1 for allowed - 0 for disallowed - -1 to remove)
 546   */
 547  function change_admin_permission($tab, $page="", $default=1)
 548  {
 549      global $db;
 550      
 551      $query = $db->simple_select("adminoptions", "uid, permissions", "permissions != ''");
 552      while($adminoption = $db->fetch_array($query))
 553      {
 554          $adminoption['permissions'] = unserialize($adminoption['permissions']);
 555          
 556          if($default == -1)
 557          {
 558              if(!empty($page))
 559              {
 560                  unset($adminoption['permissions'][$tab][$page]);
 561              }
 562              else
 563              {
 564                  unset($adminoption['permissions'][$tab]);
 565              }
 566          }
 567          else
 568          {        
 569              if(!empty($page))
 570              {
 571                  if($adminoption['uid'] == 0)
 572                  {
 573                      $adminoption['permissions'][$tab][$page] = 0;
 574                  }
 575                  else
 576                  {
 577                      $adminoption['permissions'][$tab][$page] = $default;
 578                  }
 579              }
 580              else
 581              {
 582                  if($adminoption['uid'] == 0)
 583                  {
 584                      $adminoption['permissions'][$tab]['tab'] = 0;
 585                  }
 586                  else
 587                  {
 588                      $adminoption['permissions'][$tab]['tab'] = $default;
 589                  }
 590              }
 591          }
 592          
 593          $db->update_query("adminoptions", array('permissions' => $db->escape_string(serialize($adminoption['permissions']))), "uid='{$adminoption['uid']}'");
 594      }
 595  }
 596  
 597  /**
 598   * Checks if we have had too many attempts at logging into the ACP
 599   *
 600   * @param integer The uid of the admin to check
 601   * @param boolean Return an array of the number of attempts and expiry time? (default false)
 602   * @return mixed Return an array if the second parameter is true, boolean otherwise.
 603   */
 604  function login_attempt_check_acp($uid=0, $return_num=false)
 605  {
 606      global $db, $mybb;
 607      
 608      $attempts['loginattempts'] = 0;
 609      
 610      if($uid > 0)
 611      {
 612          $query = $db->simple_select("adminoptions", "loginattempts, loginlockoutexpiry", "uid='".intval($uid)."'", 1);
 613          $attempts = $db->fetch_array($query);
 614      }
 615      
 616      if($attempts['loginattempts'] <= 0)
 617      {
 618          return false;
 619      }
 620  
 621      if($mybb->settings['maxloginattempts'] > 0 && $attempts['loginattempts'] >= $mybb->settings['maxloginattempts'])
 622      {
 623          // Has the expiry dateline been set yet?
 624          if($attempts['loginlockoutexpiry'] == 0 && $return_num == false)
 625          {
 626              $db->update_query("adminoptions", array("loginlockoutexpiry" => TIME_NOW+(intval($mybb->settings['loginattemptstimeout'])*60)), "uid='".intval($uid)."'", 1);
 627          }
 628          
 629          // Are we returning the # of login attempts?
 630          if($return_num == true)
 631          {
 632              return $attempts;
 633          }
 634          // Otherwise are we still locked out?
 635          else if($attempts['loginlockoutexpiry'] > TIME_NOW)
 636          {
 637              return true;
 638          }
 639      }
 640      
 641      return false;
 642  }
 643  
 644  /**
 645   * Checks whether there are any 'security' issues in templates via complex syntax
 646   *
 647   * @param string The template to be scanned
 648   * @return boolean A true/false depending on if an issue was detected
 649   */
 650  function check_template($template)
 651  {
 652      // Check to see if our database password is in the template
 653      if(preg_match("#database'?\\s*\]\\s*\[\\s*'?password#", $template))
 654      {
 655          return true;
 656      }
 657  
 658      // Any other malicious acts?
 659      // Courtesy of ZiNgA BuRgA
 660      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)))
 661      {
 662          return true;
 663      }
 664  
 665      return false;
 666  }
 667  
 668  /**
 669   * Provides a function to entirely delete a user's posts, and find the threads attached to them
 670   *
 671   * @param integer The uid of the user
 672   * @param int A UNIX timestamp to delete posts that are older
 673   * @return array An array of threads to delete, threads/forums to recount
 674   */
 675  function delete_user_posts($uid, $date)
 676  {
 677      global $db, $cache;
 678      $uid = intval($uid);
 679  
 680      // Build an array of posts to delete
 681      $postcache = array();
 682      $query = $db->simple_select("posts", "pid", "uid = '".$uid."' AND dateline < '".$date."'");
 683      while($post = $db->fetch_array($query))
 684      {
 685          $postcache[] = $post['pid'];
 686      }
 687      
 688      if(!$db->num_rows($query))
 689      {
 690          return false;
 691      }
 692      elseif(!empty($postcache))
 693      {
 694          // Let's start deleting posts
 695          $user_posts = implode(",", $postcache);
 696          $query = $db->query("
 697              SELECT p.pid, p.visible, f.usepostcounts, t.tid AS thread, t.firstpost, t.fid AS forum
 698              FROM ".TABLE_PREFIX."posts p
 699              LEFT JOIN ".TABLE_PREFIX."forums f ON (f.fid=p.fid)
 700              LEFT JOIN ".TABLE_PREFIX."threads t ON (t.tid=p.tid)
 701              WHERE p.pid IN ({$user_posts})
 702          ");
 703  
 704          $post_count = 0; // Collect the post number to deduct from the user's postcount
 705          $thread_list = array();
 706          $forum_list = array();
 707          $delete_thread_list = array();
 708          if(!$db->num_rows($query))
 709          {
 710              return false;
 711          }
 712          else
 713          {
 714              while($post = $db->fetch_array($query))
 715              {
 716                  if($post['usepostcounts'] != 0 && $post['visible'] != 0)
 717                  {
 718                      ++$post_count;
 719                  }
 720  
 721                  if($post['pid'] == $post['firstpost'])
 722                  {
 723                      $delete_thread_list[] = $post['thread'];
 724                  }
 725  
 726                  if(!in_array($post['thread'], $thread_list) && !in_array($post['thread'], $delete_thread_list))
 727                  {
 728                      $thread_list[] = $post['thread']; // Threads that have been affected by this action, that aren't marked to be deleted
 729                  }
 730                  if(!in_array($post['forum'], $forum_list))
 731                  {
 732                      $forum_list[] = $post['forum']; // Forums that have been affected, too
 733                  }
 734  
 735                  // Remove the attachments to this post, then delete the post
 736                  remove_attachments($post['pid']);
 737                  $db->delete_query("posts", "pid = '".$post['pid']."'");
 738                  $db->delete_query("pollvotes", "pid = '".$post['pid']."'"); // Delete pollvotes attached to this post
 739              }
 740  
 741              $db->update_query("users", array("postnum" => "postnum-".$post_count.""), "uid='".$uid."'", 1, true);
 742  
 743              $to_return = array(
 744                  'to_delete' => $delete_thread_list,
 745                  'thread_update' => $thread_list,
 746                  'forum_update' => $forum_list
 747              );
 748  
 749              return $to_return;
 750          }
 751      }
 752  }
 753  ?>


Generated: Sun Dec 11 14:16:27 2011 Cross-referenced by PHPXref 0.7.1