[ Index ]

PHP Cross Reference of MyBB

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 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("&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=\"{$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} &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(!$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  ?>


Generated: Tue Oct 8 19:19:50 2013 Cross-referenced by PHPXref 0.7.1