wikimedia /
mediawiki
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * Classes used to send e-mails |
||
| 4 | * |
||
| 5 | * This program is free software; you can redistribute it and/or modify |
||
| 6 | * it under the terms of the GNU General Public License as published by |
||
| 7 | * the Free Software Foundation; either version 2 of the License, or |
||
| 8 | * (at your option) any later version. |
||
| 9 | * |
||
| 10 | * This program is distributed in the hope that it will be useful, |
||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 13 | * GNU General Public License for more details. |
||
| 14 | * |
||
| 15 | * You should have received a copy of the GNU General Public License along |
||
| 16 | * with this program; if not, write to the Free Software Foundation, Inc., |
||
| 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
| 18 | * http://www.gnu.org/copyleft/gpl.html |
||
| 19 | * |
||
| 20 | * @file |
||
| 21 | * @author <[email protected]> |
||
| 22 | * @author <[email protected]> |
||
| 23 | * @author Tim Starling |
||
| 24 | * @author Luke Welling [email protected] |
||
| 25 | */ |
||
| 26 | |||
| 27 | /** |
||
| 28 | * Collection of static functions for sending mail |
||
| 29 | */ |
||
| 30 | class UserMailer { |
||
| 31 | private static $mErrorString; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * Send mail using a PEAR mailer |
||
| 35 | * |
||
| 36 | * @param Mail_smtp $mailer |
||
| 37 | * @param string $dest |
||
| 38 | * @param string $headers |
||
| 39 | * @param string $body |
||
| 40 | * |
||
| 41 | * @return Status |
||
| 42 | */ |
||
| 43 | protected static function sendWithPear( $mailer, $dest, $headers, $body ) { |
||
| 44 | $mailResult = $mailer->send( $dest, $headers, $body ); |
||
| 45 | |||
| 46 | // Based on the result return an error string, |
||
| 47 | View Code Duplication | if ( PEAR::isError( $mailResult ) ) { |
|
| 48 | wfDebug( "PEAR::Mail failed: " . $mailResult->getMessage() . "\n" ); |
||
| 49 | return Status::newFatal( 'pear-mail-error', $mailResult->getMessage() ); |
||
| 50 | } else { |
||
| 51 | return Status::newGood(); |
||
| 52 | } |
||
| 53 | } |
||
| 54 | |||
| 55 | /** |
||
| 56 | * Creates a single string from an associative array |
||
| 57 | * |
||
| 58 | * @param array $headers Associative Array: keys are header field names, |
||
| 59 | * values are ... values. |
||
| 60 | * @param string $endl The end of line character. Defaults to "\n" |
||
| 61 | * |
||
| 62 | * Note RFC2822 says newlines must be CRLF (\r\n) |
||
| 63 | * but php mail naively "corrects" it and requires \n for the "correction" to work |
||
| 64 | * |
||
| 65 | * @return string |
||
| 66 | */ |
||
| 67 | static function arrayToHeaderString( $headers, $endl = PHP_EOL ) { |
||
| 68 | $strings = []; |
||
| 69 | foreach ( $headers as $name => $value ) { |
||
| 70 | // Prevent header injection by stripping newlines from value |
||
| 71 | $value = self::sanitizeHeaderValue( $value ); |
||
| 72 | $strings[] = "$name: $value"; |
||
| 73 | } |
||
| 74 | return implode( $endl, $strings ); |
||
| 75 | } |
||
| 76 | |||
| 77 | /** |
||
| 78 | * Create a value suitable for the MessageId Header |
||
| 79 | * |
||
| 80 | * @return string |
||
| 81 | */ |
||
| 82 | static function makeMsgId() { |
||
| 83 | global $wgSMTP, $wgServer; |
||
| 84 | |||
| 85 | $msgid = uniqid( wfWikiID() . ".", true ); /* true required for cygwin */ |
||
| 86 | if ( is_array( $wgSMTP ) && isset( $wgSMTP['IDHost'] ) && $wgSMTP['IDHost'] ) { |
||
| 87 | $domain = $wgSMTP['IDHost']; |
||
| 88 | } else { |
||
| 89 | $url = wfParseUrl( $wgServer ); |
||
| 90 | $domain = $url['host']; |
||
| 91 | } |
||
| 92 | return "<$msgid@$domain>"; |
||
| 93 | } |
||
| 94 | |||
| 95 | /** |
||
| 96 | * This function will perform a direct (authenticated) login to |
||
| 97 | * a SMTP Server to use for mail relaying if 'wgSMTP' specifies an |
||
| 98 | * array of parameters. It requires PEAR:Mail to do that. |
||
| 99 | * Otherwise it just uses the standard PHP 'mail' function. |
||
| 100 | * |
||
| 101 | * @param MailAddress|MailAddress[] $to Recipient's email (or an array of them) |
||
| 102 | * @param MailAddress $from Sender's email |
||
| 103 | * @param string $subject Email's subject. |
||
| 104 | * @param string $body Email's text or Array of two strings to be the text and html bodies |
||
| 105 | * @param array $options: |
||
|
0 ignored issues
–
show
|
|||
| 106 | * 'replyTo' MailAddress |
||
| 107 | * 'contentType' string default 'text/plain; charset=UTF-8' |
||
| 108 | * 'headers' array Extra headers to set |
||
| 109 | * |
||
| 110 | * @throws MWException |
||
| 111 | * @throws Exception |
||
| 112 | * @return Status |
||
| 113 | */ |
||
| 114 | public static function send( $to, $from, $subject, $body, $options = [] ) { |
||
| 115 | global $wgAllowHTMLEmail; |
||
| 116 | |||
| 117 | if ( !isset( $options['contentType'] ) ) { |
||
| 118 | $options['contentType'] = 'text/plain; charset=UTF-8'; |
||
| 119 | } |
||
| 120 | |||
| 121 | if ( !is_array( $to ) ) { |
||
| 122 | $to = [ $to ]; |
||
| 123 | } |
||
| 124 | |||
| 125 | // mail body must have some content |
||
| 126 | $minBodyLen = 10; |
||
| 127 | // arbitrary but longer than Array or Object to detect casting error |
||
| 128 | |||
| 129 | // body must either be a string or an array with text and body |
||
| 130 | if ( |
||
| 131 | !( |
||
| 132 | !is_array( $body ) && |
||
| 133 | strlen( $body ) >= $minBodyLen |
||
| 134 | ) |
||
| 135 | && |
||
| 136 | !( |
||
| 137 | is_array( $body ) && |
||
| 138 | isset( $body['text'] ) && |
||
| 139 | isset( $body['html'] ) && |
||
| 140 | strlen( $body['text'] ) >= $minBodyLen && |
||
| 141 | strlen( $body['html'] ) >= $minBodyLen |
||
| 142 | ) |
||
| 143 | ) { |
||
| 144 | // if it is neither we have a problem |
||
| 145 | return Status::newFatal( 'user-mail-no-body' ); |
||
| 146 | } |
||
| 147 | |||
| 148 | if ( !$wgAllowHTMLEmail && is_array( $body ) ) { |
||
| 149 | // HTML not wanted. Dump it. |
||
| 150 | $body = $body['text']; |
||
| 151 | } |
||
| 152 | |||
| 153 | wfDebug( __METHOD__ . ': sending mail to ' . implode( ', ', $to ) . "\n" ); |
||
| 154 | |||
| 155 | // Make sure we have at least one address |
||
| 156 | $has_address = false; |
||
| 157 | foreach ( $to as $u ) { |
||
| 158 | if ( $u->address ) { |
||
| 159 | $has_address = true; |
||
| 160 | break; |
||
| 161 | } |
||
| 162 | } |
||
| 163 | if ( !$has_address ) { |
||
| 164 | return Status::newFatal( 'user-mail-no-addy' ); |
||
| 165 | } |
||
| 166 | |||
| 167 | // give a chance to UserMailerTransformContents subscribers who need to deal with each |
||
| 168 | // target differently to split up the address list |
||
| 169 | if ( count( $to ) > 1 ) { |
||
| 170 | $oldTo = $to; |
||
| 171 | Hooks::run( 'UserMailerSplitTo', [ &$to ] ); |
||
| 172 | if ( $oldTo != $to ) { |
||
| 173 | $splitTo = array_diff( $oldTo, $to ); |
||
| 174 | $to = array_diff( $oldTo, $splitTo ); // ignore new addresses added in the hook |
||
| 175 | // first send to non-split address list, then to split addresses one by one |
||
| 176 | $status = Status::newGood(); |
||
| 177 | if ( $to ) { |
||
| 178 | $status->merge( UserMailer::sendInternal( |
||
| 179 | $to, $from, $subject, $body, $options ) ); |
||
| 180 | } |
||
| 181 | foreach ( $splitTo as $newTo ) { |
||
| 182 | $status->merge( UserMailer::sendInternal( |
||
| 183 | [ $newTo ], $from, $subject, $body, $options ) ); |
||
| 184 | } |
||
| 185 | return $status; |
||
| 186 | } |
||
| 187 | } |
||
| 188 | |||
| 189 | return UserMailer::sendInternal( $to, $from, $subject, $body, $options ); |
||
| 190 | } |
||
| 191 | |||
| 192 | /** |
||
| 193 | * Helper function fo UserMailer::send() which does the actual sending. It expects a $to |
||
| 194 | * list which the UserMailerSplitTo hook would not split further. |
||
| 195 | * @param MailAddress[] $to Array of recipients' email addresses |
||
| 196 | * @param MailAddress $from Sender's email |
||
| 197 | * @param string $subject Email's subject. |
||
| 198 | * @param string $body Email's text or Array of two strings to be the text and html bodies |
||
| 199 | * @param array $options: |
||
|
0 ignored issues
–
show
There is no parameter named
$options:. Did you maybe mean $options?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit. Consider the following example. The parameter /**
* @param array $germany
* @param array $ireland
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was changed, but the annotation was not. Loading history...
|
|||
| 200 | * 'replyTo' MailAddress |
||
| 201 | * 'contentType' string default 'text/plain; charset=UTF-8' |
||
| 202 | * 'headers' array Extra headers to set |
||
| 203 | * |
||
| 204 | * @throws MWException |
||
| 205 | * @throws Exception |
||
| 206 | * @return Status |
||
| 207 | */ |
||
| 208 | protected static function sendInternal( |
||
| 209 | array $to, |
||
| 210 | MailAddress $from, |
||
| 211 | $subject, |
||
| 212 | $body, |
||
| 213 | $options = [] |
||
| 214 | ) { |
||
| 215 | global $wgSMTP, $wgEnotifMaxRecips, $wgAdditionalMailParams; |
||
| 216 | $mime = null; |
||
| 217 | |||
| 218 | $replyto = isset( $options['replyTo'] ) ? $options['replyTo'] : null; |
||
| 219 | $contentType = isset( $options['contentType'] ) ? |
||
| 220 | $options['contentType'] : 'text/plain; charset=UTF-8'; |
||
| 221 | $headers = isset( $options['headers'] ) ? $options['headers'] : []; |
||
| 222 | |||
| 223 | // Allow transformation of content, such as encrypting/signing |
||
| 224 | $error = false; |
||
| 225 | View Code Duplication | if ( !Hooks::run( 'UserMailerTransformContent', [ $to, $from, &$body, &$error ] ) ) { |
|
| 226 | if ( $error ) { |
||
| 227 | return Status::newFatal( 'php-mail-error', $error ); |
||
| 228 | } else { |
||
| 229 | return Status::newFatal( 'php-mail-error-unknown' ); |
||
| 230 | } |
||
| 231 | } |
||
| 232 | |||
| 233 | /** |
||
| 234 | * Forge email headers |
||
| 235 | * ------------------- |
||
| 236 | * |
||
| 237 | * WARNING |
||
| 238 | * |
||
| 239 | * DO NOT add To: or Subject: headers at this step. They need to be |
||
| 240 | * handled differently depending upon the mailer we are going to use. |
||
| 241 | * |
||
| 242 | * To: |
||
| 243 | * PHP mail() first argument is the mail receiver. The argument is |
||
| 244 | * used as a recipient destination and as a To header. |
||
| 245 | * |
||
| 246 | * PEAR mailer has a recipient argument which is only used to |
||
| 247 | * send the mail. If no To header is given, PEAR will set it to |
||
| 248 | * to 'undisclosed-recipients:'. |
||
| 249 | * |
||
| 250 | * NOTE: To: is for presentation, the actual recipient is specified |
||
| 251 | * by the mailer using the Rcpt-To: header. |
||
| 252 | * |
||
| 253 | * Subject: |
||
| 254 | * PHP mail() second argument to pass the subject, passing a Subject |
||
| 255 | * as an additional header will result in a duplicate header. |
||
| 256 | * |
||
| 257 | * PEAR mailer should be passed a Subject header. |
||
| 258 | * |
||
| 259 | * -- hashar 20120218 |
||
| 260 | */ |
||
| 261 | |||
| 262 | $headers['From'] = $from->toString(); |
||
| 263 | $returnPath = $from->address; |
||
| 264 | $extraParams = $wgAdditionalMailParams; |
||
| 265 | |||
| 266 | // Hook to generate custom VERP address for 'Return-Path' |
||
| 267 | Hooks::run( 'UserMailerChangeReturnPath', [ $to, &$returnPath ] ); |
||
| 268 | // Add the envelope sender address using the -f command line option when PHP mail() is used. |
||
| 269 | // Will default to the $from->address when the UserMailerChangeReturnPath hook fails and the |
||
| 270 | // generated VERP address when the hook runs effectively. |
||
| 271 | $extraParams .= ' -f ' . $returnPath; |
||
| 272 | |||
| 273 | $headers['Return-Path'] = $returnPath; |
||
| 274 | |||
| 275 | if ( $replyto ) { |
||
| 276 | $headers['Reply-To'] = $replyto->toString(); |
||
| 277 | } |
||
| 278 | |||
| 279 | $headers['Date'] = MWTimestamp::getLocalInstance()->format( 'r' ); |
||
| 280 | $headers['Message-ID'] = self::makeMsgId(); |
||
| 281 | $headers['X-Mailer'] = 'MediaWiki mailer'; |
||
| 282 | $headers['List-Unsubscribe'] = '<' . SpecialPage::getTitleFor( 'Preferences' ) |
||
| 283 | ->getFullURL( '', false, PROTO_CANONICAL ) . '>'; |
||
| 284 | |||
| 285 | // Line endings need to be different on Unix and Windows due to |
||
| 286 | // the bug described at https://core.trac.wordpress.org/ticket/2603 |
||
| 287 | $endl = PHP_EOL; |
||
| 288 | |||
| 289 | if ( is_array( $body ) ) { |
||
| 290 | // we are sending a multipart message |
||
| 291 | wfDebug( "Assembling multipart mime email\n" ); |
||
| 292 | if ( !stream_resolve_include_path( 'Mail/mime.php' ) ) { |
||
| 293 | wfDebug( "PEAR Mail_Mime package is not installed. Falling back to text email.\n" ); |
||
| 294 | // remove the html body for text email fall back |
||
| 295 | $body = $body['text']; |
||
| 296 | } else { |
||
| 297 | // Check if pear/mail_mime is already loaded (via composer) |
||
| 298 | if ( !class_exists( 'Mail_mime' ) ) { |
||
| 299 | require_once 'Mail/mime.php'; |
||
| 300 | } |
||
| 301 | if ( wfIsWindows() ) { |
||
| 302 | $body['text'] = str_replace( "\n", "\r\n", $body['text'] ); |
||
| 303 | $body['html'] = str_replace( "\n", "\r\n", $body['html'] ); |
||
| 304 | } |
||
| 305 | $mime = new Mail_mime( [ |
||
| 306 | 'eol' => $endl, |
||
| 307 | 'text_charset' => 'UTF-8', |
||
| 308 | 'html_charset' => 'UTF-8' |
||
| 309 | ] ); |
||
| 310 | $mime->setTXTBody( $body['text'] ); |
||
| 311 | $mime->setHTMLBody( $body['html'] ); |
||
| 312 | $body = $mime->get(); // must call get() before headers() |
||
| 313 | $headers = $mime->headers( $headers ); |
||
| 314 | } |
||
| 315 | } |
||
| 316 | if ( $mime === null ) { |
||
| 317 | // sending text only, either deliberately or as a fallback |
||
| 318 | if ( wfIsWindows() ) { |
||
| 319 | $body = str_replace( "\n", "\r\n", $body ); |
||
| 320 | } |
||
| 321 | $headers['MIME-Version'] = '1.0'; |
||
| 322 | $headers['Content-type'] = $contentType; |
||
| 323 | $headers['Content-transfer-encoding'] = '8bit'; |
||
| 324 | } |
||
| 325 | |||
| 326 | // allow transformation of MIME-encoded message |
||
| 327 | View Code Duplication | if ( !Hooks::run( 'UserMailerTransformMessage', |
|
| 328 | [ $to, $from, &$subject, &$headers, &$body, &$error ] ) |
||
| 329 | ) { |
||
| 330 | if ( $error ) { |
||
| 331 | return Status::newFatal( 'php-mail-error', $error ); |
||
| 332 | } else { |
||
| 333 | return Status::newFatal( 'php-mail-error-unknown' ); |
||
| 334 | } |
||
| 335 | } |
||
| 336 | |||
| 337 | $ret = Hooks::run( 'AlternateUserMailer', [ $headers, $to, $from, $subject, $body ] ); |
||
| 338 | if ( $ret === false ) { |
||
| 339 | // the hook implementation will return false to skip regular mail sending |
||
| 340 | return Status::newGood(); |
||
| 341 | } elseif ( $ret !== true ) { |
||
| 342 | // the hook implementation will return a string to pass an error message |
||
| 343 | return Status::newFatal( 'php-mail-error', $ret ); |
||
| 344 | } |
||
| 345 | |||
| 346 | if ( is_array( $wgSMTP ) ) { |
||
| 347 | // Check if pear/mail is already loaded (via composer) |
||
| 348 | if ( !class_exists( 'Mail' ) ) { |
||
| 349 | // PEAR MAILER |
||
| 350 | if ( !stream_resolve_include_path( 'Mail.php' ) ) { |
||
| 351 | throw new MWException( 'PEAR mail package is not installed' ); |
||
| 352 | } |
||
| 353 | require_once 'Mail.php'; |
||
| 354 | } |
||
| 355 | |||
| 356 | MediaWiki\suppressWarnings(); |
||
| 357 | |||
| 358 | // Create the mail object using the Mail::factory method |
||
| 359 | $mail_object =& Mail::factory( 'smtp', $wgSMTP ); |
||
| 360 | View Code Duplication | if ( PEAR::isError( $mail_object ) ) { |
|
| 361 | wfDebug( "PEAR::Mail factory failed: " . $mail_object->getMessage() . "\n" ); |
||
| 362 | MediaWiki\restoreWarnings(); |
||
| 363 | return Status::newFatal( 'pear-mail-error', $mail_object->getMessage() ); |
||
| 364 | } |
||
| 365 | |||
| 366 | wfDebug( "Sending mail via PEAR::Mail\n" ); |
||
| 367 | |||
| 368 | $headers['Subject'] = self::quotedPrintable( $subject ); |
||
| 369 | |||
| 370 | // When sending only to one recipient, shows it its email using To: |
||
| 371 | if ( count( $to ) == 1 ) { |
||
| 372 | $headers['To'] = $to[0]->toString(); |
||
| 373 | } |
||
| 374 | |||
| 375 | // Split jobs since SMTP servers tends to limit the maximum |
||
| 376 | // number of possible recipients. |
||
| 377 | $chunks = array_chunk( $to, $wgEnotifMaxRecips ); |
||
| 378 | foreach ( $chunks as $chunk ) { |
||
| 379 | $status = self::sendWithPear( $mail_object, $chunk, $headers, $body ); |
||
| 380 | // FIXME : some chunks might be sent while others are not! |
||
| 381 | if ( !$status->isOK() ) { |
||
| 382 | MediaWiki\restoreWarnings(); |
||
| 383 | return $status; |
||
| 384 | } |
||
| 385 | } |
||
| 386 | MediaWiki\restoreWarnings(); |
||
| 387 | return Status::newGood(); |
||
| 388 | } else { |
||
| 389 | // PHP mail() |
||
| 390 | if ( count( $to ) > 1 ) { |
||
| 391 | $headers['To'] = 'undisclosed-recipients:;'; |
||
| 392 | } |
||
| 393 | $headers = self::arrayToHeaderString( $headers, $endl ); |
||
| 394 | |||
| 395 | wfDebug( "Sending mail via internal mail() function\n" ); |
||
| 396 | |||
| 397 | self::$mErrorString = ''; |
||
| 398 | $html_errors = ini_get( 'html_errors' ); |
||
| 399 | ini_set( 'html_errors', '0' ); |
||
| 400 | set_error_handler( 'UserMailer::errorHandler' ); |
||
| 401 | |||
| 402 | try { |
||
| 403 | foreach ( $to as $recip ) { |
||
| 404 | $sent = mail( |
||
| 405 | $recip, |
||
| 406 | self::quotedPrintable( $subject ), |
||
| 407 | $body, |
||
| 408 | $headers, |
||
| 409 | $extraParams |
||
| 410 | ); |
||
| 411 | } |
||
| 412 | } catch ( Exception $e ) { |
||
| 413 | restore_error_handler(); |
||
| 414 | throw $e; |
||
| 415 | } |
||
| 416 | |||
| 417 | restore_error_handler(); |
||
| 418 | ini_set( 'html_errors', $html_errors ); |
||
| 419 | |||
| 420 | if ( self::$mErrorString ) { |
||
| 421 | wfDebug( "Error sending mail: " . self::$mErrorString . "\n" ); |
||
| 422 | return Status::newFatal( 'php-mail-error', self::$mErrorString ); |
||
| 423 | } elseif ( !$sent ) { |
||
|
0 ignored issues
–
show
The variable
$sent does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
| 424 | // mail function only tells if there's an error |
||
| 425 | wfDebug( "Unknown error sending mail\n" ); |
||
| 426 | return Status::newFatal( 'php-mail-error-unknown' ); |
||
| 427 | } else { |
||
| 428 | return Status::newGood(); |
||
| 429 | } |
||
| 430 | } |
||
| 431 | } |
||
| 432 | |||
| 433 | /** |
||
| 434 | * Set the mail error message in self::$mErrorString |
||
| 435 | * |
||
| 436 | * @param int $code Error number |
||
| 437 | * @param string $string Error message |
||
| 438 | */ |
||
| 439 | static function errorHandler( $code, $string ) { |
||
| 440 | self::$mErrorString = preg_replace( '/^mail\(\)(\s*\[.*?\])?: /', '', $string ); |
||
| 441 | } |
||
| 442 | |||
| 443 | /** |
||
| 444 | * Strips bad characters from a header value to prevent PHP mail header injection attacks |
||
| 445 | * @param string $val String to be santizied |
||
| 446 | * @return string |
||
| 447 | */ |
||
| 448 | public static function sanitizeHeaderValue( $val ) { |
||
| 449 | return strtr( $val, [ "\r" => '', "\n" => '' ] ); |
||
| 450 | } |
||
| 451 | |||
| 452 | /** |
||
| 453 | * Converts a string into a valid RFC 822 "phrase", such as is used for the sender name |
||
| 454 | * @param string $phrase |
||
| 455 | * @return string |
||
| 456 | */ |
||
| 457 | public static function rfc822Phrase( $phrase ) { |
||
| 458 | // Remove line breaks |
||
| 459 | $phrase = self::sanitizeHeaderValue( $phrase ); |
||
| 460 | // Remove quotes |
||
| 461 | $phrase = str_replace( '"', '', $phrase ); |
||
| 462 | return '"' . $phrase . '"'; |
||
| 463 | } |
||
| 464 | |||
| 465 | /** |
||
| 466 | * Converts a string into quoted-printable format |
||
| 467 | * @since 1.17 |
||
| 468 | * |
||
| 469 | * From PHP5.3 there is a built in function quoted_printable_encode() |
||
| 470 | * This method does not duplicate that. |
||
| 471 | * This method is doing Q encoding inside encoded-words as defined by RFC 2047 |
||
| 472 | * This is for email headers. |
||
| 473 | * The built in quoted_printable_encode() is for email bodies |
||
| 474 | * @param string $string |
||
| 475 | * @param string $charset |
||
| 476 | * @return string |
||
| 477 | */ |
||
| 478 | public static function quotedPrintable( $string, $charset = '' ) { |
||
| 479 | // Probably incomplete; see RFC 2045 |
||
| 480 | if ( empty( $charset ) ) { |
||
| 481 | $charset = 'UTF-8'; |
||
| 482 | } |
||
| 483 | $charset = strtoupper( $charset ); |
||
| 484 | $charset = str_replace( 'ISO-8859', 'ISO8859', $charset ); // ? |
||
| 485 | |||
| 486 | $illegal = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\xff='; |
||
| 487 | $replace = $illegal . '\t ?_'; |
||
| 488 | if ( !preg_match( "/[$illegal]/", $string ) ) { |
||
| 489 | return $string; |
||
| 490 | } |
||
| 491 | $out = "=?$charset?Q?"; |
||
| 492 | $out .= preg_replace_callback( "/([$replace])/", |
||
| 493 | function ( $matches ) { |
||
| 494 | return sprintf( "=%02X", ord( $matches[1] ) ); |
||
| 495 | }, |
||
| 496 | $string |
||
| 497 | ); |
||
| 498 | $out .= '?='; |
||
| 499 | return $out; |
||
| 500 | } |
||
| 501 | } |
||
| 502 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.
Consider the following example. The parameter
$irelandis not defined by the methodfinale(...).The most likely cause is that the parameter was changed, but the annotation was not.