[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-forums/bbpress/bb-includes/ -> functions.bb-core.php (source)

   1  <?php
   2  /**
   3   * Core bbPress functions.
   4   *
   5   * @package bbPress
   6   */
   7  
   8  
   9  
  10  /**
  11   * Initialization functions mostly called in bb-settings.php
  12   */
  13  
  14  /**
  15   * Marks things as deprecated and informs when they have been used.
  16   *
  17   * @since 0.9
  18   *
  19   * @param string $type The type of thing that was attempted: function, class::function, constant, variable or page.
  20   * @param string $name The thing that was called.
  21   * @param string $replacement Optional. The thing that should have been called.
  22   * @uses $bb_log BP_Log logging object.
  23   */
  24  function bb_log_deprecated( $type, $name, $replacement = 'none' ) {
  25      global $bb_log;
  26      $bb_log->notice( sprintf( __( 'Using deprecated bbPress %1$s - %2$s - replace with - %3$s' ), $type, $name, $replacement ) );
  27  
  28      if ( $bb_log->level & BP_LOG_DEBUG && $bb_log->level & BP_LOG_NOTICE ) { // Only compute the location if we're going to log it.
  29          $backtrace = debug_backtrace();
  30  
  31          $file = $backtrace[2]['file'];
  32  
  33          if ( substr( $file, 0, strlen( BB_PATH ) - 1 ) == rtrim( BB_PATH, '\\/') )
  34              $file = substr( $file, strlen( BB_PATH ) );
  35  
  36          $file = str_replace( '\\', '/', $file );
  37  
  38          // 0 = this function, 1 = the deprecated function
  39          $bb_log->notice( '    ' . sprintf( __( 'on line %1$d of file %2$s' ), $backtrace[2]['line'], $file ) );
  40      }
  41  }
  42  
  43  /**
  44   * Sanitizes user input en-masse.
  45   *
  46   * @param mixed $array The array of values or a single value to sanitize, usually a global variable like $_GET or $_POST.
  47   * @param boolean $trim Optional. Whether to trim the value or not. Default is true.
  48   * @return mixed The sanitized data.
  49   */
  50  function bb_global_sanitize( $array, $trim = true )
  51  {
  52      foreach ( $array as $k => $v ) {
  53          if ( is_array( $v ) ) {
  54              $array[$k] = bb_global_sanitize( $v );
  55          } else {
  56              if ( !get_magic_quotes_gpc() ) {
  57                  $array[$k] = addslashes( $v );
  58              }
  59              if ( $trim ) {
  60                  $array[$k] = trim( $array[$k] );
  61              }
  62          }
  63      }
  64  
  65      return $array;
  66  }
  67  
  68  /**
  69   * Reports whether bbPress is installed by getting forums.
  70   *
  71   * @return boolean True if there are forums, otherwise false.
  72   */
  73  function bb_is_installed()
  74  {
  75      // Maybe grab all the forums and cache them
  76      global $bbdb;
  77      $bbdb->suppress_errors();
  78      $forums = (array) @bb_get_forums();
  79      $bbdb->suppress_errors(false);
  80  
  81      if ( !$forums ) {
  82          return false;
  83      }
  84  
  85      return true;
  86  }
  87  
  88  /**
  89   * Sets the required variables to connect to custom user tables.
  90   *
  91   * @return boolean Always returns true.
  92   */
  93  function bb_set_custom_user_tables()
  94  {
  95      global $bb;
  96  
  97      // Check for older style custom user table
  98      if ( !isset( $bb->custom_tables['users'] ) ) { // Don't stomp new setting style
  99          if ( $bb->custom_user_table = bb_get_option( 'custom_user_table' ) ) {
 100              if ( !isset( $bb->custom_tables ) ) {
 101                  $bb->custom_tables = array();
 102              }
 103              $bb->custom_tables['users'] = $bb->custom_user_table;
 104          }
 105      }
 106  
 107      // Check for older style custom user meta table
 108      if ( !isset( $bb->custom_tables['usermeta'] ) ) { // Don't stomp new setting style
 109          if ( $bb->custom_user_meta_table = bb_get_option( 'custom_user_meta_table' ) ) {
 110              if ( !isset( $bb->custom_tables ) ) {
 111                  $bb->custom_tables = array();
 112              }
 113              $bb->custom_tables['usermeta'] = $bb->custom_user_meta_table;
 114          }
 115      }
 116  
 117      // Check for older style wp_table_prefix
 118      if ( $bb->wp_table_prefix = bb_get_option( 'wp_table_prefix' ) ) { // User has set old constant
 119          if ( !isset( $bb->custom_tables ) ) {
 120              $bb->custom_tables = array(
 121                  'users'    => $bb->wp_table_prefix . 'users',
 122                  'usermeta' => $bb->wp_table_prefix . 'usermeta'
 123              );
 124          } else {
 125              if ( !isset( $bb->custom_tables['users'] ) ) { // Don't stomp new setting style
 126                  $bb->custom_tables['users'] = $bb->wp_table_prefix . 'users';
 127              }
 128              if ( !isset( $bb->custom_tables['usermeta'] ) ) {
 129                  $bb->custom_tables['usermeta'] = $bb->wp_table_prefix . 'usermeta';
 130              }
 131          }
 132      }
 133  
 134      if ( bb_get_option( 'wordpress_mu_primary_blog_id' ) ) {
 135          $bb->wordpress_mu_primary_blog_id = bb_get_option( 'wordpress_mu_primary_blog_id' );
 136      }
 137  
 138      // Check for older style user database
 139      if ( !isset( $bb->custom_databases ) ) {
 140          $bb->custom_databases = array();
 141      }
 142      if ( !isset( $bb->custom_databases['user'] ) ) {
 143          if ( $bb->user_bbdb_name = bb_get_option( 'user_bbdb_name' ) ) {
 144              $bb->custom_databases['user']['name'] = $bb->user_bbdb_name;
 145          }
 146          if ( $bb->user_bbdb_user = bb_get_option( 'user_bbdb_user' ) ) {
 147              $bb->custom_databases['user']['user'] = $bb->user_bbdb_user;
 148          }
 149          if ( $bb->user_bbdb_password = bb_get_option( 'user_bbdb_password' ) ) {
 150              $bb->custom_databases['user']['password'] = $bb->user_bbdb_password;
 151          }
 152          if ( $bb->user_bbdb_host = bb_get_option( 'user_bbdb_host' ) ) {
 153              $bb->custom_databases['user']['host'] = $bb->user_bbdb_host;
 154          }
 155          if ( $bb->user_bbdb_charset = bb_get_option( 'user_bbdb_charset' ) ) {
 156              $bb->custom_databases['user']['charset'] = $bb->user_bbdb_charset;
 157          }
 158          if ( $bb->user_bbdb_collate = bb_get_option( 'user_bbdb_collate' ) ) {
 159              $bb->custom_databases['user']['collate'] = $bb->user_bbdb_collate;
 160          }
 161          if ( isset( $bb->custom_databases['user'] ) ) {
 162              if ( isset( $bb->custom_tables['users'] ) ) {
 163                  $bb->custom_tables['users'] = array( 'user', $bb->custom_tables['users'] );
 164              }
 165              if ( isset( $bb->custom_tables['usermeta'] ) ) {
 166                  $bb->custom_tables['usermeta'] = array( 'user', $bb->custom_tables['usermeta'] );
 167              }
 168          }
 169      }
 170  
 171      return true;
 172  }
 173  
 174  
 175  /* Pagination */
 176  
 177  /**
 178   * Retrieve paginated links for pages.
 179   *
 180   * Technically, the function can be used to create paginated link list for any
 181   * area. The 'base' argument is used to reference the url, which will be used to
 182   * create the paginated links. The 'format' argument is then used for replacing
 183   * the page number. It is however, most likely and by default, to be used on the
 184   * archive post pages.
 185   *
 186   * The 'type' argument controls format of the returned value. The default is
 187   * 'plain', which is just a string with the links separated by a newline
 188   * character. The other possible values are either 'array' or 'list'. The
 189   * 'array' value will return an array of the paginated link list to offer full
 190   * control of display. The 'list' value will place all of the paginated links in
 191   * an unordered HTML list.
 192   *
 193   * The 'total' argument is the total amount of pages and is an integer. The
 194   * 'current' argument is the current page number and is also an integer.
 195   *
 196   * An example of the 'base' argument is "http://example.com/all_posts.php%_%"
 197   * and the '%_%' is required. The '%_%' will be replaced by the contents of in
 198   * the 'format' argument. An example for the 'format' argument is "?page=%#%"
 199   * and the '%#%' is also required. The '%#%' will be replaced with the page
 200   * number.
 201   *
 202   * You can include the previous and next links in the list by setting the
 203   * 'prev_next' argument to true, which it is by default. You can set the
 204   * previous text, by using the 'prev_text' argument. You can set the next text
 205   * by setting the 'next_text' argument.
 206   *
 207   * If the 'show_all' argument is set to true, then it will show all of the pages
 208   * instead of a short list of the pages near the current page. By default, the
 209   * 'show_all' is set to false and controlled by the 'end_size' and 'mid_size'
 210   * arguments. The 'end_size' argument is how many numbers on either the start
 211   * and the end list edges, by default is 1. The 'mid_size' argument is how many
 212   * numbers to either side of current page, but not including current page.
 213   *
 214   * It is possible to add query vars to the link by using the 'add_args' argument
 215   * and see {@link add_query_arg()} for more information.
 216   *
 217   * @since 1.0
 218   *
 219   * @param string|array $args Optional. Override defaults.
 220   * @return array|string String of page links or array of page links.
 221   */
 222  function bb_paginate_links( $args = '' ) {
 223      $defaults = array(
 224          'base'         => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below)
 225          'format'       => '?page=%#%', // ?page=%#% : %#% is replaced by the page number
 226          'total'        => 1,
 227          'current'      => 0,
 228          'show_all'     => false,
 229          'prev_next'    => true,
 230          'prev_text'    => __( '&laquo; Previous' ),
 231          'next_text'    => __( 'Next &raquo;' ),
 232          'end_size'     => 1, // How many numbers on either end including the end
 233          'mid_size'     => 2, // How many numbers to either side of current not including current
 234          'type'         => 'plain',
 235          'add_args'     => false, // array of query args to add
 236          'add_fragment' => '',
 237          'n_title'      => __( 'Page %d' ), // Not from WP version
 238          'prev_title'   => __( 'Previous page' ), // Not from WP version
 239          'next_title'   => __( 'Next page' ) // Not from WP version
 240      );
 241  
 242      $args = wp_parse_args( $args, $defaults );
 243      extract( $args, EXTR_SKIP );
 244  
 245      // Who knows what else people pass in $args
 246      $total = (int) $total;
 247      if ( $total < 2 )
 248          return;
 249      $current  = (int) $current;
 250      $end_size = 0 < (int) $end_size ? (int) $end_size : 1; // Out of bounds?  Make it the default.
 251      $mid_size = 0 <= (int) $mid_size ? (int) $mid_size : 2;
 252      $add_args = is_array($add_args) ? $add_args : false;
 253      $r = '';
 254      $page_links = array();
 255      $n = 0;
 256      $dots = false;
 257  
 258      $empty_format = '';
 259      if ( strpos( $format, '?' ) === 0 ) {
 260          $empty_format = '?';
 261      }
 262  
 263      if ( $prev_next && $current && 1 < $current ) {
 264          $link = str_replace( '%_%', 2 == $current ? $empty_format : $format, $base );
 265          $link = str_replace( '%#%', $current - 1, $link );
 266          $link = str_replace( '?&', '?', $link );
 267          if ( $add_args )
 268              $link = add_query_arg( $add_args, $link );
 269          $link .= $add_fragment;
 270          $page_links[] = '<a class="prev page-numbers" href="' . esc_url( $link ) . '" title="' . esc_attr( $prev_title ) . '">' . $prev_text . '</a>';
 271      }
 272  
 273      for ( $n = 1; $n <= $total; $n++ ) {
 274          if ( $n == $current ) {
 275              $n_display = bb_number_format_i18n( $n );
 276              $n_display_title =  esc_attr( sprintf( $n_title, $n ) );
 277              $page_links[] = '<span class="page-numbers current" title="' . $n_display_title . '">' . $n_display . '</span>';
 278              $dots = true;
 279          } else {
 280              if ( $show_all || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $total - $end_size ) ) {
 281                  $n_display = bb_number_format_i18n( $n );
 282                  $n_display_title =  esc_attr( sprintf( $n_title, $n ) );
 283                  $link = str_replace( '%_%', 1 == $n ? $empty_format : $format, $base );
 284                  $link = str_replace( '%#%', $n, $link );
 285                  $link = str_replace( '?&', '?', $link );
 286                  if ( $add_args )
 287                      $link = add_query_arg( $add_args, $link );
 288                  $link .= $add_fragment;
 289                  $page_links[] = '<a class="page-numbers" href="' . esc_url( $link ) . '" title="' . $n_display_title . '">' . $n_display . '</a>';
 290                  $dots = true;
 291              } elseif ( $dots && !$show_all ) {
 292                  $page_links[] = '<span class="page-numbers dots">&hellip;</span>';
 293                  $dots = false;
 294              }
 295          }
 296      }
 297      if ( $prev_next && $current && ( $current < $total || -1 == $total ) ) {
 298          $link = str_replace( '%_%', $format, $base );
 299          $link = str_replace( '%#%', $current + 1, $link );
 300          if ( $add_args )
 301              $link = add_query_arg( $add_args, $link );
 302          $link .= $add_fragment;
 303          $page_links[] = '<a class="next page-numbers" href="' . esc_url( $link ) . '" title="' . esc_attr( $next_title ) . '">' . $next_text . '</a>';
 304      }
 305      switch ( $type ) {
 306          case 'array':
 307              return $page_links;
 308              break;
 309          case 'list':
 310              $r .= '<ul class="page-numbers">' . "\n\t" . '<li>';
 311              $r .= join( '</li>' . "\n\t" . '<li>', $page_links );
 312              $r .= '</li>' . "\n" . '</ul>' . "\n";
 313              break;
 314          default:
 315              $r = join( "\n", $page_links );
 316              break;
 317      }
 318      return $r;
 319  }
 320  
 321  function bb_get_uri_page() {
 322      if ( isset($_GET['page']) && is_numeric($_GET['page']) && 1 < (int) $_GET['page'] )
 323          return (int) $_GET['page'];
 324  
 325      if ( isset($_SERVER['PATH_INFO']) )
 326          $path = $_SERVER['PATH_INFO'];
 327      else
 328          if ( !$path = strtok($_SERVER['REQUEST_URI'], '?') )
 329              return 1;
 330  
 331      if ( preg_match( '/^\/([0-9]+)\/?$/', $path, $matches ) ) {
 332          $page = (int) $matches[1];
 333          if ( 1 < $page ) {
 334              return $page;
 335          }
 336      }
 337  
 338      if ( $page = strstr($path, '/page/') ) {
 339          $page = (int) substr($page, 6);
 340          if ( 1 < $page )
 341              return $page;
 342      }
 343      return 1;
 344  }
 345  
 346  //expects $item = 1 to be the first, not 0
 347  function bb_get_page_number( $item, $per_page = 0 ) {
 348      if ( !$per_page )
 349          $per_page = bb_get_option('page_topics');
 350      return intval( ceil( $item / $per_page ) ); // page 1 is the first page
 351  }
 352  
 353  
 354  
 355  /* Time */
 356  
 357  function bb_timer_stop($display = 0, $precision = 3) { //if called like bb_timer_stop(1), will echo $timetotal
 358      global $bb_timestart, $timeend;
 359      $mtime = explode(' ', microtime());
 360      $timeend = $mtime[1] + $mtime[0];
 361      $timetotal = $timeend - $bb_timestart;
 362      if ($display)
 363          echo bb_number_format_i18n($timetotal, $precision);
 364      return bb_number_format_i18n($timetotal, $precision);
 365  }
 366  
 367  // GMT -> so many minutes ago
 368  function bb_since( $original, $args = '' )
 369  {
 370      $defaults = array(
 371          'levels'    => 1,
 372          'separator' => ', '
 373      );
 374  
 375      // $args used to be $do_more
 376      // $do_more = 0 is equivalent to $args['levels'] = 1
 377      // $do_more = 1 is equivalent to $args['levels'] = 2
 378      if ( !is_array( $args ) ) {
 379          $args = array(
 380              'levels' => abs( (integer) $args ) + 1
 381          );
 382      }
 383  
 384      $args = wp_parse_args( $args, $defaults );
 385      extract( $args, EXTR_SKIP );
 386  
 387      $today = (integer) time();
 388  
 389      if ( !is_numeric( $original ) ) {
 390          if ( $today < $_original = bb_gmtstrtotime( str_replace( ',', ' ', $original ) ) ) { // Looks like bb_since was called twice
 391              return $original;
 392          } else {
 393              $original = $_original;
 394          }
 395      }
 396  
 397      $seconds = $today - ( (integer) $original );
 398      if ( 0 === $seconds ) {
 399          return sprintf( _n( '%d second', '%d seconds', 0 ), 0 );
 400      }
 401  
 402      $levels = abs( (integer) $levels );
 403      if ( 0 === $levels ) {
 404          return '';
 405      }
 406  
 407      // array of time period chunks
 408      $chunks = array(
 409          ( 60 * 60 * 24 * 365 ), // years
 410          ( 60 * 60 * 24 * 30 ),  // months
 411          ( 60 * 60 * 24 * 7 ),   // weeks
 412          ( 60 * 60 * 24 ),       // days
 413          ( 60 * 60 ),            // hours
 414          ( 60 ),                 // minutes
 415          ( 1 )                   // seconds
 416      );
 417  
 418      $caught = 0;
 419      $parts = array();
 420      for ( $i = 0; $i < count( $chunks ); $i++ ) {
 421          if ( ( $count = floor( $seconds / $chunks[$i] ) ) || $caught ) {
 422              if ( $count ) {
 423                  $trans = array(
 424                      _n( '%d year', '%d years', $count ),
 425                      _n( '%d month', '%d months', $count ),
 426                      _n( '%d week', '%d weeks', $count ),
 427                      _n( '%d day', '%d days', $count ),
 428                      _n( '%d hour', '%d hours', $count ),
 429                      _n( '%d minute', '%d minutes', $count ),
 430                      _n( '%d second', '%d seconds', $count )
 431                  );
 432                  $parts[] = sprintf( $trans[$i], $count );
 433              }
 434              $caught++;
 435              $seconds = $seconds - ( $count * $chunks[$i] );
 436          }
 437          if ( $caught === $levels ) {
 438              break;
 439          }
 440      }
 441  
 442      if ( empty( $parts ) ) {
 443          return sprintf( _n( '%d second', '%d seconds', 0 ), 0 );
 444      }
 445  
 446      return join( $separator, $parts );
 447  }
 448  
 449  function bb_current_time( $type = 'timestamp' ) {
 450      return current_time( $type, true );
 451  }
 452  
 453  // GMT -> Local
 454  // in future versions this could eaily become a user option.
 455  function bb_offset_time( $time, $args = null ) {
 456      if ( isset($args['format']) && 'since' == $args['format'] )
 457          return $time;
 458      if ( !is_numeric($time) ) {
 459          if ( -1 !== $_time = bb_gmtstrtotime( $time ) )
 460              return gmdate('Y-m-d H:i:s', $_time + bb_get_option( 'gmt_offset' ) * 3600);
 461          else
 462              return $time; // Perhaps should return -1 here
 463      } else {
 464          return $time + bb_get_option( 'gmt_offset' ) * 3600;
 465      }
 466  }
 467  
 468  
 469  
 470  /* Permalinking / URLs / Paths */
 471  
 472  /**
 473   * BB_URI_CONTEXT_* - Bitwise definitions for bb_uri() and bb_get_uri() contexts
 474   *
 475   * @since 1.0
 476   */
 477  define( 'BB_URI_CONTEXT_NONE',                 0 );
 478  define( 'BB_URI_CONTEXT_HEADER',               1 );
 479  define( 'BB_URI_CONTEXT_TEXT',                 2 );
 480  define( 'BB_URI_CONTEXT_A_HREF',               4 );
 481  define( 'BB_URI_CONTEXT_FORM_ACTION',          8 );
 482  define( 'BB_URI_CONTEXT_IMG_SRC',              16 );
 483  define( 'BB_URI_CONTEXT_LINK_STYLESHEET_HREF', 32 );
 484  define( 'BB_URI_CONTEXT_LINK_ALTERNATE_HREF',  64 );
 485  define( 'BB_URI_CONTEXT_LINK_OTHER',           128 );
 486  define( 'BB_URI_CONTEXT_SCRIPT_SRC',           256 );
 487  define( 'BB_URI_CONTEXT_IFRAME_SRC',           512 );
 488  define( 'BB_URI_CONTEXT_BB_FEED',              1024 );
 489  define( 'BB_URI_CONTEXT_BB_USER_FORMS',        2048 );
 490  define( 'BB_URI_CONTEXT_BB_ADMIN',             4096 );
 491  define( 'BB_URI_CONTEXT_BB_XMLRPC',            8192 );
 492  define( 'BB_URI_CONTEXT_WP_HTTP_REQUEST',      16384 );
 493  //define( 'BB_URI_CONTEXT_*',                    32768 );  // Reserved for future definitions
 494  //define( 'BB_URI_CONTEXT_*',                    65536 );  // Reserved for future definitions
 495  //define( 'BB_URI_CONTEXT_*',                    131072 ); // Reserved for future definitions
 496  //define( 'BB_URI_CONTEXT_*',                    262144 ); // Reserved for future definitions
 497  define( 'BB_URI_CONTEXT_AKISMET',              524288 );
 498  
 499  /**
 500   * Echo a URI based on the URI setting
 501   *
 502   * @since 1.0
 503   *
 504   * @param $resource string The directory, may include a querystring
 505   * @param $query mixed The query arguments as a querystring or an associative array
 506   * @param $context integer The context of the URI, use BB_URI_CONTEXT_*
 507   * @return void
 508   */
 509  function bb_uri( $resource = null, $query = null, $context = BB_URI_CONTEXT_A_HREF )
 510  {
 511      echo apply_filters( 'bb_uri', bb_get_uri( $resource, $query, $context ), $resource, $query, $context );
 512  }
 513  
 514  /**
 515   * Return a URI based on the URI setting
 516   *
 517   * @since 1.0
 518   *
 519   * @param $resource string The directory, may include a querystring
 520   * @param $query mixed The query arguments as a querystring or an associative array
 521   * @param $context integer The context of the URI, use BB_URI_CONTEXT_*
 522   * @return string The complete URI
 523   */
 524  function bb_get_uri( $resource = null, $query = null, $context = BB_URI_CONTEXT_A_HREF )
 525  {
 526      // If there is a querystring in the resource then extract it
 527      if ( $resource && strpos( $resource, '?' ) !== false ) {
 528          list( $_resource, $_query ) = explode( '?', trim( $resource ), 2 );
 529          $resource = $_resource;
 530          $_query = wp_parse_args( $_query );
 531      } else {
 532          // Make sure $_query is an array for array_merge()
 533          $_query = array();
 534      }
 535  
 536      // $query can be an array as well as a string
 537      if ( $query ) {
 538          if ( is_string( $query ) ) {
 539              $query = ltrim( trim( $query ), '?' );
 540          }
 541          $query = wp_parse_args( $query );
 542      }
 543  
 544      // Make sure $query is an array for array_merge()
 545      if ( !$query ) {
 546          $query = array();
 547      }
 548  
 549      // Merge the queries into a single array
 550      $query = array_merge( $_query, $query );
 551  
 552      // Make sure context is an integer
 553      if ( !$context || !is_integer( $context ) ) {
 554          $context = BB_URI_CONTEXT_A_HREF;
 555      }
 556  
 557      // Get the base URI
 558      static $_uri;
 559      if( !isset( $_uri ) ) {
 560          $_uri = bb_get_option( 'uri' );
 561      }
 562      $uri = $_uri;
 563  
 564      // Use https?
 565      if (
 566          ( ( $context & BB_URI_CONTEXT_BB_USER_FORMS ) && force_ssl_login() ) // Force https when required on user forms
 567      ||
 568          ( ( $context & BB_URI_CONTEXT_BB_ADMIN ) && force_ssl_admin() ) // Force https when required in admin
 569      ) {
 570          static $_uri_ssl;
 571          if( !isset( $_uri_ssl ) ) {
 572              $_uri_ssl = bb_get_option( 'uri_ssl' );
 573          }
 574          $uri = $_uri_ssl;
 575      }
 576  
 577      // Add the directory
 578      $uri .= ltrim( $resource, '/' );
 579  
 580      // Add the query string to the URI
 581      $uri = add_query_arg( $query, $uri );
 582  
 583      return apply_filters( 'bb_get_uri', $uri, $resource, $context );
 584  }
 585  
 586  /**
 587   * Forces redirection to an SSL page when required
 588   *
 589   * @since 1.0
 590   *
 591   * @return void
 592   */
 593  function bb_ssl_redirect()
 594  {
 595      $page = bb_get_location();
 596  
 597      do_action( 'bb_ssl_redirect' );
 598  
 599      if ( BB_IS_ADMIN ) {
 600          if ( !force_ssl_admin() ) {
 601              return;
 602          }
 603      } else {
 604          switch ( $page ) {
 605              case 'login-page':
 606              case 'register-page':
 607                  if ( !force_ssl_login() ) {
 608                      return;
 609                  }
 610                  break;
 611              case 'profile-page':
 612                  global $self;
 613                  if ( $self == 'profile-edit.php' ) {
 614                      if ( !force_ssl_login() ) {
 615                          return;
 616                      }
 617                  } else {
 618                      return;
 619                  }
 620                  break;
 621              default:
 622                  return;
 623                  break;
 624          }
 625      }
 626  
 627      if ( is_ssl() ) {
 628          return;
 629      }
 630  
 631      $uri_ssl = parse_url( bb_get_option( 'uri_ssl' ) );
 632      $uri = $uri_ssl['scheme'] . '://' . $uri_ssl['host'] . $_SERVER['REQUEST_URI'];
 633      bb_safe_redirect( $uri );
 634      exit;
 635  }
 636  
 637  function bb_get_path( $level = 1, $base = false, $request = false ) {
 638      if ( !$request )
 639          $request = $_SERVER['REQUEST_URI'];
 640      if ( is_string($request) )
 641          $request = parse_url($request);
 642      if ( !is_array($request) || !isset($request['path']) )
 643          return '';
 644  
 645      $path = rtrim($request['path'], " \t\n\r\0\x0B/");
 646      if ( !$base )
 647          $base = rtrim(bb_get_option('path'), " \t\n\r\0\x0B/");
 648      $path = preg_replace('|' . preg_quote($base, '|') . '/?|','',$path,1);
 649      if ( !$path )
 650          return '';
 651      if ( strpos($path, '/') === false )
 652          return '';
 653  
 654      $url = explode('/',$path);
 655      if ( !isset($url[$level]) )
 656          return '';
 657  
 658      return urldecode($url[$level]);
 659  }
 660  
 661  function bb_find_filename( $text ) {
 662      if ( preg_match('|.*?/([a-z\-]+\.php)/?.*|', $text, $matches) )
 663          return $matches[1];
 664      else {
 665          $path = bb_get_option( 'path' );
 666          $text = preg_replace("#^$path#", '', $text);
 667          $text = preg_replace('#/.+$#', '', $text);
 668          return $text . '.php';
 669      }
 670      return false;
 671  }
 672  
 673  function bb_send_headers() {
 674      if ( bb_is_user_logged_in() )
 675          nocache_headers();
 676      @header('Content-Type: ' . bb_get_option( 'html_type' ) . '; charset=' . bb_get_option( 'charset' ));
 677      do_action( 'bb_send_headers' );
 678  }
 679  
 680  function bb_pingback_header() {
 681      if (bb_get_option('enable_pingback'))
 682          @header('X-Pingback: '. bb_get_uri('xmlrpc.php', null, BB_URI_CONTEXT_HEADER + BB_URI_CONTEXT_BB_XMLRPC));
 683  }
 684  
 685  // Inspired by and adapted from Yung-Lung Scott YANG's http://scott.yang.id.au/2005/05/permalink-redirect/ (GPL)
 686  function bb_repermalink() {
 687      global $page;
 688      $location = bb_get_location();
 689      $uri = $_SERVER['REQUEST_URI'];
 690      if ( isset($_GET['id']) )
 691          $id = $_GET['id'];
 692      else
 693          $id = bb_get_path();
 694      $_original_id = $id;
 695  
 696      do_action( 'pre_permalink', $id );
 697  
 698      $id = apply_filters( 'bb_repermalink', $id );
 699  
 700      switch ($location) {
 701          case 'front-page':
 702              $path = null;
 703              $querystring = null;
 704              if ($page > 1) {
 705                  if (bb_get_option( 'mod_rewrite' )) {
 706                      $path = 'page/' . $page;
 707                  } else {
 708                      $querystring = array('page' => $page);
 709                  }
 710              }
 711              $permalink = bb_get_uri($path, $querystring, BB_URI_CONTEXT_HEADER);
 712              $issue_404 = true;
 713              break;
 714          case 'forum-page':
 715              if (empty($id)) {
 716                  $permalink = bb_get_uri(null, null, BB_URI_CONTEXT_HEADER);
 717                  break;
 718              }
 719              global $forum_id, $forum;
 720              $forum     = bb_get_forum( $id );
 721              $forum_id  = $forum->forum_id;
 722              $permalink = get_forum_link( $forum->forum_id, $page );
 723              break;
 724          case 'topic-edit-page':
 725          case 'topic-page':
 726              if (empty($id)) {
 727                  $permalink = bb_get_uri(null, null, BB_URI_CONTEXT_HEADER);
 728                  break;
 729              }
 730              global $topic_id, $topic;
 731              $topic     = get_topic( $id );
 732              $topic_id  = $topic->topic_id;
 733              $permalink = get_topic_link( $topic->topic_id, $page );
 734              break;
 735          case 'profile-page': // This handles the admin side of the profile as well.
 736              global $user_id, $user, $profile_hooks, $self;
 737              if ( isset($_GET['id']) )
 738                  $id = $_GET['id'];
 739              elseif ( isset($_GET['username']) )
 740                  $id = $_GET['username'];
 741              else
 742                  $id = bb_get_path();
 743              $_original_id = $id;
 744              
 745              if ( !$id ) {
 746                  $user = bb_get_current_user(); // Attempt to go to the current users profile
 747              } else {
 748                  if ( bb_get_option( 'mod_rewrite' ) === 'slugs') {
 749                      if ( !$user = bb_get_user_by_nicename( $id ) ) {
 750                          $user = bb_get_user( $id );
 751                      }
 752                  } else {
 753                      if ( !$user = bb_get_user( $id ) ) {
 754                          $user = bb_get_user_by_nicename( $id );
 755                      }
 756                  }
 757              }
 758  
 759              if ( !$user || ( 1 == $user->user_status && !bb_current_user_can( 'moderate' ) ) )
 760                  bb_die(__('User not found.'), '', 404);
 761  
 762              $user_id = $user->ID;
 763              bb_global_profile_menu_structure();
 764              $valid = false;
 765              if ( $tab = isset($_GET['tab']) ? $_GET['tab'] : bb_get_path(2) ) {
 766                  foreach ( $profile_hooks as $valid_tab => $valid_file ) {
 767                      if ( $tab == $valid_tab ) {
 768                          $valid = true;
 769                          $self = $valid_file;
 770                      }
 771                  }
 772              }
 773              if ( $valid ) {
 774                  $permalink = get_profile_tab_link( $user->ID, $tab, $page );
 775              } else {
 776                  $permalink = get_user_profile_link( $user->ID, $page );
 777                  unset($self, $tab);
 778              }
 779              break;
 780          case 'favorites-page':
 781              $permalink = get_favorites_link();
 782              break;
 783          case 'tag-page': // It's not an integer and tags.php pulls double duty.
 784              $id = ( isset($_GET['tag']) ) ? $_GET['tag'] : false;
 785              if ( ! $id || ! bb_get_tag( (string) $id ) )
 786                  $permalink = bb_get_tag_page_link();
 787              else {
 788                  global $tag, $tag_name;
 789                  $tag_name = $id;
 790                  $tag = bb_get_tag( (string) $id );
 791                  $permalink = bb_get_tag_link( 0, $page ); // 0 => grabs $tag from global.
 792              }
 793              break;
 794          case 'view-page': // Not an integer
 795              if ( isset($_GET['view']) )
 796                  $id = $_GET['view'];
 797              else
 798                  $id = bb_get_path();
 799              $_original_id = $id;
 800              global $view;
 801              $view = $id;
 802              $permalink = get_view_link( $view, $page );
 803              break;
 804          default:
 805              return;
 806              break;
 807      }
 808      
 809      wp_parse_str($_SERVER['QUERY_STRING'], $args);
 810      $args = urlencode_deep($args);
 811      if ( $args ) {
 812          $permalink = add_query_arg($args, $permalink);
 813          if ( bb_get_option('mod_rewrite') ) {
 814              $pretty_args = array('id', 'page', 'tag', 'tab', 'username'); // these are already specified in the path
 815              if ( $location == 'view-page' )
 816                  $pretty_args[] = 'view';
 817              foreach ( $pretty_args as $pretty_arg )
 818                  $permalink = remove_query_arg( $pretty_arg, $permalink );
 819          }
 820      }
 821  
 822      $permalink = apply_filters( 'bb_repermalink_result', $permalink, $location );
 823  
 824      $domain = bb_get_option('domain');
 825      $domain = preg_replace('/^https?/', '', $domain);
 826      $check = preg_replace( '|^.*' . trim($domain, ' /' ) . '|', '', $permalink, 1 );
 827      $uri = rtrim( $uri, " \t\n\r\0\x0B?" );
 828      $uri = str_replace( '/index.php', '/', $uri );
 829  
 830      global $bb_log;
 831      $bb_log->debug($uri, 'bb_repermalink() ' . __('REQUEST_URI'));
 832      $bb_log->debug($check, 'bb_repermalink() ' . __('should be'));
 833      $bb_log->debug($permalink, 'bb_repermalink() ' . __('full permalink'));
 834      $bb_log->debug(isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : null, 'bb_repermalink() ' . __('PATH_INFO'));
 835  
 836      if ( $check != $uri && $check != str_replace(urlencode($_original_id), $_original_id, $uri) ) {
 837          if ( $issue_404 && rtrim( $check, " \t\n\r\0\x0B/" ) !== rtrim( $uri, " \t\n\r\0\x0B/" ) ) {
 838              status_header( 404 );
 839              bb_load_template( '404.php' );
 840          } else {
 841              wp_redirect( $permalink );
 842          }
 843          exit;
 844      }
 845  
 846      do_action( 'post_permalink', $permalink );
 847  }
 848  
 849  /* Profile/Admin */
 850  
 851  function bb_global_profile_menu_structure() {
 852      global $user_id, $profile_menu, $profile_hooks;
 853      // Menu item name
 854      // The capability required for own user to view the tab ('' to allow non logged in access)
 855      // The capability required for other users to view the tab ('' to allow non logged in access)
 856      // The URL of the item's file
 857      // Item name for URL (nontranslated)
 858      $profile_menu[0] = array(__('Edit'), 'edit_profile', 'edit_users', 'profile-edit.php', 'edit');
 859      $profile_menu[5] = array(__('Favorites'), '', '', 'favorites.php', 'favorites');
 860  
 861      // Create list of page plugin hook names the current user can access
 862      $profile_hooks = array();
 863      foreach ($profile_menu as $profile_tab)
 864          if ( bb_can_access_tab( $profile_tab, bb_get_current_user_info( 'id' ), $user_id ) )
 865              $profile_hooks[bb_sanitize_with_dashes($profile_tab[4])] = $profile_tab[3];
 866  
 867      do_action('bb_profile_menu');
 868      ksort($profile_menu);
 869  }
 870  
 871  function bb_add_profile_tab($tab_title, $users_cap, $others_cap, $file, $arg = false) {
 872      global $profile_menu, $profile_hooks, $user_id;
 873  
 874      $arg = $arg ? $arg : $tab_title;
 875  
 876      $profile_tab = array($tab_title, $users_cap, $others_cap, $file, $arg);
 877      $profile_menu[] = $profile_tab;
 878      if ( bb_can_access_tab( $profile_tab, bb_get_current_user_info( 'id' ), $user_id ) )
 879          $profile_hooks[bb_sanitize_with_dashes($arg)] = $file;
 880  }
 881  
 882  function bb_can_access_tab( $profile_tab, $viewer_id, $owner_id ) {
 883      global $bb_current_user;
 884      $viewer_id = (int) $viewer_id;
 885      $owner_id = (int) $owner_id;
 886      if ( $viewer_id == bb_get_current_user_info( 'id' ) )
 887          $viewer =& $bb_current_user;
 888      else
 889          $viewer = new BP_User( $viewer_id );
 890      if ( !$viewer )
 891          return '' === $profile_tab[2];
 892  
 893      if ( $owner_id == $viewer_id ) {
 894          if ( '' === $profile_tab[1] )
 895              return true;
 896          else
 897              return $viewer->has_cap($profile_tab[1]);
 898      } else {
 899          if ( '' === $profile_tab[2] )
 900              return true;
 901          else
 902              return $viewer->has_cap($profile_tab[2]);
 903      }
 904  }
 905  
 906  //meta_key => (required?, Label, hCard property).  Don't use user_{anything} as the name of your meta_key.
 907  function bb_get_profile_info_keys( $context = null ) {
 908      return apply_filters( 'get_profile_info_keys', array(
 909          'first_name' => array(0, __('First name')),
 910          'last_name' => array(0, __('Last name')),
 911          'display_name' => array(1, __('Display name as')),
 912          'user_email' => array(1, __('Email'), 'email'),
 913          'user_url' => array(0, __('Website'), 'url'),
 914          'from' => array(0, __('Location')),
 915          'occ' => array(0, __('Occupation'), 'role'),
 916          'interest' => array(0, __('Interests')),
 917      ), $context );
 918  }
 919  
 920  function bb_get_profile_admin_keys( $context = null ) {
 921      global $bbdb;
 922      return apply_filters( 'get_profile_admin_keys', array(
 923          $bbdb->prefix . 'title' => array(0, __('Custom Title'))
 924      ), $context );
 925  }
 926  
 927  function bb_get_assignable_caps() {
 928      $caps = array();
 929      if ( $throttle_time = bb_get_option( 'throttle_time' ) )
 930          $caps['throttle'] = sprintf( __('Ignore the %d second post throttling limit'), $throttle_time );
 931      return apply_filters( 'get_assignable_caps', $caps );
 932  }
 933  
 934  /* Views */
 935  
 936  function bb_get_views() {
 937      global $bb_views;
 938  
 939      $views = array();
 940      foreach ( (array) $bb_views as $view => $array )
 941          $views[$view] = $array['title'];
 942  
 943      return $views;
 944  }
 945  
 946  function bb_register_view( $view, $title, $query_args = '', $feed = TRUE ) {
 947      global $bb_views;
 948  
 949      $view  = bb_slug_sanitize( $view );
 950      $title = esc_html( $title );
 951  
 952      if ( !$view || !$title )
 953          return false;
 954  
 955      $query_args = wp_parse_args( $query_args );
 956  
 957      if ( !$sticky_set = isset($query_args['sticky']) )
 958          $query_args['sticky'] = 'no';
 959  
 960      $bb_views[$view]['title']  = $title;
 961      $bb_views[$view]['query']  = $query_args;
 962      $bb_views[$view]['sticky'] = !$sticky_set; // No sticky set => split into stickies and not
 963      $bb_views[$view]['feed'] = $feed;
 964      return $bb_views[$view];
 965  }
 966  
 967  function bb_deregister_view( $view ) {
 968      global $bb_views;
 969  
 970      $view = bb_slug_sanitize( $view );
 971      if ( !isset($bb_views[$view]) )
 972          return false;
 973  
 974      unset($GLOBALS['bb_views'][$view]);
 975      return true;
 976  }
 977  
 978  function bb_view_query( $view, $new_args = '' ) {
 979      global $bb_views;
 980  
 981      $view = bb_slug_sanitize( $view );
 982      if ( !isset($bb_views[$view]) )
 983          return false;
 984  
 985      if ( $new_args ) {
 986          $new_args = wp_parse_args( $new_args );
 987          $query_args = array_merge( $bb_views[$view]['query'], $new_args );
 988      } else {
 989          $query_args = $bb_views[$view]['query'];
 990      }
 991  
 992      return new BB_Query( 'topic', $query_args, "bb_view_$view" );
 993  }
 994  
 995  function bb_get_view_query_args( $view ) {
 996      global $bb_views;
 997  
 998      $view = bb_slug_sanitize( $view );
 999      if ( !isset($bb_views[$view]) )
1000          return false;
1001  
1002      return $bb_views[$view]['query'];
1003  }
1004  
1005  function bb_register_default_views() {
1006      // no posts (besides the first one), older than 2 hours
1007      bb_register_view( 'no-replies', __('Topics with no replies'), array( 'post_count' => 1, 'started' => '<' . gmdate( 'YmdH', time() - 7200 ) ) );
1008      bb_register_view( 'untagged'  , __('Topics with no tags')   , array( 'tag_count'  => 0 ) );
1009  }
1010  
1011  /* Feeds */
1012  
1013  /**
1014   * Send status headers for clients supporting Conditional Get
1015   *
1016   * The function sends the Last-Modified and ETag headers for all clients. It
1017   * then checks both the If-None-Match and If-Modified-Since headers to see if
1018   * the client has used them. If so, and the ETag does matches the client ETag
1019   * or the last modified date sent by the client is newer or the same as the
1020   * generated last modified, the function sends a 304 Not Modified and exits.
1021   *
1022   * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
1023   * @param string $bb_last_modified Last modified time. Must be a HTTP-date
1024   */
1025  function bb_send_304( $bb_last_modified ) {
1026      $bb_etag = '"' . md5($bb_last_modified) . '"';
1027      @header("Last-Modified: $bb_last_modified");
1028      @header("ETag: $bb_etag");
1029  
1030      // Support for Conditional GET
1031      if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) $client_etag = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);
1032      else $client_etag = false;
1033  
1034      $client_last_modified = trim( $_SERVER['HTTP_IF_MODIFIED_SINCE']);
1035      // If string is empty, return 0. If not, attempt to parse into a timestamp
1036      $client_modified_timestamp = $client_last_modified ? bb_gmtstrtotime($client_last_modified) : 0;
1037  
1038      // Make a timestamp for our most recent modification...    
1039      $bb_modified_timestamp = bb_gmtstrtotime($bb_last_modified);
1040  
1041      if ( ($client_last_modified && $client_etag) ?
1042           (($client_modified_timestamp >= $bb_modified_timestamp) && ($client_etag == $bb_etag)) :
1043           (($client_modified_timestamp >= $bb_modified_timestamp) || ($client_etag == $bb_etag)) ) {
1044          status_header( 304 );
1045          exit;
1046      }
1047  }
1048  
1049  /* Nonce */
1050  
1051  /**
1052   * Retrieve URL with nonce added to URL query.
1053   *
1054   * @package bbPress
1055   * @subpackage Security
1056   * @since 1.0
1057   *
1058   * @param string $actionurl URL to add nonce action
1059   * @param string $action Optional. Nonce action name
1060   * @return string URL with nonce action added.
1061   */
1062  function bb_nonce_url( $actionurl, $action = -1 ) {
1063      $actionurl = str_replace( '&amp;', '&', $actionurl );
1064      $nonce = bb_create_nonce( $action );
1065      return esc_html( add_query_arg( '_wpnonce', $nonce, $actionurl ) );
1066  }
1067  
1068  /**
1069   * Retrieve or display nonce hidden field for forms.
1070   *
1071   * The nonce field is used to validate that the contents of the form came from
1072   * the location on the current site and not somewhere else. The nonce does not
1073   * offer absolute protection, but should protect against most cases. It is very
1074   * important to use nonce field in forms.
1075   *
1076   * If you set $echo to true and set $referer to true, then you will need to
1077   * retrieve the {@link wp_referer_field() wp referer field}. If you have the
1078   * $referer set to true and are echoing the nonce field, it will also echo the
1079   * referer field.
1080   *
1081   * The $action and $name are optional, but if you want to have better security,
1082   * it is strongly suggested to set those two parameters. It is easier to just
1083   * call the function without any parameters, because validation of the nonce
1084   * doesn't require any parameters, but since crackers know what the default is
1085   * it won't be difficult for them to find a way around your nonce and cause
1086   * damage.
1087   *
1088   * The input name will be whatever $name value you gave. The input value will be
1089   * the nonce creation value.
1090   *
1091   * @package bbPress
1092   * @subpackage Security
1093   * @since 1.0
1094   *
1095   * @param string $action Optional. Action name.
1096   * @param string $name Optional. Nonce name.
1097   * @param bool $referer Optional, default true. Whether to set the referer field for validation.
1098   * @param bool $echo Optional, default true. Whether to display or return hidden form field.
1099   * @return string Nonce field.
1100   */
1101  function bb_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
1102      $name = esc_attr( $name );
1103      $nonce = bb_create_nonce( $action );
1104      $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . $nonce . '" />';
1105      if ( $echo )
1106          echo $nonce_field;
1107  
1108      if ( $referer )
1109          wp_referer_field( $echo, 'previous' );
1110  
1111      return $nonce_field;
1112  }
1113  
1114  function bb_nonce_ays( $action )
1115  {
1116      $title = __( 'bbPress Failure Notice' );
1117      $html .= "\t<div id='message' class='updated fade'>\n\t<p>" . esc_html( bb_explain_nonce( $action ) ) . "</p>\n\t<p>";
1118      if ( wp_get_referer() )
1119          $html .= "<a href='" . remove_query_arg( 'updated', esc_url( wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
1120      $html .= "</p>\n\t</div>\n";
1121      $html .= "</body>\n</html>";
1122      bb_die( $html, $title );
1123  }
1124  
1125  function bb_install_header( $title = '', $header = false, $logo = false )
1126  {
1127      if ( empty($title) )
1128          if ( function_exists('__') )
1129              $title = __('bbPress');
1130          else
1131              $title = 'bbPress';
1132          
1133          $uri = false;
1134          if ( function_exists('bb_get_uri') && !BB_INSTALLING ) {
1135              $uri = bb_get_uri();
1136              $uri_stylesheet = bb_get_uri('bb-admin/install.css', null, BB_URI_CONTEXT_LINK_STYLESHEET_HREF + BB_URI_CONTEXT_BB_INSTALLER);
1137              $uri_stylesheet_rtl = bb_get_uri('bb-admin/install-rtl.css', null, BB_URI_CONTEXT_LINK_STYLESHEET_HREF + BB_URI_CONTEXT_BB_INSTALLER);
1138              $uri_logo = bb_get_uri('bb-admin/images/bbpress-logo.png', null, BB_URI_CONTEXT_IMG_SRC + BB_URI_CONTEXT_BB_INSTALLER);
1139          }
1140          
1141          if (!$uri) {
1142              $uri = preg_replace('|(/bb-admin)?/[^/]+?$|', '/', $_SERVER['PHP_SELF']);
1143              $uri_stylesheet = $uri . 'bb-admin/install.css';
1144              $uri_stylesheet_rtl = $uri . 'bb-admin/install-rtl.css';
1145              $uri_logo = $uri . 'bb-admin/images/bbpress-logo.png';
1146          }
1147      
1148      header('Content-Type: text/html; charset=utf-8');
1149  ?>
1150  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1151  <html xmlns="http://www.w3.org/1999/xhtml"<?php if ( function_exists( 'bb_language_attributes' ) ) bb_language_attributes(); ?>>
1152  <head>
1153      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1154      <title><?php echo $title; ?></title>
1155      <meta name="robots" content="noindex, nofollow" />
1156      <link rel="stylesheet" href="<?php echo $uri_stylesheet; ?>" type="text/css" />
1157  <?php
1158      if ( function_exists( 'bb_get_option' ) && 'rtl' == bb_get_option( 'text_direction' ) ) {
1159  ?>
1160      <link rel="stylesheet" href="<?php echo $uri_stylesheet_rtl; ?>" type="text/css" />
1161  <?php
1162      }
1163  ?>
1164  </head>
1165  <body>
1166      <div id="container">
1167  <?php
1168      if ( $logo ) {
1169  ?>
1170          <div class="logo">
1171              <img src="<?php echo $uri_logo; ?>" alt="bbPress" />
1172          </div>
1173  <?php
1174      }
1175  
1176      if ( !empty($header) ) {
1177  ?>
1178          <h1>
1179              <?php echo $header; ?>
1180          </h1>
1181  <?php
1182      }
1183  }
1184  
1185  function bb_install_footer() {
1186  ?>
1187      </div>
1188  </body>
1189  </html>
1190  <?php
1191  }
1192  
1193  function bb_die( $message, $title = '', $header = 0 ) {
1194      global $bb_locale;
1195  
1196      if ( $header && !headers_sent() )
1197          status_header( $header );
1198  
1199      if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
1200          if ( empty( $title ) ) {
1201              $error_data = $message->get_error_data();
1202              if ( is_array( $error_data ) && isset( $error_data['title'] ) )
1203                  $title = $error_data['title'];
1204          }
1205          $errors = $message->get_error_messages();
1206          switch ( count( $errors ) ) :
1207          case 0 :
1208              $message = '';
1209              break;
1210          case 1 :
1211              $message = "<p>{$errors[0]}</p>";
1212              break;
1213          default :
1214              $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
1215              break;
1216          endswitch;
1217      } elseif ( is_string( $message ) ) {
1218          $message = bb_autop( $message );
1219      }
1220  
1221      if ( empty($title) )
1222          $title = __('bbPress &rsaquo; Error');
1223      
1224      bb_install_header( $title );
1225  ?>
1226      <?php echo $message; ?>
1227  <?php
1228      if ($uri = bb_get_uri()) {
1229  ?>
1230      <p class="last"><?php printf( __('Back to <a href="%s">%s</a>.'), $uri, bb_get_option( 'name' ) ); ?></p>
1231  <?php
1232      }
1233      bb_install_footer();
1234      die();
1235  }
1236  
1237  function bb_explain_nonce($action) {
1238      if ( $action !== -1 && preg_match('/([a-z]+)-([a-z]+)(_(.+))?/', $action, $matches) ) {
1239          $verb = $matches[1];
1240          $noun = $matches[2];
1241  
1242          $trans = array();
1243          $trans['create']['post'] = array(__('Your attempt to submit this post has failed.'), false);
1244          $trans['edit']['post'] = array(__('Your attempt to edit this post has failed.'), false);
1245          $trans['delete']['post'] = array(__('Your attempt to delete this post has failed.'), false);
1246  
1247          $trans['create']['topic'] = array(__('Your attempt to create this topic has failed.'), false);
1248          $trans['resolve']['topic'] = array(__('Your attempt to change the resolution status of this topic has failed.'), false);
1249          $trans['delete']['topic'] = array(__('Your attempt to delete this topic has failed.'), false);
1250          $trans['close']['topic'] = array(__('Your attempt to change the status of this topic has failed.'), false);
1251          $trans['stick']['topic'] = array(__('Your attempt to change the sticky status of this topic has failed.'), false);
1252          $trans['move']['topic'] = array(__('Your attempt to move this topic has failed.'), false);
1253  
1254          $trans['add']['tag'] = array(__('Your attempt to add this tag to this topic has failed.'), false);
1255          $trans['rename']['tag'] = array(__('Your attempt to rename this tag has failed.'), false);
1256          $trans['merge']['tag'] = array(__('Your attempt to submit these tags has failed.'), false);
1257          $trans['destroy']['tag'] = array(__('Your attempt to destroy this tag has failed.'), false);
1258          $trans['remove']['tag'] = array(__('Your attempt to remove this tag from this topic has failed.'), false);
1259  
1260          $trans['toggle']['favorite'] = array(__('Your attempt to toggle your favorite status for this topic has failed.'), false);
1261  
1262          $trans['edit']['profile'] = array(__("Your attempt to edit this user's profile has failed."), false);
1263  
1264          $trans['add']['forum'] = array(__("Your attempt to add this forum has failed."), false);
1265          $trans['update']['forums'] = array(__("Your attempt to update your forums has failed."), false);
1266          $trans['delete']['forums'] = array(__("Your attempt to delete that forum has failed."), false);
1267  
1268          $trans['do']['counts'] = array(__("Your attempt to recount these items has failed."), false);
1269  
1270          $trans['switch']['theme'] = array(__("Your attempt to switch themes has failed."), false);
1271  
1272          if ( isset($trans[$verb][$noun]) ) {
1273              if ( !empty($trans[$verb][$noun][1]) ) {
1274                  $lookup = $trans[$verb][$noun][1];
1275                  $object = $matches[4];
1276                  if ( 'use_id' != $lookup )
1277                      $object = call_user_func($lookup, $object);
1278                  return sprintf($trans[$verb][$noun][0], esc_html( $object ));
1279              } else {
1280                  return $trans[$verb][$noun][0];
1281              }
1282          }
1283      }
1284  
1285      return apply_filters( 'bb_explain_nonce_' . $verb . '-' . $noun, __('Your attempt to do this has failed.'), $matches[4] );
1286  }
1287  
1288  /* DB Helpers */
1289  
1290  function bb_count_last_query( $query = '' ) {
1291      global $bbdb, $bb_last_countable_query;
1292  
1293      if ( $query )
1294          $q = $query;
1295      elseif ( $bb_last_countable_query )
1296          $q = $bb_last_countable_query;
1297      else
1298          $q = $bbdb->last_query;
1299  
1300      if ( false === strpos($q, 'SELECT') )
1301          return false;
1302  
1303      if ( false !== strpos($q, 'SQL_CALC_FOUND_ROWS') )
1304          return (int) $bbdb->get_var( "SELECT FOUND_ROWS()" );
1305  
1306      $q_original = $q;
1307  
1308      $q = preg_replace(
1309          array('/SELECT.*?\s+FROM/', '/LIMIT [0-9]+(\s*,\s*[0-9]+)?/', '/ORDER BY\s+.*$/', '/DESC/', '/ASC/'),
1310          array('SELECT COUNT(*) FROM', ''),
1311          $q
1312      );
1313  
1314      if ( preg_match( '/GROUP BY\s+(\S+)/', $q, $matches ) )
1315          $q = str_replace( array( 'COUNT(*)', $matches[0] ), array( "COUNT(DISTINCT $matches[1])", '' ), $q );
1316  
1317      if ( !$query )
1318          $bb_last_countable_query = '';
1319  
1320      $q = apply_filters( 'bb_count_last_query', $q, $q_original );
1321  
1322      return (int) $bbdb->get_var($q);
1323  }
1324  
1325  function bb_no_where( $where ) {
1326      return;
1327  }
1328  
1329  /* Plugins/Themes utility */
1330  
1331  function bb_basename( $file, $directories )
1332  {
1333      if ( strpos( $file, '#' ) !== false ) {
1334          return $file; // It's already a basename
1335      }
1336  
1337      foreach ( $directories as $type => $directory ) {
1338          if ( strpos( $file, $directory ) !== false ) {
1339              break; // Keep the $file and $directory set and use them below, nifty huh?
1340          }
1341      }
1342  
1343      list( $file, $directory ) = str_replace( '\\','/', array( $file, $directory ) );
1344      list( $file, $directory ) = preg_replace( '|/+|','/', array( $file,$directory ) );
1345      $file = preg_replace( '|^.*' . preg_quote( $directory, '|' ) . '|', $type . '#', $file );
1346  
1347      return $file;
1348  }
1349  
1350  /* Plugins */
1351  
1352  function bb_plugin_basename( $file )
1353  {
1354      global $bb;
1355      $directories = array();
1356      foreach ( $bb->plugin_locations as $_name => $_data ) {
1357          $directories[$_name] = $_data['dir'];
1358      }
1359      return bb_basename( $file, $directories );
1360  }
1361  
1362  function bb_register_plugin_activation_hook( $file, $function )
1363  {
1364      $file = bb_plugin_basename( $file );
1365      add_action( 'bb_activate_plugin_' . $file, $function );
1366  }
1367  
1368  function bb_register_plugin_deactivation_hook( $file, $function )
1369  {
1370      $file = bb_plugin_basename( $file );
1371      add_action( 'bb_deactivate_plugin_' . $file, $function );
1372  }
1373  
1374  function bb_get_plugin_uri( $plugin = false )
1375  {
1376      global $bb;
1377      if ( preg_match( '/^([a-z0-9_-]+)#((?:[a-z0-9\/\\_-]+.)+)(php)$/i', $plugin, $_matches ) ) {
1378          $plugin_uri = $bb->plugin_locations[$_matches[1]]['url'] . $_matches[2] . $_matches[3];
1379          $plugin_uri = dirname( $plugin_uri ) . '/';
1380      } else {
1381          $plugin_uri = $bb->plugin_locations['core']['url'];
1382      }
1383      return apply_filters( 'bb_get_plugin_uri', $plugin_uri, $plugin );
1384  }
1385  
1386  function bb_get_plugin_directory( $plugin = false, $path = false )
1387  {
1388      global $bb;
1389      if ( preg_match( '/^([a-z0-9_-]+)#((?:[a-z0-9\/\\_-]+.)+)(php)$/i', $plugin, $_matches ) ) {
1390          $plugin_directory = $bb->plugin_locations[$_matches[1]]['dir'] . $_matches[2] . $_matches[3];
1391          if ( !$path ) {
1392              $plugin_directory = dirname( $plugin_directory ) . '/';
1393          }
1394      } else {
1395          $plugin_directory = $bb->plugin_locations['core']['dir'];
1396      }
1397      return apply_filters( 'bb_get_plugin_directory', $plugin_directory, $plugin, $path );
1398  }
1399  
1400  function bb_get_plugin_path( $plugin = false )
1401  {
1402      $plugin_path = bb_get_plugin_directory( $plugin, true );
1403      return apply_filters( 'bb_get_plugin_path', $plugin_path, $plugin );
1404  }
1405  
1406  /* Themes / Templates */
1407  
1408  function bb_get_active_theme_directory()
1409  {
1410      return apply_filters( 'bb_get_active_theme_directory', bb_get_theme_directory() );
1411  }
1412  
1413  function bb_get_theme_directory( $theme = false )
1414  {
1415      global $bb;
1416      if ( !$theme ) {
1417          $theme = bb_get_option( 'bb_active_theme' );
1418      }
1419      if ( preg_match( '/^([a-z0-9_-]+)#([\.a-z0-9_-]+)$/i', $theme, $_matches ) ) {
1420          $theme_directory = $bb->theme_locations[$_matches[1]]['dir'] . $_matches[2] . '/';
1421      } else {
1422          $theme_directory = BB_DEFAULT_THEME_DIR;
1423      }
1424      return $theme_directory;
1425  }
1426  
1427  function bb_get_themes()
1428  {
1429      $r = array();
1430      global $bb;
1431      foreach ( $bb->theme_locations as $_name => $_data ) {
1432          if ( $themes_dir = @dir( $_data['dir'] ) ) {
1433              while( ( $theme_dir = $themes_dir->read() ) !== false ) {
1434                  if ( is_file( $_data['dir'] . $theme_dir . '/style.css' ) && is_readable( $_data['dir'] . $theme_dir . '/style.css' ) && '.' != $theme_dir{0} ) {
1435                      $r[$_name . '#' . $theme_dir] = $_name . '#' . $theme_dir;
1436                  }
1437              }
1438          }
1439      }
1440      ksort( $r );
1441      return $r;
1442  }
1443  
1444  function bb_theme_basename( $file )
1445  {
1446      global $bb;
1447      $directories = array();
1448      foreach ( $bb->theme_locations as $_name => $_data ) {
1449          $directories[$_name] = $_data['dir'];
1450      }
1451      $file = bb_basename( $file, $directories );
1452      $file = preg_replace( '|/+.*|', '', $file );
1453      return $file;
1454  }
1455  
1456  function bb_register_theme_activation_hook( $file, $function )
1457  {
1458      $file = bb_theme_basename( $file );
1459      add_action( 'bb_activate_theme_' . $file, $function );
1460  }
1461  
1462  function bb_register_theme_deactivation_hook( $file, $function )
1463  {
1464      $file = bb_theme_basename( $file );
1465      add_action( 'bb_deactivate_theme_' . $file, $function );
1466  }
1467  
1468  /* Search Functions */
1469  // NOT bbdb::prepared
1470  function bb_user_search( $args = '' ) {
1471      global $bbdb, $bb_last_countable_query;
1472  
1473      if ( $args && is_string( $args ) && false === strpos( $args, '=' ) ) {
1474          $args = array( 'query' => $args );
1475      }
1476  
1477      $defaults = array(
1478          'query' => '',
1479          'append_meta' => true,
1480          'user_login' => true,
1481          'display_name' => true,
1482          'user_nicename' => false,
1483          'user_url' => true,
1484          'user_email' => false,
1485          'user_meta' => false,
1486          'users_per_page' => false,
1487          'page' => false,
1488          'roles' => false
1489      );
1490  
1491      $args = wp_parse_args( $args, $defaults );
1492      extract( $args, EXTR_SKIP );
1493  
1494      $query = trim( $query );
1495      if ( $query && strlen( preg_replace( '/[^a-z0-9]/i', '', $query ) ) < 3 ) {
1496          return new WP_Error( 'invalid-query', __('Your search term was too short') );
1497      }
1498      $query = $bbdb->escape( $query );
1499  
1500      if ( !$page ) {
1501          $page = $GLOBALS['page'];
1502      }
1503      $page = (int) $page;
1504  
1505      $limit = 0 < (int) $users_per_page ? (int) $users_per_page : bb_get_option( 'page_topics' );
1506      if ( 1 < $page ) {
1507          $limit = ($limit * ($page - 1)) . ", $limit";
1508      }
1509  
1510      $likeit = preg_replace( '/\s+/', '%', like_escape( $query ) );
1511  
1512      $fields = array();
1513      foreach ( array( 'user_login', 'display_name', 'user_nicename', 'user_url', 'user_email' ) as $field ) {
1514          if ( $$field ) {
1515              $fields[] = $field;
1516          }
1517      }
1518  
1519      if ( $roles ) {
1520          $roles = (array) $roles;
1521      }
1522  
1523      if ( $roles && !empty( $roles ) && false === $role_user_ids = apply_filters( 'bb_user_search_role_user_ids', false, $roles, $args ) ) {
1524          $role_meta_key = $bbdb->escape( $bbdb->prefix . 'capabilities' );
1525          $role_sql_terms = array();
1526          foreach ( $roles as $role ) {
1527              $role_sql_terms[] = "`meta_value` LIKE '%" . $bbdb->escape( like_escape( $role ) ) . "%'";
1528          }
1529          $role_sql_terms = join( ' OR ', $role_sql_terms );
1530          $role_sql = "SELECT `user_id` FROM `$bbdb->usermeta` WHERE `meta_key` = '$role_meta_key' AND ($role_sql_terms);";
1531          $role_user_ids = $bbdb->get_col( $role_sql, 0 );
1532          if ( is_wp_error( $role_user_ids ) ) {
1533              return false;
1534          }
1535      }
1536  
1537      if ( is_array( $role_user_ids ) && empty( $role_user_ids ) ) {
1538          return false;
1539      }
1540  
1541      if ( $query && $user_meta && false === $meta_user_ids = apply_filters( 'bb_user_search_meta_user_ids', false, $args ) ) {
1542          $meta_sql = "SELECT `user_id` FROM `$bbdb->usermeta` WHERE `meta_value` LIKE ('%$likeit%')";
1543          if ( empty( $fields ) ) {
1544              $meta_sql .= " LIMIT $limit";
1545          }
1546          $meta_user_ids = $bbdb->get_col( $meta_sql, 0 );
1547          if ( is_wp_error( $meta_user_ids ) ) {
1548              $meta_user_ids = false;
1549          }
1550      }
1551  
1552      $user_ids = array();
1553      if ( $role_user_ids && $meta_user_ids ) {
1554          $user_ids = array_intersect( (array) $role_user_ids, (array) $meta_user_ids );
1555      } elseif ( $role_user_ids ) {
1556          $user_ids = (array) $role_user_ids;
1557      } elseif ( $meta_user_ids ) {
1558          $user_ids = (array) $meta_user_ids;
1559      }
1560  
1561      $sql = "SELECT * FROM $bbdb->users";
1562  
1563      $sql_terms = array();
1564      if ( $query && count( $fields ) ) {
1565          foreach ( $fields as $field ) {
1566              $sql_terms[] = "$field LIKE ('%$likeit%')";
1567          }
1568      }
1569  
1570      $user_ids_sql = '';
1571      if ( $user_ids ) {
1572          $user_ids_sql = "AND ID IN (". join(',', $user_ids) . ")";
1573      }
1574  
1575      if ( $query && empty( $sql_terms ) ) {
1576          return new WP_Error( 'invalid-query', __( 'Your query parameters are invalid' ) );
1577      }
1578  
1579      if ( count( $sql_terms ) || count( $user_ids ) ) {
1580          $sql .= ' WHERE ';
1581      }
1582  
1583      if ( count( $sql_terms ) ) {
1584          $sql .= '(' . implode( ' OR ', $sql_terms ) . ')';
1585      }
1586  
1587      if ( count( $sql_terms ) && count( $user_ids ) ) {
1588          $sql .= ' AND ';
1589      }
1590  
1591      if ( count( $user_ids ) ) {
1592          $sql .= '`ID` IN (' . join( ',', $user_ids ) . ')';
1593      }
1594  
1595      $sql .= " ORDER BY user_login LIMIT $limit";
1596  
1597      $bb_last_countable_query = $sql;
1598  
1599      do_action( 'bb_user_search', $sql, $args );
1600  
1601      if ( ( $users = $bbdb->get_results( $sql ) ) && $append_meta ) {
1602          return bb_append_meta( $users, 'user' );
1603      }
1604  
1605      return $users ? $users : false;
1606  }
1607  
1608  function bb_tag_search( $args = '' ) {
1609      global $page, $wp_taxonomy_object;
1610  
1611      if ( $args && is_string($args) && false === strpos($args, '=') )
1612          $args = array( 'search' => $args );
1613  
1614      $defaults = array( 'search' => '', 'number' => false );
1615  
1616      $args = wp_parse_args( $args );
1617      if ( isset( $args['query'] ) )
1618          $args['search'] = $args['query'];
1619      if ( isset( $args['tags_per_page'] ) )
1620          $args['number'] = $args['tags_per_page'];
1621      unset($args['query'], $args['tags_per_page']);
1622      $args = wp_parse_args( $args, $defaults );
1623  
1624      extract( $args, EXTR_SKIP );
1625  
1626      $number = (int) $number;
1627      $search = trim( $search );
1628      if ( strlen( $search ) < 3 )
1629          return new WP_Error( 'invalid-query', __('Your search term was too short') );
1630  
1631      $number = 0 < $number ? $number : bb_get_option( 'page_topics' );
1632      if ( 1 < $page )
1633          $offset = ( intval($page) - 1 ) * $number;
1634  
1635      $args = array_merge( $args, compact( 'number', 'offset', 'search' ) );
1636  
1637      $terms = $wp_taxonomy_object->get_terms( 'bb_topic_tag', $args );
1638      if ( is_wp_error( $terms ) )
1639          return false;
1640  
1641      for ( $i = 0; isset($terms[$i]); $i++ )
1642          _bb_make_tag_compat( $terms[$i] );
1643  
1644      return $terms;
1645  }
1646  
1647  
1648  
1649  /* Slugs */
1650  
1651  function bb_slug_increment( $slug, $existing_slug, $slug_length = 255 ) {
1652      if ( preg_match('/^.*-([0-9]+)$/', $existing_slug, $m) )
1653          $number = (int) $m[1] + 1;
1654      else
1655          $number = 1;
1656  
1657      $r = bb_encoded_utf8_cut( $slug, $slug_length - 1 - strlen($number) );
1658      return apply_filters( 'bb_slug_increment', "$r-$number", $slug, $existing_slug, $slug_length );
1659  }
1660  
1661  function bb_get_id_from_slug( $table, $slug, $slug_length = 255 ) {
1662      global $bbdb;
1663      $tablename = $table . 's';
1664  
1665      list($_slug, $sql) = bb_get_sql_from_slug( $table, $slug, $slug_length );
1666  
1667      if ( !$_slug || !$sql )
1668          return 0;
1669  
1670      return (int) $bbdb->get_var( "SELECT $table}_id FROM {$bbdb->$tablename} WHERE $sql" );
1671  }
1672  
1673  function bb_get_sql_from_slug( $table, $slug, $slug_length = 255 ) {
1674      global $bbdb;
1675  
1676      // Look for new style equiv of old style slug
1677      $_slug = bb_slug_sanitize( (string) $slug );
1678      if ( strlen( $_slug ) < 1 )
1679          return '';
1680  
1681      if ( strlen($_slug) > $slug_length && preg_match('/^.*-([0-9]+)$/', $_slug, $m) ) {
1682          $_slug = bb_encoded_utf8_cut( $_slug, $slug_length - 1 - strlen($number) );
1683          $number = (int) $m[1];
1684          $_slug =  "$_slug-$number";
1685      }
1686  
1687      return array( $_slug, $bbdb->prepare( "$table}_slug = %s", $_slug ) );
1688  }    
1689  
1690  
1691  
1692  /* Utility */
1693  
1694  function bb_flatten_array( $array, $cut_branch = 0, $keep_child_array_keys = true ) {
1695      if ( !is_array($array) )
1696          return $array;
1697      
1698      if ( empty($array) )
1699          return null;
1700      
1701      $temp = array();
1702      foreach ( $array as $k => $v ) {
1703          if ( $cut_branch && $k == $cut_branch )
1704              continue;
1705          if ( is_array($v) ) {
1706              if ( $keep_child_array_keys ) {
1707                  $temp[$k] = true;
1708              }
1709              $temp += bb_flatten_array($v, $cut_branch, $keep_child_array_keys);
1710          } else {
1711              $temp[$k] = $v;
1712          }
1713      }
1714      return $temp;
1715  }
1716  
1717  function bb_get_common_parts($string1 = false, $string2 = false, $delimiter = '', $reverse = false) {
1718      if (!$string1 || !$string2) {
1719          return false;
1720      }
1721      
1722      if ($string1 === $string2) {
1723          return $string1;
1724      }
1725      
1726      $string1_parts = explode( $delimiter, (string) $string1 );
1727      $string2_parts = explode( $delimiter, (string) $string2 );
1728      
1729      if ($reverse) {
1730          $string1_parts = array_reverse( $string1_parts );
1731          $string2_parts = array_reverse( $string2_parts );
1732          ksort( $string1_parts );
1733          ksort( $string2_parts );
1734      }
1735      
1736      $common_parts = array();
1737      foreach ( $string1_parts as $index => $part ) {
1738          if ( isset( $string2_parts[$index] ) && $string2_parts[$index] == $part ) {
1739              $common_parts[] = $part;
1740          } else {
1741              break;
1742          }
1743      }
1744      
1745      if (!count($common_parts)) {
1746          return false;
1747      }
1748      
1749      if ($reverse) {
1750          $common_parts = array_reverse( $common_parts );
1751      }
1752      
1753      return join( $delimiter, $common_parts );
1754  }
1755  
1756  function bb_get_common_domains($domain1 = false, $domain2 = false) {
1757      if (!$domain1 || !$domain2) {
1758          return false;
1759      }
1760      
1761      $domain1 = strtolower( preg_replace( '@^https?://([^/]+).*$@i', '$1', $domain1 ) );
1762      $domain2 = strtolower( preg_replace( '@^https?://([^/]+).*$@i', '$1', $domain2 ) );
1763      
1764      return bb_get_common_parts( $domain1, $domain2, '.', true );
1765  }
1766  
1767  function bb_get_common_paths($path1 = false, $path2 = false) {
1768      if (!$path1 || !$path2) {
1769          return false;
1770      }
1771      
1772      $path1 = preg_replace('@^https?://[^/]+(.*)$@i', '$1', $path1);
1773      $path2 = preg_replace('@^https?://[^/]+(.*)$@i', '$1', $path2);
1774      
1775      if ($path1 === $path2) {
1776          return $path1;
1777      }
1778      
1779      $path1 = trim( $path1, '/' );
1780      $path2 = trim( $path2, '/' );
1781      
1782      $common_path = bb_get_common_parts( $path1, $path2, '/' );
1783      
1784      if ($common_path) {
1785          return '/' . $common_path . '/';
1786      } else {
1787          return '/';
1788      }
1789  }
1790  
1791  function bb_match_domains($domain1 = false, $domain2 = false) {
1792      if (!$domain1 || !$domain2) {
1793          return false;
1794      }
1795      
1796      $domain1 = strtolower( preg_replace( '@^https?://([^/]+).*$@i', '$1', $domain1 ) );
1797      $domain2 = strtolower( preg_replace( '@^https?://([^/]+).*$@i', '$1', $domain2 ) );
1798      
1799      if ( (string) $domain1 === (string) $domain2 ) {
1800          return true;
1801      }
1802      
1803      return false;
1804  }
1805  
1806  function bb_glob($pattern) {
1807      // On fail return an empty array so that loops don't explode
1808      
1809      if (!$pattern)
1810          return array();
1811      
1812      // May break if pattern contains forward slashes
1813      $directory = dirname( $pattern );
1814      
1815      if (!$directory)
1816          return array();
1817      
1818      if (!file_exists($directory))
1819          return array();
1820      
1821      if (!is_dir($directory))
1822          return array();
1823      
1824      if (!function_exists('glob'))
1825          return array();
1826      
1827      if (!is_callable('glob'))
1828          return array();
1829      
1830      $glob = glob($pattern);
1831      
1832      if (!is_array($glob))
1833          $glob = array();
1834      
1835      return $glob;
1836  }


Generated: Thu Dec 7 01:01:35 2017 Cross-referenced by PHPXref 0.7.1