Verzeichnisstruktur phpBB-3.0.0


Veröffentlicht
12.12.2007

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_content.php

Zuletzt modifiziert: 09.10.2024, 12:50 - Dateigröße: 34.31 KiB


0001  <?php
0002  /**
0003  *
0004  * @package phpBB3
0005  * @version $Id$
0006  * @copyright (c) 2005 phpBB Group
0007  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
0008  *
0009  */
0010   
0011  /**
0012  * @ignore
0013  */
0014  if (!defined('IN_PHPBB'))
0015  {
0016      exit;
0017  }
0018   
0019  /**
0020  * gen_sort_selects()
0021  * make_jumpbox()
0022  * bump_topic_allowed()
0023  * get_context()
0024  * decode_message()
0025  * strip_bbcode()
0026  * generate_text_for_display()
0027  * generate_text_for_storage()
0028  * generate_text_for_edit()
0029  * make_clickable_callback()
0030  * make_clickable()
0031  * censor_text()
0032  * bbcode_nl2br()
0033  * smiley_text()
0034  * parse_attachments()
0035  * extension_allowed()
0036  * truncate_string()
0037  * get_username_string()
0038  * class bitfield
0039  */
0040   
0041  /**
0042  * Generate sort selection fields
0043  */
0044  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)
0045  {
0046      global $user;
0047   
0048      $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']);
0049   
0050      // Check if the key is selectable. If not, we reset to the first key found.
0051      // This ensures the values are always valid.
0052      if (!isset($limit_days[$sort_days]))
0053      {
0054          @reset($limit_days);
0055          $sort_days = key($limit_days);
0056      }
0057   
0058      if (!isset($sort_by_text[$sort_key]))
0059      {
0060          @reset($sort_by_text);
0061          $sort_key = key($sort_by_text);
0062      }
0063   
0064      if (!isset($sort_dir_text[$sort_dir]))
0065      {
0066          @reset($sort_dir_text);
0067          $sort_dir = key($sort_dir_text);
0068      }
0069   
0070      $s_limit_days = '<select name="st">';
0071      foreach ($limit_days as $day => $text)
0072      {
0073          $selected = ($sort_days == $day) ? ' selected="selected"' : '';
0074          $s_limit_days .= '<option value="' . $day . '"' . $selected . '>' . $text . '</option>';
0075      }
0076      $s_limit_days .= '</select>';
0077   
0078      $s_sort_key = '<select name="sk">';
0079      foreach ($sort_by_text as $key => $text)
0080      {
0081          $selected = ($sort_key == $key) ? ' selected="selected"' : '';
0082          $s_sort_key .= '<option value="' . $key . '"' . $selected . '>' . $text . '</option>';
0083      }
0084      $s_sort_key .= '</select>';
0085   
0086      $s_sort_dir = '<select name="sd">';
0087      foreach ($sort_dir_text as $key => $value)
0088      {
0089          $selected = ($sort_dir == $key) ? ' selected="selected"' : '';
0090          $s_sort_dir .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>';
0091      }
0092      $s_sort_dir .= '</select>';
0093   
0094      $u_sort_param = "st=$sort_days&amp;sk=$sort_key&amp;sd=$sort_dir";
0095   
0096      return;
0097  }
0098   
0099  /**
0100  * Generate Jumpbox
0101  */
0102  function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list = false, $force_display = false)
0103  {
0104      global $config, $auth, $template, $user, $db;
0105   
0106      // We only return if the jumpbox is not forced to be displayed (in case it is needed for functionality)
0107      if (!$config['load_jumpbox'] && $force_display === false)
0108      {
0109          return;
0110      }
0111   
0112      $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id
0113          FROM ' . FORUMS_TABLE . '
0114          ORDER BY left_id ASC';
0115      $result = $db->sql_query($sql, 600);
0116   
0117      $right = $padding = 0;
0118      $padding_store = array('0' => 0);
0119      $display_jumpbox = false;
0120      $iteration = 0;
0121   
0122      // Sometimes it could happen that forums will be displayed here not be displayed within the index page
0123      // This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions.
0124      // If this happens, the padding could be "broken"
0125   
0126      while ($row = $db->sql_fetchrow($result))
0127      {
0128          if ($row['left_id'] < $right)
0129          {
0130              $padding++;
0131              $padding_store[$row['parent_id']] = $padding;
0132          }
0133          else if ($row['left_id'] > $right + 1)
0134          {
0135              // Ok, if the $padding_store for this parent is empty there is something wrong. For now we will skip over it.
0136              // @todo digging deep to find out "how" this can happen.
0137              $padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : $padding;
0138          }
0139   
0140          $right = $row['right_id'];
0141   
0142          if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id']))
0143          {
0144              // Non-postable forum with no subforums, don't display
0145              continue;
0146          }
0147   
0148          if (!$auth->acl_get('f_list', $row['forum_id']))
0149          {
0150              // if the user does not have permissions to list this forum skip
0151              continue;
0152          }
0153   
0154          if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id']))
0155          {
0156              continue;
0157          }
0158   
0159          if (!$display_jumpbox)
0160          {
0161              $template->assign_block_vars('jumpbox_forums', array(
0162                  'FORUM_ID'        => ($select_all) ? 0 : -1,
0163                  'FORUM_NAME'    => ($select_all) ? $user->lang['ALL_FORUMS'] : $user->lang['SELECT_FORUM'],
0164                  'S_FORUM_COUNT'    => $iteration)
0165              );
0166   
0167              $iteration++;
0168              $display_jumpbox = true;
0169          }
0170   
0171          $template->assign_block_vars('jumpbox_forums', array(
0172              'FORUM_ID'        => $row['forum_id'],
0173              'FORUM_NAME'    => $row['forum_name'],
0174              'SELECTED'        => ($row['forum_id'] == $forum_id) ? ' selected="selected"' : '',
0175              'S_FORUM_COUNT'    => $iteration,
0176              'S_IS_CAT'        => ($row['forum_type'] == FORUM_CAT) ? true : false,
0177              'S_IS_LINK'        => ($row['forum_type'] == FORUM_LINK) ? true : false,
0178              'S_IS_POST'        => ($row['forum_type'] == FORUM_POST) ? true : false)
0179          );
0180   
0181          for ($i = 0; $i < $padding; $i++)
0182          {
0183              $template->assign_block_vars('jumpbox_forums.level', array());
0184          }
0185          $iteration++;
0186      }
0187      $db->sql_freeresult($result);
0188      unset($padding_store);
0189   
0190      $template->assign_vars(array(
0191          'S_DISPLAY_JUMPBOX'    => $display_jumpbox,
0192          'S_JUMPBOX_ACTION'    => $action)
0193      );
0194   
0195      return;
0196  }
0197   
0198  /**
0199  * Bump Topic Check - used by posting and viewtopic
0200  */
0201  function bump_topic_allowed($forum_id, $topic_bumped, $last_post_time, $topic_poster, $last_topic_poster)
0202  {
0203      global $config, $auth, $user;
0204   
0205      // Check permission and make sure the last post was not already bumped
0206      if (!$auth->acl_get('f_bump', $forum_id) || $topic_bumped)
0207      {
0208          return false;
0209      }
0210   
0211      // Check bump time range, is the user really allowed to bump the topic at this time?
0212      $bump_time = ($config['bump_type'] == 'm') ? $config['bump_interval'] * 60 : (($config['bump_type'] == 'h') ? $config['bump_interval'] * 3600 : $config['bump_interval'] * 86400);
0213   
0214      // Check bump time
0215      if ($last_post_time + $bump_time > time())
0216      {
0217          return false;
0218      }
0219   
0220      // Check bumper, only topic poster and last poster are allowed to bump
0221      if ($topic_poster != $user->data['user_id'] && $last_topic_poster != $user->data['user_id'])
0222      {
0223          return false;
0224      }
0225   
0226      // A bump time of 0 will completely disable the bump feature... not intended but might be useful.
0227      return $bump_time;
0228  }
0229   
0230  /**
0231  * Generates a text with approx. the specified length which contains the specified words and their context
0232  *
0233  * @param    string    $text    The full text from which context shall be extracted
0234  * @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!)
0235  * @param    int        $length    The desired length of the resulting text, however the result might be shorter or longer than this value
0236  *
0237  * @return    string            Context of the specified words separated by "..."
0238  */
0239  function get_context($text, $words, $length = 400)
0240  {
0241      // first replace all whitespaces with single spaces
0242      $text = preg_replace('/ +/', ' ', strtr($text, "\t\n\r\x0C ", '     '), $text);
0243   
0244      $word_indizes = array();
0245      if (sizeof($words))
0246      {
0247          $match = '';
0248          // find the starting indizes of all words
0249          foreach ($words as $word)
0250          {
0251              if ($word)
0252              {
0253                  if (preg_match('#(?:[^\w]|^)(' . $word . ')(?:[^\w]|$)#i', $text, $match))
0254                  {
0255                      $pos = utf8_strpos($text, $match[1]);
0256                      if ($pos !== false)
0257                      {
0258                          $word_indizes[] = $pos;
0259                      }
0260                  }
0261              }
0262          }
0263          unset($match);
0264   
0265          if (sizeof($word_indizes))
0266          {
0267              $word_indizes = array_unique($word_indizes);
0268              sort($word_indizes);
0269   
0270              $wordnum = sizeof($word_indizes);
0271              // number of characters on the right and left side of each word
0272              $sequence_length = (int) ($length / (2 * $wordnum)) - 2;
0273              $final_text = '';
0274              $word = $j = 0;
0275              $final_text_index = -1;
0276   
0277              // cycle through every character in the original text
0278              for ($i = $word_indizes[$word], $n = utf8_strlen($text); $i < $n; $i++)
0279              {
0280                  // if the current position is the start of one of the words then append $sequence_length characters to the final text
0281                  if (isset($word_indizes[$word]) && ($i == $word_indizes[$word]))
0282                  {
0283                      if ($final_text_index < $i - $sequence_length - 1)
0284                      {
0285                          $final_text .= '... ' . preg_replace('#^([^ ]*)#', '', utf8_substr($text, $i - $sequence_length, $sequence_length));
0286                      }
0287                      else
0288                      {
0289                          // if the final text is already nearer to the current word than $sequence_length we only append the text
0290                          // from its current index on and distribute the unused length to all other sequenes
0291                          $sequence_length += (int) (($final_text_index - $i + $sequence_length + 1) / (2 * $wordnum));
0292                          $final_text .= utf8_substr($text, $final_text_index + 1, $i - $final_text_index - 1);
0293                      }
0294                      $final_text_index = $i - 1;
0295   
0296                      // add the following characters to the final text (see below)
0297                      $word++;
0298                      $j = 1;
0299                  }
0300   
0301                  if ($j > 0)
0302                  {
0303                      // add the character to the final text and increment the sequence counter
0304                      $final_text .= utf8_substr($text, $i, 1);
0305                      $final_text_index++;
0306                      $j++;
0307   
0308                      // if this is a whitespace then check whether we are done with this sequence
0309                      if (utf8_substr($text, $i, 1) == ' ')
0310                      {
0311                          // only check whether we have to exit the context generation completely if we haven't already reached the end anyway
0312                          if ($i + 4 < $n)
0313                          {
0314                              if (($j > $sequence_length && $word >= $wordnum) || utf8_strlen($final_text) > $length)
0315                              {
0316                                  $final_text .= ' ...';
0317                                  break;
0318                              }
0319                          }
0320                          else
0321                          {
0322                              // make sure the text really reaches the end
0323                              $j -= 4;
0324                          }
0325   
0326                          // stop context generation and wait for the next word
0327                          if ($j > $sequence_length)
0328                          {
0329                              $j = 0;
0330                          }
0331                      }
0332                  }
0333              }
0334              return $final_text;
0335          }
0336      }
0337   
0338      if (!sizeof($words) || !sizeof($word_indizes))
0339      {
0340          return (utf8_strlen($text) >= $length + 3) ? utf8_substr($text, 0, $length) . '...' : $text;
0341      }
0342  }
0343   
0344  /**
0345  * Decode text whereby text is coming from the db and expected to be pre-parsed content
0346  * We are placing this outside of the message parser because we are often in need of it...
0347  */
0348  function decode_message(&$message, $bbcode_uid = '')
0349  {
0350      global $config;
0351   
0352      if ($bbcode_uid)
0353      {
0354          $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid");
0355          $replace = array("\n", '', '', '', '');
0356      }
0357      else
0358      {
0359          $match = array('<br />');
0360          $replace = array("\n");
0361      }
0362   
0363      $message = str_replace($match, $replace, $message);
0364   
0365      $match = get_preg_expression('bbcode_htm');
0366      $replace = array('\1', '\1', '\2', '\1', '', '');
0367   
0368      $message = preg_replace($match, $replace, $message);
0369  }
0370   
0371  /**
0372  * Strips all bbcode from a text and returns the plain content
0373  */
0374  function strip_bbcode(&$text, $uid = '')
0375  {
0376      if (!$uid)
0377      {
0378          $uid = '[0-9a-z]{5,}';
0379      }
0380   
0381      $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:&quot;.*&quot;|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text);
0382   
0383      $match = get_preg_expression('bbcode_htm');
0384      $replace = array('\1', '\1', '\2', '\1', '', '');
0385      
0386      $text = preg_replace($match, $replace, $text);
0387  }
0388   
0389  /**
0390  * For display of custom parsed text on user-facing pages
0391  * Expects $text to be the value directly from the database (stored value)
0392  */
0393  function generate_text_for_display($text, $uid, $bitfield, $flags)
0394  {
0395      static $bbcode;
0396   
0397      if (!$text)
0398      {
0399          return '';
0400      }
0401   
0402      $text = censor_text($text);
0403   
0404      // Parse bbcode if bbcode uid stored and bbcode enabled
0405      if ($uid && ($flags & OPTION_FLAG_BBCODE))
0406      {
0407          if (!class_exists('bbcode'))
0408          {
0409              global $phpbb_root_path, $phpEx;
0410              include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
0411          }
0412   
0413          if (empty($bbcode))
0414          {
0415              $bbcode = new bbcode($bitfield);
0416          }
0417          else
0418          {
0419              $bbcode->bbcode($bitfield);
0420          }
0421          
0422          $bbcode->bbcode_second_pass($text, $uid);
0423      }
0424   
0425      $text = bbcode_nl2br($text);
0426      $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES));
0427   
0428      return $text;
0429  }
0430   
0431  /**
0432  * For parsing custom parsed text to be stored within the database.
0433  * This function additionally returns the uid and bitfield that needs to be stored.
0434  * Expects $text to be the value directly from request_var() and in it's non-parsed form
0435  */
0436  function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false)
0437  {
0438      global $phpbb_root_path, $phpEx;
0439   
0440      $uid = $bitfield = '';
0441   
0442      if (!$text)
0443      {
0444          return;
0445      }
0446   
0447      if (!class_exists('parse_message'))
0448      {
0449          include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
0450      }
0451   
0452      $message_parser = new parse_message($text);
0453      $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies);
0454   
0455      $text = $message_parser->message;
0456      $uid = $message_parser->bbcode_uid;
0457   
0458      // If the bbcode_bitfield is empty, there is no need for the uid to be stored.
0459      if (!$message_parser->bbcode_bitfield)
0460      {
0461          $uid = '';
0462      }
0463   
0464      $flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0);
0465      $bitfield = $message_parser->bbcode_bitfield;
0466   
0467      return;
0468  }
0469   
0470  /**
0471  * For decoding custom parsed text for edits as well as extracting the flags
0472  * Expects $text to be the value directly from the database (pre-parsed content)
0473  */
0474  function generate_text_for_edit($text, $uid, $flags)
0475  {
0476      global $phpbb_root_path, $phpEx;
0477   
0478      decode_message($text, $uid);
0479   
0480      return array(
0481          'allow_bbcode'    => ($flags & OPTION_FLAG_BBCODE) ? 1 : 0,
0482          'allow_smilies'    => ($flags & OPTION_FLAG_SMILIES) ? 1 : 0,
0483          'allow_urls'    => ($flags & OPTION_FLAG_LINKS) ? 1 : 0,
0484          'text'            => $text
0485      );
0486  }
0487   
0488  /**
0489  * A subroutine of make_clickable used with preg_replace
0490  * It places correct HTML around an url, shortens the displayed text
0491  * and makes sure no entities are inside URLs
0492  */
0493  function make_clickable_callback($type, $whitespace, $url, $relative_url, $class)
0494  {
0495      $append            = '';
0496      $url            = htmlspecialchars_decode($url);
0497      $relative_url    = htmlspecialchars_decode($relative_url);
0498   
0499      // make sure no HTML entities were matched
0500      $chars = array('<', '>', '"');
0501      $split = false;
0502   
0503      foreach ($chars as $char)
0504      {
0505          $next_split = strpos($url, $char);
0506          if ($next_split !== false)
0507          {
0508              $split = ($split !== false) ? min($split, $next_split) : $next_split;
0509          }
0510      }
0511   
0512      if ($split !== false)
0513      {
0514          // an HTML entity was found, so the URL has to end before it
0515          $append            = substr($url, $split) . $relative_url;
0516          $url            = substr($url, 0, $split);
0517          $relative_url    = '';
0518      }
0519      else if ($relative_url)
0520      {
0521          // same for $relative_url
0522          $split = false;
0523          foreach ($chars as $char)
0524          {
0525              $next_split = strpos($relative_url, $char);
0526              if ($next_split !== false)
0527              {
0528                  $split = ($split !== false) ? min($split, $next_split) : $next_split;
0529              }
0530          }
0531   
0532          if ($split !== false)
0533          {
0534              $append            = substr($relative_url, $split);
0535              $relative_url    = substr($relative_url, 0, $split);
0536          }
0537      }
0538   
0539      // if the last character of the url is a punctuation mark, exclude it from the url
0540      $last_char = ($relative_url) ? $relative_url[strlen($relative_url) - 1] : $url[strlen($url) - 1];
0541   
0542      switch ($last_char)
0543      {
0544          case '.':
0545          case '?':
0546          case '!':
0547          case ':':
0548          case ',':
0549              $append = $last_char;
0550              if ($relative_url)
0551              {
0552                  $relative_url = substr($relative_url, 0, -1);
0553              }
0554              else
0555              {
0556                  $url = substr($url, 0, -1);
0557              }
0558          break;
0559      }
0560   
0561      switch ($type)
0562      {
0563          case MAGIC_URL_LOCAL:
0564              $tag            = 'l';
0565              $relative_url    = preg_replace('/[&?]sid=[0-9a-f]{32}$/', '', preg_replace('/([&?])sid=[0-9a-f]{32}&/', '$1', $relative_url));
0566              $url            = $url . '/' . $relative_url;
0567              $text            = ($relative_url) ? $relative_url : $url;
0568          break;
0569   
0570          case MAGIC_URL_FULL:
0571              $tag    = 'm';
0572              $text    = (strlen($url) > 55) ? substr($url, 0, 39) . ' ... ' . substr($url, -10) : $url;
0573          break;
0574   
0575          case MAGIC_URL_WWW:
0576              $tag    = 'w';
0577              $url    = 'http://' . $url;
0578              $text    = (strlen($url) > 55) ? substr($url, 0, 39) . ' ... ' . substr($url, -10) : $url;
0579          break;
0580   
0581          case MAGIC_URL_EMAIL:
0582              $tag    = 'e';
0583              $text    = (strlen($url) > 55) ? substr($url, 0, 39) . ' ... ' . substr($url, -10) : $url;
0584              $url    = 'mailto:' . $url;
0585          break;
0586      }
0587   
0588      $url    = htmlspecialchars($url);
0589      $text    = htmlspecialchars($text);
0590      $append    = htmlspecialchars($append);
0591   
0592      $html    = "$whitespace<!-- $tag --><a$class href=\"$url\">$text</a><!-- $tag -->$append";
0593   
0594      return $html;
0595  }
0596   
0597  /**
0598  * make_clickable function
0599  *
0600  * Replace magic urls of form http://xxx.xxx., www.xxx. and xxx@xxx.xxx.
0601  * Cuts down displayed size of link if over 50 chars, turns absolute links
0602  * into relative versions when the server/script path matches the link
0603  */
0604  function make_clickable($text, $server_url = false, $class = 'postlink')
0605  {
0606      if ($server_url === false)
0607      {
0608          $server_url = generate_board_url();
0609      }
0610   
0611      static $magic_url_match;
0612      static $magic_url_replace;
0613      static $static_class;
0614   
0615      if (!is_array($magic_url_match) || $static_class != $class)
0616      {
0617          $static_class = $class;
0618          $class = ($static_class) ? ' class="' . $static_class . '"' : '';
0619          $local_class = ($static_class) ? ' class="' . $static_class . '-local"' : '';
0620   
0621          $magic_url_match = $magic_url_replace = array();
0622          // Be sure to not let the matches cross over. ;)
0623   
0624          // relative urls for this board
0625          $magic_url_match[] = '#(^|[\n\t (>.])(' . preg_quote($server_url, '#') . ')/(' . get_preg_expression('relative_url_inline') . ')#ie';
0626          $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_LOCAL, '\$1', '\$2', '\$3', '$local_class')";
0627   
0628          // matches a xxxx://aaaaa.bbb.cccc. ...
0629          $magic_url_match[] = '#(^|[\n\t (>.])(' . get_preg_expression('url_inline') . ')#ie';
0630          $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_FULL, '\$1', '\$2', '', '$class')";
0631   
0632          // matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing
0633          $magic_url_match[] = '#(^|[\n\t (>])(' . get_preg_expression('www_url_inline') . ')#ie';
0634          $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_WWW, '\$1', '\$2', '', '$class')";
0635   
0636          // matches an email@domain type address at the start of a line, or after a space or after what might be a BBCode.
0637          $magic_url_match[] = '/(^|[\n\t (>])(' . get_preg_expression('email') . ')/ie';
0638          $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_EMAIL, '\$1', '\$2', '', '')";
0639      }
0640   
0641      return preg_replace($magic_url_match, $magic_url_replace, $text);
0642  }
0643   
0644  /**
0645  * Censoring
0646  */
0647  function censor_text($text)
0648  {
0649      static $censors;
0650      global $cache;
0651   
0652      if (!isset($censors) || !is_array($censors))
0653      {
0654          // obtain_word_list is taking care of the users censor option and the board-wide option
0655          $censors = $cache->obtain_word_list();
0656      }
0657   
0658      if (sizeof($censors))
0659      {
0660          return preg_replace($censors['match'], $censors['replace'], $text);
0661      }
0662   
0663      return $text;
0664  }
0665   
0666  /**
0667  * custom version of nl2br which takes custom BBCodes into account
0668  */
0669  function bbcode_nl2br($text)
0670  {
0671      // custom BBCodes might contain carriage returns so they
0672      // are not converted into <br /> so now revert that
0673      $text = str_replace(array("\n", "\r"), array('<br />', "\n"), $text);
0674      return $text;
0675  }
0676   
0677  /**
0678  * Smiley processing
0679  */
0680  function smiley_text($text, $force_option = false)
0681  {
0682      global $config, $user, $phpbb_root_path;
0683   
0684      if ($force_option || !$config['allow_smilies'] || !$user->optionget('viewsmilies'))
0685      {
0686          return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#', '\1', $text);
0687      }
0688      else
0689      {
0690          return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/(.*?) \/><!\-\- s\1 \-\->#', '<img src="' . $phpbb_root_path . $config['smilies_path'] . '/\2 />', $text);
0691      }
0692  }
0693   
0694  /**
0695  * General attachment parsing
0696  *
0697  * @param mixed $forum_id The forum id the attachments are displayed in (false if in private message)
0698  * @param string &$message The post/private message
0699  * @param array &$attachments The attachments to parse for (inline) display. The attachments array will hold templated data after parsing.
0700  * @param array &$update_count The attachment counts to be updated - will be filled
0701  * @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.
0702  */
0703  function parse_attachments($forum_id, &$message, &$attachments, &$update_count, $preview = false)
0704  {
0705      if (!sizeof($attachments))
0706      {
0707          return;
0708      }
0709   
0710      global $template, $cache, $user;
0711      global $extensions, $config, $phpbb_root_path, $phpEx;
0712   
0713      //
0714      $compiled_attachments = array();
0715   
0716      if (!isset($template->filename['attachment_tpl']))
0717      {
0718          $template->set_filenames(array(
0719              'attachment_tpl'    => 'attachment.html')
0720          );
0721      }
0722   
0723      if (empty($extensions) || !is_array($extensions))
0724      {
0725          $extensions = $cache->obtain_attach_extensions($forum_id);
0726      }
0727   
0728      // Look for missing attachment information...
0729      $attach_ids = array();
0730      foreach ($attachments as $pos => $attachment)
0731      {
0732          // If is_orphan is set, we need to retrieve the attachments again...
0733          if (!isset($attachment['extension']) && !isset($attachment['physical_filename']))
0734          {
0735              $attach_ids[(int) $attachment['attach_id']] = $pos;
0736          }
0737      }
0738   
0739      // Grab attachments (security precaution)
0740      if (sizeof($attach_ids))
0741      {
0742          global $db;
0743   
0744          $new_attachment_data = array();
0745   
0746          $sql = 'SELECT *
0747              FROM ' . ATTACHMENTS_TABLE . '
0748              WHERE ' . $db->sql_in_set('attach_id', array_keys($attach_ids));
0749          $result = $db->sql_query($sql);
0750   
0751          while ($row = $db->sql_fetchrow($result))
0752          {
0753              if (!isset($attach_ids[$row['attach_id']]))
0754              {
0755                  continue;
0756              }
0757   
0758              // If we preview attachments we will set some retrieved values here
0759              if ($preview)
0760              {
0761                  $row['attach_comment'] = $attachments[$attach_ids[$row['attach_id']]]['attach_comment'];
0762              }
0763   
0764              $new_attachment_data[$attach_ids[$row['attach_id']]] = $row;
0765          }
0766          $db->sql_freeresult($result);
0767   
0768          $attachments = $new_attachment_data;
0769          unset($new_attachment_data);
0770      }
0771   
0772      // Sort correctly
0773      if ($config['display_order'])
0774      {
0775          // Ascending sort
0776          krsort($attachments);
0777      }
0778      else
0779      {
0780          // Descending sort
0781          ksort($attachments);
0782      }
0783   
0784      foreach ($attachments as $attachment)
0785      {
0786          if (!sizeof($attachment))
0787          {
0788              continue;
0789          }
0790   
0791          // We need to reset/empty the _file block var, because this function might be called more than once
0792          $template->destroy_block_vars('_file');
0793   
0794          $block_array = array();
0795          
0796          // Some basics...
0797          $attachment['extension'] = strtolower(trim($attachment['extension']));
0798          $filename = $phpbb_root_path . $config['upload_path'] . '/' . basename($attachment['physical_filename']);
0799          $thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . basename($attachment['physical_filename']);
0800   
0801          $upload_icon = '';
0802   
0803          if (isset($extensions[$attachment['extension']]))
0804          {
0805              if ($user->img('icon_topic_attach', '') && !$extensions[$attachment['extension']]['upload_icon'])
0806              {
0807                  $upload_icon = $user->img('icon_topic_attach', '');
0808              }
0809              else if ($extensions[$attachment['extension']]['upload_icon'])
0810              {
0811                  $upload_icon = '<img src="' . $phpbb_root_path . $config['upload_icons_path'] . '/' . trim($extensions[$attachment['extension']]['upload_icon']) . '" alt="" />';
0812              }
0813          }
0814   
0815          $filesize = $attachment['filesize'];
0816          $size_lang = ($filesize >= 1048576) ? $user->lang['MB'] : ( ($filesize >= 1024) ? $user->lang['KB'] : $user->lang['BYTES'] );
0817          $filesize = ($filesize >= 1048576) ? round((round($filesize / 1048576 * 100) / 100), 2) : (($filesize >= 1024) ? round((round($filesize / 1024 * 100) / 100), 2) : $filesize);
0818   
0819          $comment = bbcode_nl2br(censor_text($attachment['attach_comment']));
0820   
0821          $block_array += array(
0822              'UPLOAD_ICON'        => $upload_icon,
0823              'FILESIZE'            => $filesize,
0824              'SIZE_LANG'            => $size_lang,
0825              'DOWNLOAD_NAME'        => basename($attachment['real_filename']),
0826              'COMMENT'            => $comment,
0827          );
0828   
0829          $denied = false;
0830   
0831          if (!extension_allowed($forum_id, $attachment['extension'], $extensions))
0832          {
0833              $denied = true;
0834   
0835              $block_array += array(
0836                  'S_DENIED'            => true,
0837                  'DENIED_MESSAGE'    => sprintf($user->lang['EXTENSION_DISABLED_AFTER_POSTING'], $attachment['extension'])
0838              );
0839          }
0840   
0841          if (!$denied)
0842          {
0843              $l_downloaded_viewed = $download_link = '';
0844              $display_cat = $extensions[$attachment['extension']]['display_cat'];
0845   
0846              if ($display_cat == ATTACHMENT_CATEGORY_IMAGE)
0847              {
0848                  if ($attachment['thumbnail'])
0849                  {
0850                      $display_cat = ATTACHMENT_CATEGORY_THUMB;
0851                  }
0852                  else
0853                  {
0854                      if ($config['img_display_inlined'])
0855                      {
0856                          if ($config['img_link_width'] || $config['img_link_height'])
0857                          {
0858                              $dimension = @getimagesize($filename);
0859   
0860                              // If the dimensions could not be determined or the image being 0x0 we display it as a link for safety purposes
0861                              if ($dimension === false || empty($dimension[0]) || empty($dimension[1]))
0862                              {
0863                                  $display_cat = ATTACHMENT_CATEGORY_NONE;
0864                              }
0865                              else
0866                              {
0867                                  $display_cat = ($dimension[0] <= $config['img_link_width'] && $dimension[1] <= $config['img_link_height']) ? ATTACHMENT_CATEGORY_IMAGE : ATTACHMENT_CATEGORY_NONE;
0868                              }
0869                          }
0870                      }
0871                      else
0872                      {
0873                          $display_cat = ATTACHMENT_CATEGORY_NONE;
0874                      }
0875                  }
0876              }
0877   
0878              // Make some descisions based on user options being set.
0879              if (($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !$user->optionget('viewimg'))
0880              {
0881                  $display_cat = ATTACHMENT_CATEGORY_NONE;
0882              }
0883   
0884              if ($display_cat == ATTACHMENT_CATEGORY_FLASH && !$user->optionget('viewflash'))
0885              {
0886                  $display_cat = ATTACHMENT_CATEGORY_NONE;
0887              }
0888   
0889              $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']);
0890   
0891              switch ($display_cat)
0892              {
0893                  // Images
0894                  case ATTACHMENT_CATEGORY_IMAGE:
0895                      $l_downloaded_viewed = 'VIEWED_COUNT';
0896                      $inline_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']);
0897                      $download_link .= '&amp;mode=view';
0898   
0899                      $block_array += array(
0900                          'S_IMAGE'        => true,
0901                          'U_INLINE_LINK'        => $inline_link,
0902                      );
0903   
0904                      $update_count[] = $attachment['attach_id'];
0905                  break;
0906   
0907                  // Images, but display Thumbnail
0908                  case ATTACHMENT_CATEGORY_THUMB:
0909                      $l_downloaded_viewed = 'VIEWED_COUNT';
0910                      $thumbnail_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id'] . '&amp;t=1');
0911                      $download_link .= '&amp;mode=view';
0912   
0913                      $block_array += array(
0914                          'S_THUMBNAIL'        => true,
0915                          'THUMB_IMAGE'        => $thumbnail_link,
0916                      );
0917                  break;
0918   
0919                  // Windows Media Streams
0920                  case ATTACHMENT_CATEGORY_WM:
0921                      $l_downloaded_viewed = 'VIEWED_COUNT';
0922   
0923                      // Giving the filename directly because within the wm object all variables are in local context making it impossible
0924                      // to validate against a valid session (all params can differ)
0925                      // $download_link = $filename;
0926   
0927                      $block_array += array(
0928                          'U_FORUM'        => generate_board_url(),
0929                          'ATTACH_ID'        => $attachment['attach_id'],
0930                          'S_WM_FILE'        => true,
0931                      );
0932   
0933                      // Viewed/Heared File ... update the download count
0934                      $update_count[] = $attachment['attach_id'];
0935                  break;
0936   
0937                  // Real Media Streams
0938                  case ATTACHMENT_CATEGORY_RM:
0939                  case ATTACHMENT_CATEGORY_QUICKTIME:
0940                      $l_downloaded_viewed = 'VIEWED_COUNT';
0941   
0942                      $block_array += array(
0943                          'S_RM_FILE'            => ($display_cat == ATTACHMENT_CATEGORY_RM) ? true : false,
0944                          'S_QUICKTIME_FILE'    => ($display_cat == ATTACHMENT_CATEGORY_QUICKTIME) ? true : false,
0945                          'U_FORUM'            => generate_board_url(),
0946                          'ATTACH_ID'            => $attachment['attach_id'],
0947                      );
0948   
0949                      // Viewed/Heared File ... update the download count
0950                      $update_count[] = $attachment['attach_id'];
0951                  break;
0952   
0953                  // Macromedia Flash Files
0954                  case ATTACHMENT_CATEGORY_FLASH:
0955                      list($width, $height) = @getimagesize($filename);
0956   
0957                      $l_downloaded_viewed = 'VIEWED_COUNT';
0958   
0959                      $block_array += array(
0960                          'S_FLASH_FILE'    => true,
0961                          'WIDTH'            => $width,
0962                          'HEIGHT'        => $height,
0963                      );
0964   
0965                      // Viewed/Heared File ... update the download count
0966                      $update_count[] = $attachment['attach_id'];
0967                  break;
0968   
0969                  default:
0970                      $l_downloaded_viewed = 'DOWNLOAD_COUNT';
0971   
0972                      $block_array += array(
0973                          'S_FILE'        => true,
0974                      );
0975                  break;
0976              }
0977   
0978              $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']));
0979   
0980              $block_array += array(
0981                  'U_DOWNLOAD_LINK'        => $download_link,
0982                  'L_DOWNLOAD_COUNT'        => $l_download_count
0983              );
0984          }
0985   
0986          $template->assign_block_vars('_file', $block_array);
0987   
0988          $compiled_attachments[] = $template->assign_display('attachment_tpl');
0989      }
0990   
0991      $attachments = $compiled_attachments;
0992      unset($compiled_attachments);
0993   
0994      $tpl_size = sizeof($attachments);
0995   
0996      $unset_tpl = array();
0997   
0998      preg_match_all('#<!\-\- ia([0-9]+) \-\->(.*?)<!\-\- ia\1 \-\->#', $message, $matches, PREG_PATTERN_ORDER);
0999   
1000      $replace = array();
1001      foreach ($matches[0] as $num => $capture)
1002      {
1003          // Flip index if we are displaying the reverse way
1004          $index = ($config['display_order']) ? ($tpl_size-($matches[1][$num] + 1)) : $matches[1][$num];
1005   
1006          $replace['from'][] = $matches[0][$num];
1007          $replace['to'][] = (isset($attachments[$index])) ? $attachments[$index] : sprintf($user->lang['MISSING_INLINE_ATTACHMENT'], $matches[2][array_search($index, $matches[1])]);
1008   
1009          $unset_tpl[] = $index;
1010      }
1011   
1012      if (isset($replace['from']))
1013      {
1014          $message = str_replace($replace['from'], $replace['to'], $message);
1015      }
1016   
1017      $unset_tpl = array_unique($unset_tpl);
1018   
1019      // Needed to let not display the inlined attachments at the end of the post again
1020      foreach ($unset_tpl as $index)
1021      {
1022          unset($attachments[$index]);
1023      }
1024  }
1025   
1026  /**
1027  * Check if extension is allowed to be posted.
1028  *
1029  * @param mixed $forum_id The forum id to check or false if private message
1030  * @param string $extension The extension to check, for example zip.
1031  * @param array &$extensions The extension array holding the information from the cache (will be obtained if empty)
1032  *
1033  * @return bool False if the extension is not allowed to be posted, else true.
1034  */
1035  function extension_allowed($forum_id, $extension, &$extensions)
1036  {
1037      if (empty($extensions))
1038      {
1039          global $cache;
1040          $extensions = $cache->obtain_attach_extensions($forum_id);
1041      }
1042   
1043      return (!isset($extensions['_allowed_'][$extension])) ? false : true;
1044  }
1045   
1046  /**
1047  * Truncates string while retaining special characters if going over the max length
1048  * The default max length is 60 at the moment
1049  */
1050  function truncate_string($string, $max_length = 60, $allow_reply = true, $append = '')
1051  {
1052      $chars = array();
1053   
1054      $strip_reply = false;
1055      $stripped = false;
1056      if ($allow_reply && strpos($string, 'Re: ') === 0)
1057      {
1058          $strip_reply = true;
1059          $string = substr($string, 4);
1060      }
1061   
1062      $_chars = utf8_str_split(htmlspecialchars_decode($string));
1063      $chars = array_map('utf8_htmlspecialchars', $_chars);
1064   
1065      // Now check the length ;)
1066      if (sizeof($chars) > $max_length)
1067      {
1068          // Cut off the last elements from the array
1069          $string = implode('', array_slice($chars, 0, $max_length - utf8_strlen($append)));
1070          $stripped = true;
1071      }
1072   
1073      if ($strip_reply)
1074      {
1075          $string = 'Re: ' . $string;
1076      }
1077      
1078      if ($append != '' && $stripped)
1079      {
1080          $string = $string . $append;
1081      }
1082   
1083      return $string;
1084  }
1085   
1086  /**
1087  * Get username details for placing into templates.
1088  *
1089  * @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)
1090  * @param int $user_id The users id
1091  * @param string $username The users name
1092  * @param string $username_colour The users colour
1093  * @param string $guest_username optional parameter to specify the guest username. It will be used in favor of the GUEST language variable then.
1094  * @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}
1095  *
1096  * @return string A string consisting of what is wanted based on $mode.
1097  */
1098  function get_username_string($mode, $user_id, $username, $username_colour = '', $guest_username = false, $custom_profile_url = false)
1099  {
1100      global $phpbb_root_path, $phpEx, $user, $auth;
1101   
1102      $profile_url = '';
1103      $username_colour = ($username_colour) ? '#' . $username_colour : '';
1104   
1105      if ($guest_username === false)
1106      {
1107          $username = ($username) ? $username : $user->lang['GUEST'];
1108      }
1109      else
1110      {
1111          $username = ($user_id && $user_id != ANONYMOUS) ? $username : ((!empty($guest_username)) ? $guest_username : $user->lang['GUEST']);
1112      }
1113   
1114      // Only show the link if not anonymous
1115      if ($mode != 'no_profile' && $user_id && $user_id != ANONYMOUS)
1116      {
1117          // Do not show the link if the user is already logged in but do not have u_viewprofile permissions (relevant for bots mostly).
1118          // For all others the link leads to a login page or the profile.
1119          if ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile'))
1120          {
1121              $profile_url = '';
1122          }
1123          else
1124          {
1125              $profile_url = ($custom_profile_url !== false) ? $custom_profile_url . '&amp;u=' . (int) $user_id : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&amp;u=' . (int) $user_id);
1126          }
1127      }
1128      else
1129      {
1130          $profile_url = '';
1131      }
1132   
1133      switch ($mode)
1134      {
1135          case 'profile':
1136              return $profile_url;
1137          break;
1138   
1139          case 'username':
1140              return $username;
1141          break;
1142   
1143          case 'colour':
1144              return $username_colour;
1145          break;
1146   
1147          case 'no_profile':
1148          case 'full':
1149          default:
1150   
1151              $tpl = '';
1152              if (!$profile_url && !$username_colour)
1153              {
1154                  $tpl = '{USERNAME}';
1155              }
1156              else if (!$profile_url && $username_colour)
1157              {
1158                  $tpl = '<span style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</span>';
1159              }
1160              else if ($profile_url && !$username_colour)
1161              {
1162                  $tpl = '<a href="{PROFILE_URL}">{USERNAME}</a>';
1163              }
1164              else if ($profile_url && $username_colour)
1165              {
1166                  $tpl = '<a href="{PROFILE_URL}" style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</a>';
1167              }
1168   
1169              return str_replace(array('{PROFILE_URL}', '{USERNAME_COLOUR}', '{USERNAME}'), array($profile_url, $username_colour, $username), $tpl);
1170          break;
1171      }
1172  }
1173   
1174  /**
1175  * @package phpBB3
1176  */
1177  class bitfield
1178  {
1179      var $data;
1180   
1181      function bitfield($bitfield = '')
1182      {
1183          $this->data = base64_decode($bitfield);
1184      }
1185   
1186      /**
1187      */
1188      function get($n)
1189      {
1190          // Get the ($n / 8)th char
1191          $byte = $n >> 3;
1192   
1193          if (strlen($this->data) >= $byte + 1)
1194          {
1195              $c = $this->data[$byte];
1196      
1197              // Lookup the ($n % 8)th bit of the byte
1198              $bit = 7 - ($n & 7);
1199              return (bool) (ord($c) & (1 << $bit));
1200          }
1201          else
1202          {
1203              return false;
1204          }
1205      }
1206   
1207      function set($n)
1208      {
1209          $byte = $n >> 3;
1210          $bit = 7 - ($n & 7);
1211   
1212          if (strlen($this->data) >= $byte + 1)
1213          {
1214              $this->data[$byte] = $this->data[$byte] | chr(1 << $bit);
1215          }
1216          else
1217          {
1218              $this->data .= str_repeat("\0", $byte - strlen($this->data));
1219              $this->data .= chr(1 << $bit);
1220          }
1221      }
1222   
1223      function clear($n)
1224      {
1225          $byte = $n >> 3;
1226   
1227          if (strlen($this->data) >= $byte + 1)
1228          {
1229              $bit = 7 - ($n & 7);
1230              $this->data[$byte] = $this->data[$byte] &~ chr(1 << $bit);
1231          }
1232      }
1233   
1234      function get_blob()
1235      {
1236          return $this->data;
1237      }
1238   
1239      function get_base64()
1240      {
1241          return base64_encode($this->data);
1242      }
1243   
1244      function get_bin()
1245      {
1246          $bin = '';
1247          $len = strlen($this->data);
1248   
1249          for ($i = 0; $i < $len; ++$i)
1250          {
1251              $bin .= str_pad(decbin(ord($this->data[$i])), 8, '0', STR_PAD_LEFT);
1252          }
1253   
1254          return $bin;
1255      }
1256   
1257      function get_all_set()
1258      {
1259          return array_keys(array_filter(str_split($this->get_bin())));
1260      }
1261   
1262      function merge($bitfield)
1263      {
1264          $this->data = $this->data | $bitfield->get_blob();
1265      }
1266  }
1267   
1268  ?>