[ Index ]

PHP Cross Reference of MyBB

title

Body

[close]

/inc/ -> functions_posting.php (source)

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


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