[ Index ] |
PHP Cross Reference of MyBB 1.8.38 |
[Summary view] [Print] [Text view]
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(=(?:"|\"|')?.*?(?:"|\"|')?)?\]#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
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
2005 - 2021 © MyBB.de | Alle Rechte vorbehalten! | Sponsor: netcup | Cross-referenced by PHPXref |