[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/ -> functions_content.php (source)

   1  <?php
   2  /**
   3  *
   4  * @package phpBB3
   5  * @version $Id$
   6  * @copyright (c) 2005 phpBB Group
   7  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
   8  *
   9  */
  10  
  11  /**
  12  * @ignore
  13  */
  14  if (!defined('IN_PHPBB'))
  15  {
  16      exit;
  17  }
  18  
  19  /**
  20  * gen_sort_selects()
  21  * make_jumpbox()
  22  * bump_topic_allowed()
  23  * get_context()
  24  * decode_message()
  25  * strip_bbcode()
  26  * generate_text_for_display()
  27  * generate_text_for_storage()
  28  * generate_text_for_edit()
  29  * make_clickable_callback()
  30  * make_clickable()
  31  * censor_text()
  32  * bbcode_nl2br()
  33  * smiley_text()
  34  * parse_attachments()
  35  * extension_allowed()
  36  * truncate_string()
  37  * get_username_string()
  38  * class bitfield
  39  */
  40  
  41  /**
  42  * Generate sort selection fields
  43  */
  44  function gen_sort_selects(&$limit_days, &$sort_by_text, &$sort_days, &$sort_key, &$sort_dir, &$s_limit_days, &$s_sort_key, &$s_sort_dir, &$u_sort_param, $def_st = false, $def_sk = false, $def_sd = false)
  45  {
  46      global $user;
  47  
  48      $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']);
  49  
  50      $sorts = array(
  51          'st'    => array(
  52              'key'        => 'sort_days',
  53              'default'    => $def_st,
  54              'options'    => $limit_days,
  55              'output'    => &$s_limit_days,
  56          ),
  57  
  58          'sk'    => array(
  59              'key'        => 'sort_key',
  60              'default'    => $def_sk,
  61              'options'    => $sort_by_text,
  62              'output'    => &$s_sort_key,
  63          ),
  64  
  65          'sd'    => array(
  66              'key'        => 'sort_dir',
  67              'default'    => $def_sd,
  68              'options'    => $sort_dir_text,
  69              'output'    => &$s_sort_dir,
  70          ),
  71      );
  72      $u_sort_param  = '';
  73  
  74      foreach ($sorts as $name => $sort_ary)
  75      {
  76          $key = $sort_ary['key'];
  77          $selected = $$sort_ary['key'];
  78  
  79          // Check if the key is selectable. If not, we reset to the default or first key found.
  80          // This ensures the values are always valid. We also set $sort_dir/sort_key/etc. to the
  81          // correct value, else the protection is void. ;)
  82          if (!isset($sort_ary['options'][$selected]))
  83          {
  84              if ($sort_ary['default'] !== false)
  85              {
  86                  $selected = $$key = $sort_ary['default'];
  87              }
  88              else
  89              {
  90                  @reset($sort_ary['options']);
  91                  $selected = $$key = key($sort_ary['options']);
  92              }
  93          }
  94  
  95          $sort_ary['output'] = '<select name="' . $name . '" id="' . $name . '">';
  96          foreach ($sort_ary['options'] as $option => $text)
  97          {
  98              $sort_ary['output'] .= '<option value="' . $option . '"' . (($selected == $option) ? ' selected="selected"' : '') . '>' . $text . '</option>';
  99          }
 100          $sort_ary['output'] .= '</select>';
 101  
 102          $u_sort_param .= ($selected !== $sort_ary['default']) ? ((strlen($u_sort_param)) ? '&amp;' : '') . "{$name}={$selected}" : '';
 103      }
 104  
 105      return;
 106  }
 107  
 108  /**
 109  * Generate Jumpbox
 110  */
 111  function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list = false, $force_display = false)
 112  {
 113      global $config, $auth, $template, $user, $db;
 114  
 115      // We only return if the jumpbox is not forced to be displayed (in case it is needed for functionality)
 116      if (!$config['load_jumpbox'] && $force_display === false)
 117      {
 118          return;
 119      }
 120  
 121      $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id
 122          FROM ' . FORUMS_TABLE . '
 123          ORDER BY left_id ASC';
 124      $result = $db->sql_query($sql, 600);
 125  
 126      $right = $padding = 0;
 127      $padding_store = array('0' => 0);
 128      $display_jumpbox = false;
 129      $iteration = 0;
 130  
 131      // Sometimes it could happen that forums will be displayed here not be displayed within the index page
 132      // This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions.
 133      // If this happens, the padding could be "broken"
 134  
 135      while ($row = $db->sql_fetchrow($result))
 136      {
 137          if ($row['left_id'] < $right)
 138          {
 139              $padding++;
 140              $padding_store[$row['parent_id']] = $padding;
 141          }
 142          else if ($row['left_id'] > $right + 1)
 143          {
 144              // Ok, if the $padding_store for this parent is empty there is something wrong. For now we will skip over it.
 145              // @todo digging deep to find out "how" this can happen.
 146              $padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : $padding;
 147          }
 148  
 149          $right = $row['right_id'];
 150  
 151          if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id']))
 152          {
 153              // Non-postable forum with no subforums, don't display
 154              continue;
 155          }
 156  
 157          if (!$auth->acl_get('f_list', $row['forum_id']))
 158          {
 159              // if the user does not have permissions to list this forum skip
 160              continue;
 161          }
 162  
 163          if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id']))
 164          {
 165              continue;
 166          }
 167  
 168          if (!$display_jumpbox)
 169          {
 170              $template->assign_block_vars('jumpbox_forums', array(
 171                  'FORUM_ID'        => ($select_all) ? 0 : -1,
 172                  'FORUM_NAME'    => ($select_all) ? $user->lang['ALL_FORUMS'] : $user->lang['SELECT_FORUM'],
 173                  'S_FORUM_COUNT'    => $iteration)
 174              );
 175  
 176              $iteration++;
 177              $display_jumpbox = true;
 178          }
 179  
 180          $template->assign_block_vars('jumpbox_forums', array(
 181              'FORUM_ID'        => $row['forum_id'],
 182              'FORUM_NAME'    => $row['forum_name'],
 183              'SELECTED'        => ($row['forum_id'] == $forum_id) ? ' selected="selected"' : '',
 184              'S_FORUM_COUNT'    => $iteration,
 185              'S_IS_CAT'        => ($row['forum_type'] == FORUM_CAT) ? true : false,
 186              'S_IS_LINK'        => ($row['forum_type'] == FORUM_LINK) ? true : false,
 187              'S_IS_POST'        => ($row['forum_type'] == FORUM_POST) ? true : false)
 188          );
 189  
 190          for ($i = 0; $i < $padding; $i++)
 191          {
 192              $template->assign_block_vars('jumpbox_forums.level', array());
 193          }
 194          $iteration++;
 195      }
 196      $db->sql_freeresult($result);
 197      unset($padding_store);
 198  
 199      $template->assign_vars(array(
 200          'S_DISPLAY_JUMPBOX'    => $display_jumpbox,
 201          'S_JUMPBOX_ACTION'    => $action)
 202      );
 203  
 204      return;
 205  }
 206  
 207  /**
 208  * Bump Topic Check - used by posting and viewtopic
 209  */
 210  function bump_topic_allowed($forum_id, $topic_bumped, $last_post_time, $topic_poster, $last_topic_poster)
 211  {
 212      global $config, $auth, $user;
 213  
 214      // Check permission and make sure the last post was not already bumped
 215      if (!$auth->acl_get('f_bump', $forum_id) || $topic_bumped)
 216      {
 217          return false;
 218      }
 219  
 220      // Check bump time range, is the user really allowed to bump the topic at this time?
 221      $bump_time = ($config['bump_type'] == 'm') ? $config['bump_interval'] * 60 : (($config['bump_type'] == 'h') ? $config['bump_interval'] * 3600 : $config['bump_interval'] * 86400);
 222  
 223      // Check bump time
 224      if ($last_post_time + $bump_time > time())
 225      {
 226          return false;
 227      }
 228  
 229      // Check bumper, only topic poster and last poster are allowed to bump
 230      if ($topic_poster != $user->data['user_id'] && $last_topic_poster != $user->data['user_id'])
 231      {
 232          return false;
 233      }
 234  
 235      // A bump time of 0 will completely disable the bump feature... not intended but might be useful.
 236      return $bump_time;
 237  }
 238  
 239  /**
 240  * Generates a text with approx. the specified length which contains the specified words and their context
 241  *
 242  * @param    string    $text    The full text from which context shall be extracted
 243  * @param    string    $words    An array of words which should be contained in the result, has to be a valid part of a PCRE pattern (escape with preg_quote!)
 244  * @param    int        $length    The desired length of the resulting text, however the result might be shorter or longer than this value
 245  *
 246  * @return    string            Context of the specified words separated by "..."
 247  */
 248  function get_context($text, $words, $length = 400)
 249  {
 250      // first replace all whitespaces with single spaces
 251      $text = preg_replace('/ +/', ' ', strtr($text, "\t\n\r\x0C ", '     '));
 252  
 253      // we need to turn the entities back into their original form, to not cut the message in between them
 254      $entities = array('&lt;', '&gt;', '&#91;', '&#93;', '&#46;', '&#58;', '&#058;');
 255      $characters = array('<', '>', '[', ']', '.', ':', ':');
 256      $text = str_replace($entities, $characters, $text);
 257  
 258      $word_indizes = array();
 259      if (sizeof($words))
 260      {
 261          $match = '';
 262          // find the starting indizes of all words
 263          foreach ($words as $word)
 264          {
 265              if ($word)
 266              {
 267                  if (preg_match('#(?:[^\w]|^)(' . $word . ')(?:[^\w]|$)#i', $text, $match))
 268                  {
 269                      if (empty($match[1]))
 270                      {
 271                          continue;
 272                      }
 273  
 274                      $pos = utf8_strpos($text, $match[1]);
 275                      if ($pos !== false)
 276                      {
 277                          $word_indizes[] = $pos;
 278                      }
 279                  }
 280              }
 281          }
 282          unset($match);
 283  
 284          if (sizeof($word_indizes))
 285          {
 286              $word_indizes = array_unique($word_indizes);
 287              sort($word_indizes);
 288  
 289              $wordnum = sizeof($word_indizes);
 290              // number of characters on the right and left side of each word
 291              $sequence_length = (int) ($length / (2 * $wordnum)) - 2;
 292              $final_text = '';
 293              $word = $j = 0;
 294              $final_text_index = -1;
 295  
 296              // cycle through every character in the original text
 297              for ($i = $word_indizes[$word], $n = utf8_strlen($text); $i < $n; $i++)
 298              {
 299                  // if the current position is the start of one of the words then append $sequence_length characters to the final text
 300                  if (isset($word_indizes[$word]) && ($i == $word_indizes[$word]))
 301                  {
 302                      if ($final_text_index < $i - $sequence_length - 1)
 303                      {
 304                          $final_text .= '... ' . preg_replace('#^([^ ]*)#', '', utf8_substr($text, $i - $sequence_length, $sequence_length));
 305                      }
 306                      else
 307                      {
 308                          // if the final text is already nearer to the current word than $sequence_length we only append the text
 309                          // from its current index on and distribute the unused length to all other sequenes
 310                          $sequence_length += (int) (($final_text_index - $i + $sequence_length + 1) / (2 * $wordnum));
 311                          $final_text .= utf8_substr($text, $final_text_index + 1, $i - $final_text_index - 1);
 312                      }
 313                      $final_text_index = $i - 1;
 314  
 315                      // add the following characters to the final text (see below)
 316                      $word++;
 317                      $j = 1;
 318                  }
 319  
 320                  if ($j > 0)
 321                  {
 322                      // add the character to the final text and increment the sequence counter
 323                      $final_text .= utf8_substr($text, $i, 1);
 324                      $final_text_index++;
 325                      $j++;
 326  
 327                      // if this is a whitespace then check whether we are done with this sequence
 328                      if (utf8_substr($text, $i, 1) == ' ')
 329                      {
 330                          // only check whether we have to exit the context generation completely if we haven't already reached the end anyway
 331                          if ($i + 4 < $n)
 332                          {
 333                              if (($j > $sequence_length && $word >= $wordnum) || utf8_strlen($final_text) > $length)
 334                              {
 335                                  $final_text .= ' ...';
 336                                  break;
 337                              }
 338                          }
 339                          else
 340                          {
 341                              // make sure the text really reaches the end
 342                              $j -= 4;
 343                          }
 344  
 345                          // stop context generation and wait for the next word
 346                          if ($j > $sequence_length)
 347                          {
 348                              $j = 0;
 349                          }
 350                      }
 351                  }
 352              }
 353              return str_replace($characters, $entities, $final_text);
 354          }
 355      }
 356  
 357      if (!sizeof($words) || !sizeof($word_indizes))
 358      {
 359          return str_replace($characters, $entities, ((utf8_strlen($text) >= $length + 3) ? utf8_substr($text, 0, $length) . '...' : $text));
 360      }
 361  }
 362  
 363  /**
 364  * Decode text whereby text is coming from the db and expected to be pre-parsed content
 365  * We are placing this outside of the message parser because we are often in need of it...
 366  */
 367  function decode_message(&$message, $bbcode_uid = '')
 368  {
 369      global $config;
 370  
 371      if ($bbcode_uid)
 372      {
 373          $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid");
 374          $replace = array("\n", '', '', '', '');
 375      }
 376      else
 377      {
 378          $match = array('<br />');
 379          $replace = array("\n");
 380      }
 381  
 382      $message = str_replace($match, $replace, $message);
 383  
 384      $match = get_preg_expression('bbcode_htm');
 385      $replace = array('\1', '\1', '\2', '\1', '', '');
 386  
 387      $message = preg_replace($match, $replace, $message);
 388  }
 389  
 390  /**
 391  * Strips all bbcode from a text and returns the plain content
 392  */
 393  function strip_bbcode(&$text, $uid = '')
 394  {
 395      if (!$uid)
 396      {
 397          $uid = '[0-9a-z]{5,}';
 398      }
 399  
 400      $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:&quot;.*&quot;|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text);
 401  
 402      $match = get_preg_expression('bbcode_htm');
 403      $replace = array('\1', '\1', '\2', '\1', '', '');
 404  
 405      $text = preg_replace($match, $replace, $text);
 406  }
 407  
 408  /**
 409  * For display of custom parsed text on user-facing pages
 410  * Expects $text to be the value directly from the database (stored value)
 411  */
 412  function generate_text_for_display($text, $uid, $bitfield, $flags)
 413  {
 414      static $bbcode;
 415  
 416      if (!$text)
 417      {
 418          return '';
 419      }
 420  
 421      $text = censor_text($text);
 422  
 423      // Parse bbcode if bbcode uid stored and bbcode enabled
 424      if ($uid && ($flags & OPTION_FLAG_BBCODE))
 425      {
 426          if (!class_exists('bbcode'))
 427          {
 428              global $phpbb_root_path, $phpEx;
 429              include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
 430          }
 431  
 432          if (empty($bbcode))
 433          {
 434              $bbcode = new bbcode($bitfield);
 435          }
 436          else
 437          {
 438              $bbcode->bbcode($bitfield);
 439          }
 440  
 441          $bbcode->bbcode_second_pass($text, $uid);
 442      }
 443  
 444      $text = bbcode_nl2br($text);
 445      $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES));
 446  
 447      return $text;
 448  }
 449  
 450  /**
 451  * For parsing custom parsed text to be stored within the database.
 452  * This function additionally returns the uid and bitfield that needs to be stored.
 453  * Expects $text to be the value directly from request_var() and in it's non-parsed form
 454  */
 455  function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false)
 456  {
 457      global $phpbb_root_path, $phpEx;
 458  
 459      $uid = $bitfield = '';
 460      $flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0);
 461  
 462      if (!$text)
 463      {
 464          return;
 465      }
 466  
 467      if (!class_exists('parse_message'))
 468      {
 469          include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
 470      }
 471  
 472      $message_parser = new parse_message($text);
 473      $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies);
 474  
 475      $text = $message_parser->message;
 476      $uid = $message_parser->bbcode_uid;
 477  
 478      // If the bbcode_bitfield is empty, there is no need for the uid to be stored.
 479      if (!$message_parser->bbcode_bitfield)
 480      {
 481          $uid = '';
 482      }
 483  
 484      $bitfield = $message_parser->bbcode_bitfield;
 485  
 486      return;
 487  }
 488  
 489  /**
 490  * For decoding custom parsed text for edits as well as extracting the flags
 491  * Expects $text to be the value directly from the database (pre-parsed content)
 492  */
 493  function generate_text_for_edit($text, $uid, $flags)
 494  {
 495      global $phpbb_root_path, $phpEx;
 496  
 497      decode_message($text, $uid);
 498  
 499      return array(
 500          'allow_bbcode'    => ($flags & OPTION_FLAG_BBCODE) ? 1 : 0,
 501          'allow_smilies'    => ($flags & OPTION_FLAG_SMILIES) ? 1 : 0,
 502          'allow_urls'    => ($flags & OPTION_FLAG_LINKS) ? 1 : 0,
 503          'text'            => $text
 504      );
 505  }
 506  
 507  /**
 508  * A subroutine of make_clickable used with preg_replace
 509  * It places correct HTML around an url, shortens the displayed text
 510  * and makes sure no entities are inside URLs
 511  */
 512  function make_clickable_callback($type, $whitespace, $url, $relative_url, $class)
 513  {
 514      $orig_url        = $url;
 515      $orig_relative    = $relative_url;
 516      $append            = '';
 517      $url            = htmlspecialchars_decode($url);
 518      $relative_url    = htmlspecialchars_decode($relative_url);
 519  
 520      // make sure no HTML entities were matched
 521      $chars = array('<', '>', '"');
 522      $split = false;
 523  
 524      foreach ($chars as $char)
 525      {
 526          $next_split = strpos($url, $char);
 527          if ($next_split !== false)
 528          {
 529              $split = ($split !== false) ? min($split, $next_split) : $next_split;
 530          }
 531      }
 532  
 533      if ($split !== false)
 534      {
 535          // an HTML entity was found, so the URL has to end before it
 536          $append            = substr($url, $split) . $relative_url;
 537          $url            = substr($url, 0, $split);
 538          $relative_url    = '';
 539      }
 540      else if ($relative_url)
 541      {
 542          // same for $relative_url
 543          $split = false;
 544          foreach ($chars as $char)
 545          {
 546              $next_split = strpos($relative_url, $char);
 547              if ($next_split !== false)
 548              {
 549                  $split = ($split !== false) ? min($split, $next_split) : $next_split;
 550              }
 551          }
 552  
 553          if ($split !== false)
 554          {
 555              $append            = substr($relative_url, $split);
 556              $relative_url    = substr($relative_url, 0, $split);
 557          }
 558      }
 559  
 560      // if the last character of the url is a punctuation mark, exclude it from the url
 561      $last_char = ($relative_url) ? $relative_url[strlen($relative_url) - 1] : $url[strlen($url) - 1];
 562  
 563      switch ($last_char)
 564      {
 565          case '.':
 566          case '?':
 567          case '!':
 568          case ':':
 569          case ',':
 570              $append = $last_char;
 571              if ($relative_url)
 572              {
 573                  $relative_url = substr($relative_url, 0, -1);
 574              }
 575              else
 576              {
 577                  $url = substr($url, 0, -1);
 578              }
 579          break;
 580  
 581          // set last_char to empty here, so the variable can be used later to
 582          // check whether a character was removed
 583          default:
 584              $last_char = '';
 585          break;
 586      }
 587  
 588      $short_url = (strlen($url) > 55) ? substr($url, 0, 39) . ' ... ' . substr($url, -10) : $url;
 589  
 590      switch ($type)
 591      {
 592          case MAGIC_URL_LOCAL:
 593              $tag            = 'l';
 594              $relative_url    = preg_replace('/[&?]sid=[0-9a-f]{32}$/', '', preg_replace('/([&?])sid=[0-9a-f]{32}&/', '$1', $relative_url));
 595              $url            = $url . '/' . $relative_url;
 596              $text            = $relative_url;
 597  
 598              // this url goes to http://domain.tld/path/to/board/ which
 599              // would result in an empty link if treated as local so
 600              // don't touch it and let MAGIC_URL_FULL take care of it.
 601              if (!$relative_url)
 602              {
 603                  return $whitespace . $orig_url . '/' . $orig_relative; // slash is taken away by relative url pattern
 604              }
 605          break;
 606  
 607          case MAGIC_URL_FULL:
 608              $tag    = 'm';
 609              $text    = $short_url;
 610          break;
 611  
 612          case MAGIC_URL_WWW:
 613              $tag    = 'w';
 614              $url    = 'http://' . $url;
 615              $text    = $short_url;
 616          break;
 617  
 618          case MAGIC_URL_EMAIL:
 619              $tag    = 'e';
 620              $text    = $short_url;
 621              $url    = 'mailto:' . $url;
 622          break;
 623      }
 624  
 625      $url    = htmlspecialchars($url);
 626      $text    = htmlspecialchars($text);
 627      $append    = htmlspecialchars($append);
 628  
 629      $html    = "$whitespace<!-- $tag --><a$class href=\"$url\">$text</a><!-- $tag -->$append";
 630  
 631      return $html;
 632  }
 633  
 634  /**
 635  * make_clickable function
 636  *
 637  * Replace magic urls of form http://xxx.xxx., www.xxx. and xxx@xxx.xxx.
 638  * Cuts down displayed size of link if over 50 chars, turns absolute links
 639  * into relative versions when the server/script path matches the link
 640  */
 641  function make_clickable($text, $server_url = false, $class = 'postlink')
 642  {
 643      if ($server_url === false)
 644      {
 645          $server_url = generate_board_url();
 646      }
 647  
 648      static $magic_url_match;
 649      static $magic_url_replace;
 650      static $static_class;
 651  
 652      if (!is_array($magic_url_match) || $static_class != $class)
 653      {
 654          $static_class = $class;
 655          $class = ($static_class) ? ' class="' . $static_class . '"' : '';
 656          $local_class = ($static_class) ? ' class="' . $static_class . '-local"' : '';
 657  
 658          $magic_url_match = $magic_url_replace = array();
 659          // Be sure to not let the matches cross over. ;)
 660  
 661          // relative urls for this board
 662          $magic_url_match[] = '#(^|[\n\t (>.])(' . preg_quote($server_url, '#') . ')/(' . get_preg_expression('relative_url_inline') . ')#ie';
 663          $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_LOCAL, '\$1', '\$2', '\$3', '$local_class')";
 664  
 665          // matches a xxxx://aaaaa.bbb.cccc. ...
 666          $magic_url_match[] = '#(^|[\n\t (>.])(' . get_preg_expression('url_inline') . ')#ie';
 667          $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_FULL, '\$1', '\$2', '', '$class')";
 668  
 669          // matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing
 670          $magic_url_match[] = '#(^|[\n\t (>])(' . get_preg_expression('www_url_inline') . ')#ie';
 671          $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_WWW, '\$1', '\$2', '', '$class')";
 672  
 673          // matches an email@domain type address at the start of a line, or after a space or after what might be a BBCode.
 674          $magic_url_match[] = '/(^|[\n\t (>])(' . get_preg_expression('email') . ')/ie';
 675          $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_EMAIL, '\$1', '\$2', '', '')";
 676      }
 677  
 678      return preg_replace($magic_url_match, $magic_url_replace, $text);
 679  }
 680  
 681  /**
 682  * Censoring
 683  */
 684  function censor_text($text)
 685  {
 686      static $censors;
 687  
 688      // Nothing to do?
 689      if ($text === '')
 690      {
 691          return '';
 692      }
 693  
 694      // We moved the word censor checks in here because we call this function quite often - and then only need to do the check once
 695      if (!isset($censors) || !is_array($censors))
 696      {
 697          global $config, $user, $auth, $cache;
 698  
 699          // We check here if the user is having viewing censors disabled (and also allowed to do so).
 700          if (!$user->optionget('viewcensors') && $config['allow_nocensors'] && $auth->acl_get('u_chgcensors'))
 701          {
 702              $censors = array();
 703          }
 704          else
 705          {
 706              $censors = $cache->obtain_word_list();
 707          }
 708      }
 709  
 710      if (sizeof($censors))
 711      {
 712          return preg_replace($censors['match'], $censors['replace'], $text);
 713      }
 714  
 715      return $text;
 716  }
 717  
 718  /**
 719  * custom version of nl2br which takes custom BBCodes into account
 720  */
 721  function bbcode_nl2br($text)
 722  {
 723      // custom BBCodes might contain carriage returns so they
 724      // are not converted into <br /> so now revert that
 725      $text = str_replace(array("\n", "\r"), array('<br />', "\n"), $text);
 726      return $text;
 727  }
 728  
 729  /**
 730  * Smiley processing
 731  */
 732  function smiley_text($text, $force_option = false)
 733  {
 734      global $config, $user, $phpbb_root_path;
 735  
 736      if ($force_option || !$config['allow_smilies'] || !$user->optionget('viewsmilies'))
 737      {
 738          return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#', '\1', $text);
 739      }
 740      else
 741      {
 742          $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path;
 743          return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/(.*?) \/><!\-\- s\1 \-\->#', '<img src="' . $root_path . $config['smilies_path'] . '/\2 />', $text);
 744      }
 745  }
 746  
 747  /**
 748  * General attachment parsing
 749  *
 750  * @param mixed $forum_id The forum id the attachments are displayed in (false if in private message)
 751  * @param string &$message The post/private message
 752  * @param array &$attachments The attachments to parse for (inline) display. The attachments array will hold templated data after parsing.
 753  * @param array &$update_count The attachment counts to be updated - will be filled
 754  * @param bool $preview If set to true the attachments are parsed for preview. Within preview mode the comments are fetched from the given $attachments array and not fetched from the database.
 755  */
 756  function parse_attachments($forum_id, &$message, &$attachments, &$update_count, $preview = false)
 757  {
 758      if (!sizeof($attachments))
 759      {
 760          return;
 761      }
 762  
 763      global $template, $cache, $user;
 764      global $extensions, $config, $phpbb_root_path, $phpEx;
 765  
 766      //
 767      $compiled_attachments = array();
 768  
 769      if (!isset($template->filename['attachment_tpl']))
 770      {
 771          $template->set_filenames(array(
 772              'attachment_tpl'    => 'attachment.html')
 773          );
 774      }
 775  
 776      if (empty($extensions) || !is_array($extensions))
 777      {
 778          $extensions = $cache->obtain_attach_extensions($forum_id);
 779      }
 780  
 781      // Look for missing attachment information...
 782      $attach_ids = array();
 783      foreach ($attachments as $pos => $attachment)
 784      {
 785          // If is_orphan is set, we need to retrieve the attachments again...
 786          if (!isset($attachment['extension']) && !isset($attachment['physical_filename']))
 787          {
 788              $attach_ids[(int) $attachment['attach_id']] = $pos;
 789          }
 790      }
 791  
 792      // Grab attachments (security precaution)
 793      if (sizeof($attach_ids))
 794      {
 795          global $db;
 796  
 797          $new_attachment_data = array();
 798  
 799          $sql = 'SELECT *
 800              FROM ' . ATTACHMENTS_TABLE . '
 801              WHERE ' . $db->sql_in_set('attach_id', array_keys($attach_ids));
 802          $result = $db->sql_query($sql);
 803  
 804          while ($row = $db->sql_fetchrow($result))
 805          {
 806              if (!isset($attach_ids[$row['attach_id']]))
 807              {
 808                  continue;
 809              }
 810  
 811              // If we preview attachments we will set some retrieved values here
 812              if ($preview)
 813              {
 814                  $row['attach_comment'] = $attachments[$attach_ids[$row['attach_id']]]['attach_comment'];
 815              }
 816  
 817              $new_attachment_data[$attach_ids[$row['attach_id']]] = $row;
 818          }
 819          $db->sql_freeresult($result);
 820  
 821          $attachments = $new_attachment_data;
 822          unset($new_attachment_data);
 823      }
 824  
 825      // Sort correctly
 826      if ($config['display_order'])
 827      {
 828          // Ascending sort
 829          krsort($attachments);
 830      }
 831      else
 832      {
 833          // Descending sort
 834          ksort($attachments);
 835      }
 836  
 837      foreach ($attachments as $attachment)
 838      {
 839          if (!sizeof($attachment))
 840          {
 841              continue;
 842          }
 843  
 844          // We need to reset/empty the _file block var, because this function might be called more than once
 845          $template->destroy_block_vars('_file');
 846  
 847          $block_array = array();
 848  
 849          // Some basics...
 850          $attachment['extension'] = strtolower(trim($attachment['extension']));
 851          $filename = $phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($attachment['physical_filename']);
 852          $thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . utf8_basename($attachment['physical_filename']);
 853  
 854          $upload_icon = '';
 855  
 856          if (isset($extensions[$attachment['extension']]))
 857          {
 858              if ($user->img('icon_topic_attach', '') && !$extensions[$attachment['extension']]['upload_icon'])
 859              {
 860                  $upload_icon = $user->img('icon_topic_attach', '');
 861              }
 862              else if ($extensions[$attachment['extension']]['upload_icon'])
 863              {
 864                  $upload_icon = '<img src="' . $phpbb_root_path . $config['upload_icons_path'] . '/' . trim($extensions[$attachment['extension']]['upload_icon']) . '" alt="" />';
 865              }
 866          }
 867  
 868          $filesize = get_formatted_filesize($attachment['filesize'], false);
 869  
 870          $comment = bbcode_nl2br(censor_text($attachment['attach_comment']));
 871  
 872          $block_array += array(
 873              'UPLOAD_ICON'        => $upload_icon,
 874              'FILESIZE'            => $filesize['value'],
 875              'SIZE_LANG'            => $filesize['unit'],
 876              'DOWNLOAD_NAME'        => utf8_basename($attachment['real_filename']),
 877              'COMMENT'            => $comment,
 878          );
 879  
 880          $denied = false;
 881  
 882          if (!extension_allowed($forum_id, $attachment['extension'], $extensions))
 883          {
 884              $denied = true;
 885  
 886              $block_array += array(
 887                  'S_DENIED'            => true,
 888                  'DENIED_MESSAGE'    => sprintf($user->lang['EXTENSION_DISABLED_AFTER_POSTING'], $attachment['extension'])
 889              );
 890          }
 891  
 892          if (!$denied)
 893          {
 894              $l_downloaded_viewed = $download_link = '';
 895              $display_cat = $extensions[$attachment['extension']]['display_cat'];
 896  
 897              if ($display_cat == ATTACHMENT_CATEGORY_IMAGE)
 898              {
 899                  if ($attachment['thumbnail'])
 900                  {
 901                      $display_cat = ATTACHMENT_CATEGORY_THUMB;
 902                  }
 903                  else
 904                  {
 905                      if ($config['img_display_inlined'])
 906                      {
 907                          if ($config['img_link_width'] || $config['img_link_height'])
 908                          {
 909                              $dimension = @getimagesize($filename);
 910  
 911                              // If the dimensions could not be determined or the image being 0x0 we display it as a link for safety purposes
 912                              if ($dimension === false || empty($dimension[0]) || empty($dimension[1]))
 913                              {
 914                                  $display_cat = ATTACHMENT_CATEGORY_NONE;
 915                              }
 916                              else
 917                              {
 918                                  $display_cat = ($dimension[0] <= $config['img_link_width'] && $dimension[1] <= $config['img_link_height']) ? ATTACHMENT_CATEGORY_IMAGE : ATTACHMENT_CATEGORY_NONE;
 919                              }
 920                          }
 921                      }
 922                      else
 923                      {
 924                          $display_cat = ATTACHMENT_CATEGORY_NONE;
 925                      }
 926                  }
 927              }
 928  
 929              // Make some descisions based on user options being set.
 930              if (($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !$user->optionget('viewimg'))
 931              {
 932                  $display_cat = ATTACHMENT_CATEGORY_NONE;
 933              }
 934  
 935              if ($display_cat == ATTACHMENT_CATEGORY_FLASH && !$user->optionget('viewflash'))
 936              {
 937                  $display_cat = ATTACHMENT_CATEGORY_NONE;
 938              }
 939  
 940              $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']);
 941  
 942              switch ($display_cat)
 943              {
 944                  // Images
 945                  case ATTACHMENT_CATEGORY_IMAGE:
 946                      $l_downloaded_viewed = 'VIEWED_COUNT';
 947                      $inline_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']);
 948                      $download_link .= '&amp;mode=view';
 949  
 950                      $block_array += array(
 951                          'S_IMAGE'        => true,
 952                          'U_INLINE_LINK'        => $inline_link,
 953                      );
 954  
 955                      $update_count[] = $attachment['attach_id'];
 956                  break;
 957  
 958                  // Images, but display Thumbnail
 959                  case ATTACHMENT_CATEGORY_THUMB:
 960                      $l_downloaded_viewed = 'VIEWED_COUNT';
 961                      $thumbnail_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id'] . '&amp;t=1');
 962                      $download_link .= '&amp;mode=view';
 963  
 964                      $block_array += array(
 965                          'S_THUMBNAIL'        => true,
 966                          'THUMB_IMAGE'        => $thumbnail_link,
 967                      );
 968  
 969                      $update_count[] = $attachment['attach_id'];
 970                  break;
 971  
 972                  // Windows Media Streams
 973                  case ATTACHMENT_CATEGORY_WM:
 974                      $l_downloaded_viewed = 'VIEWED_COUNT';
 975  
 976                      // Giving the filename directly because within the wm object all variables are in local context making it impossible
 977                      // to validate against a valid session (all params can differ)
 978                      // $download_link = $filename;
 979  
 980                      $block_array += array(
 981                          'U_FORUM'        => generate_board_url(),
 982                          'ATTACH_ID'        => $attachment['attach_id'],
 983                          'S_WM_FILE'        => true,
 984                      );
 985  
 986                      // Viewed/Heared File ... update the download count
 987                      $update_count[] = $attachment['attach_id'];
 988                  break;
 989  
 990                  // Real Media Streams
 991                  case ATTACHMENT_CATEGORY_RM:
 992                  case ATTACHMENT_CATEGORY_QUICKTIME:
 993                      $l_downloaded_viewed = 'VIEWED_COUNT';
 994  
 995                      $block_array += array(
 996                          'S_RM_FILE'            => ($display_cat == ATTACHMENT_CATEGORY_RM) ? true : false,
 997                          'S_QUICKTIME_FILE'    => ($display_cat == ATTACHMENT_CATEGORY_QUICKTIME) ? true : false,
 998                          'U_FORUM'            => generate_board_url(),
 999                          'ATTACH_ID'            => $attachment['attach_id'],
1000                      );
1001  
1002                      // Viewed/Heared File ... update the download count
1003                      $update_count[] = $attachment['attach_id'];
1004                  break;
1005  
1006                  // Macromedia Flash Files
1007                  case ATTACHMENT_CATEGORY_FLASH:
1008                      list($width, $height) = @getimagesize($filename);
1009  
1010                      $l_downloaded_viewed = 'VIEWED_COUNT';
1011  
1012                      $block_array += array(
1013                          'S_FLASH_FILE'    => true,
1014                          'WIDTH'            => $width,
1015                          'HEIGHT'        => $height,
1016                          'U_VIEW_LINK'    => $download_link . '&amp;view=1',
1017                      );
1018  
1019                      // Viewed/Heared File ... update the download count
1020                      $update_count[] = $attachment['attach_id'];
1021                  break;
1022  
1023                  default:
1024                      $l_downloaded_viewed = 'DOWNLOAD_COUNT';
1025  
1026                      $block_array += array(
1027                          'S_FILE'        => true,
1028                      );
1029                  break;
1030              }
1031  
1032              $l_download_count = (!isset($attachment['download_count']) || $attachment['download_count'] == 0) ? $user->lang[$l_downloaded_viewed . '_NONE'] : (($attachment['download_count'] == 1) ? sprintf($user->lang[$l_downloaded_viewed], $attachment['download_count']) : sprintf($user->lang[$l_downloaded_viewed . 'S'], $attachment['download_count']));
1033  
1034              $block_array += array(
1035                  'U_DOWNLOAD_LINK'        => $download_link,
1036                  'L_DOWNLOAD_COUNT'        => $l_download_count
1037              );
1038          }
1039  
1040          $template->assign_block_vars('_file', $block_array);
1041  
1042          $compiled_attachments[] = $template->assign_display('attachment_tpl');
1043      }
1044  
1045      $attachments = $compiled_attachments;
1046      unset($compiled_attachments);
1047  
1048      $tpl_size = sizeof($attachments);
1049  
1050      $unset_tpl = array();
1051  
1052      preg_match_all('#<!\-\- ia([0-9]+) \-\->(.*?)<!\-\- ia\1 \-\->#', $message, $matches, PREG_PATTERN_ORDER);
1053  
1054      $replace = array();
1055      foreach ($matches[0] as $num => $capture)
1056      {
1057          // Flip index if we are displaying the reverse way
1058          $index = ($config['display_order']) ? ($tpl_size-($matches[1][$num] + 1)) : $matches[1][$num];
1059  
1060          $replace['from'][] = $matches[0][$num];
1061          $replace['to'][] = (isset($attachments[$index])) ? $attachments[$index] : sprintf($user->lang['MISSING_INLINE_ATTACHMENT'], $matches[2][array_search($index, $matches[1])]);
1062  
1063          $unset_tpl[] = $index;
1064      }
1065  
1066      if (isset($replace['from']))
1067      {
1068          $message = str_replace($replace['from'], $replace['to'], $message);
1069      }
1070  
1071      $unset_tpl = array_unique($unset_tpl);
1072  
1073      // Needed to let not display the inlined attachments at the end of the post again
1074      foreach ($unset_tpl as $index)
1075      {
1076          unset($attachments[$index]);
1077      }
1078  }
1079  
1080  /**
1081  * Check if extension is allowed to be posted.
1082  *
1083  * @param mixed $forum_id The forum id to check or false if private message
1084  * @param string $extension The extension to check, for example zip.
1085  * @param array &$extensions The extension array holding the information from the cache (will be obtained if empty)
1086  *
1087  * @return bool False if the extension is not allowed to be posted, else true.
1088  */
1089  function extension_allowed($forum_id, $extension, &$extensions)
1090  {
1091      if (empty($extensions))
1092      {
1093          global $cache;
1094          $extensions = $cache->obtain_attach_extensions($forum_id);
1095      }
1096  
1097      return (!isset($extensions['_allowed_'][$extension])) ? false : true;
1098  }
1099  
1100  /**
1101  * Truncates string while retaining special characters if going over the max length
1102  * The default max length is 60 at the moment
1103  * The maximum storage length is there to fit the string within the given length. The string may be further truncated due to html entities.
1104  * For example: string given is 'a "quote"' (length: 9), would be a stored as 'a &quot;quote&quot;' (length: 19)
1105  *
1106  * @param string $string The text to truncate to the given length. String is specialchared.
1107  * @param int $max_length Maximum length of string (multibyte character count as 1 char / Html entity count as 1 char)
1108  * @param int $max_store_length Maximum character length of string (multibyte character count as 1 char / Html entity count as entity chars).
1109  * @param bool $allow_reply Allow Re: in front of string 
1110  *     NOTE: This parameter can cause undesired behavior (returning strings longer than $max_store_length) and is deprecated. 
1111  * @param string $append String to be appended
1112  */
1113  function truncate_string($string, $max_length = 60, $max_store_length = 255, $allow_reply = false, $append = '')
1114  {
1115      $chars = array();
1116  
1117      $strip_reply = false;
1118      $stripped = false;
1119      if ($allow_reply && strpos($string, 'Re: ') === 0)
1120      {
1121          $strip_reply = true;
1122          $string = substr($string, 4);
1123      }
1124  
1125      $_chars = utf8_str_split(htmlspecialchars_decode($string));
1126      $chars = array_map('utf8_htmlspecialchars', $_chars);
1127  
1128      // Now check the length ;)
1129      if (sizeof($chars) > $max_length)
1130      {
1131          // Cut off the last elements from the array
1132          $string = implode('', array_slice($chars, 0, $max_length - utf8_strlen($append)));
1133          $stripped = true;
1134      }
1135  
1136      // Due to specialchars, we may not be able to store the string...
1137      if (utf8_strlen($string) > $max_store_length)
1138      {
1139          // let's split again, we do not want half-baked strings where entities are split
1140          $_chars = utf8_str_split(htmlspecialchars_decode($string));
1141          $chars = array_map('utf8_htmlspecialchars', $_chars);
1142  
1143          do
1144          {
1145              array_pop($chars);
1146              $string = implode('', $chars);
1147          }
1148          while (!empty($chars) && utf8_strlen($string) > $max_store_length);
1149      }
1150  
1151      if ($strip_reply)
1152      {
1153          $string = 'Re: ' . $string;
1154      }
1155  
1156      if ($append != '' && $stripped)
1157      {
1158          $string = $string . $append;
1159      }
1160  
1161      return $string;
1162  }
1163  
1164  /**
1165  * Get username details for placing into templates.
1166  * This function caches all modes on first call, except for no_profile and anonymous user - determined by $user_id.
1167  *
1168  * @param string $mode Can be profile (for getting an url to the profile), username (for obtaining the username), colour (for obtaining the user colour), full (for obtaining a html string representing a coloured link to the users profile) or no_profile (the same as full but forcing no profile link)
1169  * @param int $user_id The users id
1170  * @param string $username The users name
1171  * @param string $username_colour The users colour
1172  * @param string $guest_username optional parameter to specify the guest username. It will be used in favor of the GUEST language variable then.
1173  * @param string $custom_profile_url optional parameter to specify a profile url. The user id get appended to this url as &amp;u={user_id}
1174  *
1175  * @return string A string consisting of what is wanted based on $mode.
1176  * @author BartVB, Acyd Burn
1177  */
1178  function get_username_string($mode, $user_id, $username, $username_colour = '', $guest_username = false, $custom_profile_url = false)
1179  {
1180      static $_profile_cache;
1181  
1182      // We cache some common variables we need within this function
1183      if (empty($_profile_cache))
1184      {
1185          global $phpbb_root_path, $phpEx;
1186  
1187          $_profile_cache['base_url'] = append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u={USER_ID}');
1188          $_profile_cache['tpl_noprofile'] = '{USERNAME}';
1189          $_profile_cache['tpl_noprofile_colour'] = '<span style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</span>';
1190          $_profile_cache['tpl_profile'] = '<a href="{PROFILE_URL}">{USERNAME}</a>';
1191          $_profile_cache['tpl_profile_colour'] = '<a href="{PROFILE_URL}" style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</a>';
1192      }
1193  
1194      global $user, $auth;
1195  
1196      // This switch makes sure we only run code required for the mode
1197      switch ($mode)
1198      {
1199          case 'full':
1200          case 'no_profile':
1201          case 'colour':
1202  
1203              // Build correct username colour
1204              $username_colour = ($username_colour) ? '#' . $username_colour : '';
1205  
1206              // Return colour
1207              if ($mode == 'colour')
1208              {
1209                  return $username_colour;
1210              }
1211  
1212          // no break;
1213  
1214          case 'username':
1215  
1216              // Build correct username
1217              if ($guest_username === false)
1218              {
1219                  $username = ($username) ? $username : $user->lang['GUEST'];
1220              }
1221              else
1222              {
1223                  $username = ($user_id && $user_id != ANONYMOUS) ? $username : ((!empty($guest_username)) ? $guest_username : $user->lang['GUEST']);
1224              }
1225  
1226              // Return username
1227              if ($mode == 'username')
1228              {
1229                  return $username;
1230              }
1231  
1232          // no break;
1233  
1234          case 'profile':
1235  
1236              // Build correct profile url - only show if not anonymous and permission to view profile if registered user
1237              // For anonymous the link leads to a login page.
1238              if ($user_id && $user_id != ANONYMOUS && ($user->data['user_id'] == ANONYMOUS || $auth->acl_get('u_viewprofile')))
1239              {
1240                  $profile_url = ($custom_profile_url !== false) ? $custom_profile_url . '&amp;u=' . (int) $user_id : str_replace(array('={USER_ID}', '=%7BUSER_ID%7D'), '=' . (int) $user_id, $_profile_cache['base_url']);
1241              }
1242              else
1243              {
1244                  $profile_url = '';
1245              }
1246  
1247              // Return profile
1248              if ($mode == 'profile')
1249              {
1250                  return $profile_url;
1251              }
1252  
1253          // no break;
1254      }
1255  
1256      if (($mode == 'full' && !$profile_url) || $mode == 'no_profile')
1257      {
1258          return str_replace(array('{USERNAME_COLOUR}', '{USERNAME}'), array($username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_noprofile'] : $_profile_cache['tpl_noprofile_colour']);
1259      }
1260  
1261      return str_replace(array('{PROFILE_URL}', '{USERNAME_COLOUR}', '{USERNAME}'), array($profile_url, $username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_profile'] : $_profile_cache['tpl_profile_colour']);
1262  }
1263  
1264  /**
1265  * @package phpBB3
1266  */
1267  class bitfield
1268  {
1269      var $data;
1270  
1271  	function bitfield($bitfield = '')
1272      {
1273          $this->data = base64_decode($bitfield);
1274      }
1275  
1276      /**
1277      */
1278  	function get($n)
1279      {
1280          // Get the ($n / 8)th char
1281          $byte = $n >> 3;
1282  
1283          if (strlen($this->data) >= $byte + 1)
1284          {
1285              $c = $this->data[$byte];
1286  
1287              // Lookup the ($n % 8)th bit of the byte
1288              $bit = 7 - ($n & 7);
1289              return (bool) (ord($c) & (1 << $bit));
1290          }
1291          else
1292          {
1293              return false;
1294          }
1295      }
1296  
1297  	function set($n)
1298      {
1299          $byte = $n >> 3;
1300          $bit = 7 - ($n & 7);
1301  
1302          if (strlen($this->data) >= $byte + 1)
1303          {
1304              $this->data[$byte] = $this->data[$byte] | chr(1 << $bit);
1305          }
1306          else
1307          {
1308              $this->data .= str_repeat("\0", $byte - strlen($this->data));
1309              $this->data .= chr(1 << $bit);
1310          }
1311      }
1312  
1313  	function clear($n)
1314      {
1315          $byte = $n >> 3;
1316  
1317          if (strlen($this->data) >= $byte + 1)
1318          {
1319              $bit = 7 - ($n & 7);
1320              $this->data[$byte] = $this->data[$byte] &~ chr(1 << $bit);
1321          }
1322      }
1323  
1324  	function get_blob()
1325      {
1326          return $this->data;
1327      }
1328  
1329  	function get_base64()
1330      {
1331          return base64_encode($this->data);
1332      }
1333  
1334  	function get_bin()
1335      {
1336          $bin = '';
1337          $len = strlen($this->data);
1338  
1339          for ($i = 0; $i < $len; ++$i)
1340          {
1341              $bin .= str_pad(decbin(ord($this->data[$i])), 8, '0', STR_PAD_LEFT);
1342          }
1343  
1344          return $bin;
1345      }
1346  
1347  	function get_all_set()
1348      {
1349          return array_keys(array_filter(str_split($this->get_bin())));
1350      }
1351  
1352  	function merge($bitfield)
1353      {
1354          $this->data = $this->data | $bitfield->get_blob();
1355      }
1356  }
1357  
1358  ?>


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1