[ Index ]

PHP Cross Reference of MyBB 1.8.38

title

Body

[close]

/inc/ -> functions_posting.php (source)

   1  <?php
   2  /**
   3   * MyBB 1.8
   4   * Copyright 2014 MyBB Group, All Rights Reserved
   5   *
   6   * Website: http://www.mybb.com
   7   * License: http://www.mybb.com/about/license
   8   *
   9   */
  10  
  11  /**
  12   * Selectively removes quote tags from a message, depending on its nested depth.  This is to be used with reply with quote functions.
  13   * For malformed quote tag structures, will try to simulate how MyBB's parser handles the issue, but is slightly inaccurate.
  14   * Examples, with a cutoff depth of 2:
  15   *  #1. INPUT:  [quote]a[quote=me]b[quote]c[/quote][/quote][/quote]
  16   *     OUTPUT:  [quote]a[quote=me]b[/quote][/quote]
  17   *  #2. INPUT:  [quote=a][quote=b][quote=c][quote=d][/quote][quote=e][/quote][/quote][quote=f][/quote][/quote]
  18   *     OUTPUT:  [quote=a][quote=b][/quote][quote=f][/quote][/quote]
  19   *
  20   * @param string $text the message from which quotes are to be removed
  21   * @param integer $rmdepth nested depth at which quotes should be removed; if none supplied, will use MyBB's default; must be at least 0
  22   * @return string the original message passed in $text, but with quote tags selectively removed
  23   */
  24  function remove_message_quotes(&$text, $rmdepth=null)
  25  {
  26      if(!$text)
  27      {
  28          return $text;
  29      }
  30      if(!isset($rmdepth))
  31      {
  32          global $mybb;
  33          $rmdepth = $mybb->settings['maxquotedepth'];
  34      }
  35      $rmdepth = (int)$rmdepth;
  36  
  37      // find all tokens
  38      // note, at various places, we use the prefix "s" to denote "start" (ie [quote]) and "e" to denote "end" (ie [/quote])
  39      preg_match_all("#\[quote(=(?:&quot;|\"|')?.*?(?:&quot;|\"|')?)?\]#si", $text, $smatches, PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER);
  40      preg_match_all("#\[/quote\]#i", $text, $ematches, PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER);
  41  
  42      if(empty($smatches) || empty($ematches))
  43      {
  44          return $text;
  45      }
  46  
  47      // make things easier by only keeping offsets
  48      $soffsets = $eoffsets = array();
  49      foreach($smatches[0] as $id => $match)
  50      {
  51          $soffsets[] = $match[1];
  52      }
  53      $first_token = 0;
  54      if(isset($soffsets[0])) {
  55          $first_token = $soffsets[0];
  56      }
  57      // whilst we loop, also remove unnecessary end tokens at the start of string
  58      foreach($ematches[0] as $id => $match)
  59      {
  60          if($match[1] > $first_token)
  61          {
  62              $eoffsets[] = $match[1];
  63          }
  64      }
  65      unset($smatches, $ematches);
  66  
  67  
  68      // elmininate malformed quotes by parsing like the parser does (preg_replace in a while loop)
  69      // NOTE: this is slightly inaccurate because the parser considers [quote] and [quote=...] to be different things
  70      $good_offsets = array();
  71      while(!empty($soffsets) && !empty($eoffsets)) // don't rely on this condition - an end offset before the start offset will cause this to loop indefinitely
  72      {
  73          $last_offset = 0;
  74          foreach($soffsets as $sk => &$soffset)
  75          {
  76              if($soffset >= $last_offset)
  77              {
  78                  // search for corresponding eoffset
  79                  foreach($eoffsets as $ek => &$eoffset) // use foreach instead of for to get around indexing issues with unset
  80                  {
  81                      if($eoffset > $soffset)
  82                      {
  83                          // we've found a pair
  84                          $good_offsets[$soffset] = 1;
  85                          $good_offsets[$eoffset] = -1;
  86                          $last_offset = $eoffset;
  87  
  88                          unset($soffsets[$sk], $eoffsets[$ek]);
  89                          break;
  90                      }
  91                  }
  92              }
  93          }
  94  
  95          // remove any end offsets occurring before start offsets
  96          $first_start = reset($soffsets);
  97          foreach($eoffsets as $ek => &$eoffset)
  98          {
  99              if($eoffset < $first_start)
 100              {
 101                  unset($eoffsets[$ek]);
 102              }
 103              else
 104              {
 105                  break;
 106              }
 107          }
 108          // we don't need to remove start offsets after the last end offset, because the loop will deplete something before that
 109      }
 110  
 111      if(empty($good_offsets))
 112      {
 113          return $text;
 114      }
 115      ksort($good_offsets);
 116  
 117  
 118      // we now have a list of all the ordered tokens, ready to go through
 119      $depth = 0;
 120      $remove_regions = array();
 121      $tmp_start = 0;
 122      foreach($good_offsets as $offset => $dincr)
 123      {
 124          if($depth == $rmdepth && $dincr == 1)
 125          {
 126              $tmp_start = $offset;
 127          }
 128          $depth += $dincr;
 129          if($depth == $rmdepth && $dincr == -1)
 130          {
 131              $remove_regions[] = array($tmp_start, $offset);
 132          }
 133      }
 134  
 135      if(empty($remove_regions))
 136      {
 137          return $text;
 138      }
 139  
 140      // finally, remove the quotes from the string
 141      $newtext = '';
 142      $cpy_start = 0;
 143      foreach($remove_regions as &$region)
 144      {
 145          $newtext .= substr($text, $cpy_start, $region[0]-$cpy_start);
 146          $cpy_start = $region[1]+8; // 8 = strlen('[/quote]')
 147          // clean up newlines
 148          $next_char = $text[$region[1]+8];
 149          if($next_char == "\r" || $next_char == "\n")
 150          {
 151              ++$cpy_start;
 152              if($next_char == "\r" && $text[$region[1]+9] == "\n")
 153              {
 154                  ++$cpy_start;
 155              }
 156          }
 157      }
 158      // append remaining end text
 159      if(strlen($text) != $cpy_start)
 160      {
 161          $newtext .= substr($text, $cpy_start);
 162      }
 163  
 164      // we're done
 165      return $newtext;
 166  }
 167  
 168  /**
 169   * Performs cleanup of a quoted message, such as replacing /me commands, before presenting quoted post to the user.
 170   *
 171   * @param array $quoted_post quoted post info, taken from the DB (requires the 'message', 'username', 'pid' and 'dateline' entries to be set; will use 'userusername' if present. requires 'quote_is_pm' if quote message is from a private message)
 172   * @param boolean $remove_message_quotes whether to call remove_message_quotes() on the quoted message
 173   * @return string the cleaned up message, wrapped in a quote tag
 174   */
 175  
 176  function parse_quoted_message(&$quoted_post, $remove_message_quotes=true)
 177  {
 178      global $parser, $lang, $plugins;
 179      if(!isset($parser))
 180      {
 181          require_once  MYBB_ROOT."inc/class_parser.php";
 182          $parser = new postParser;
 183      }
 184  
 185      // Swap username over if we have a registered user
 186      if(isset($quoted_post['userusername']))
 187      {
 188          $quoted_post['username'] = $quoted_post['userusername'];
 189      }
 190      else
 191      {
 192          if(empty($quoted_post['username']))
 193          {
 194              $quoted_post['username'] = htmlspecialchars_uni($lang->guest);
 195          }
 196      }
 197      // Clean up the message
 198      $quoted_post['message'] = preg_replace(array(
 199          '#(^|\r|\n)/me ([^\r\n<]*)#i',
 200          '#(^|\r|\n)/slap ([^\r\n<]*)#i',
 201          '#\[attachment=([0-9]+?)\]#i'
 202      ), array(
 203          "\\1* {$quoted_post['username']} \\2",
 204          "\\1* {$quoted_post['username']} {$lang->slaps} \\2 {$lang->with_trout}",
 205          "",
 206      ), $quoted_post['message']);
 207      $quoted_post['message'] = $parser->parse_badwords($quoted_post['message']);
 208  
 209      if($remove_message_quotes)
 210      {
 211          global $mybb;
 212          $max_quote_depth = (int)$mybb->settings['maxquotedepth'];
 213          if($max_quote_depth)
 214          {
 215              $quoted_post['message'] = remove_message_quotes($quoted_post['message'], $max_quote_depth-1); // we're wrapping the message in a [quote] tag, so take away one quote depth level
 216          }
 217      }
 218  
 219      $quoted_post = $plugins->run_hooks("parse_quoted_message", $quoted_post);
 220  
 221      $extra = '';
 222      if(empty($quoted_post['quote_is_pm']))
 223      {
 224          $extra = " pid='{$quoted_post['pid']}' dateline='{$quoted_post['dateline']}'";
 225      }
 226  
 227      $quote_char = '"';
 228      if(strpos($quoted_post['username'], '"') !== false)
 229      {
 230          $quote_char = "'";
 231      }
 232  
 233      return "[quote={$quote_char}{$quoted_post['username']}{$quote_char}{$extra}]\n{$quoted_post['message']}\n[/quote]\n\n";
 234  }
 235  


2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup Cross-referenced by PHPXref