annotate includes/mail.inc @ 1:c1f4ac30525a 6.0

Drupal 6.0
author Franck Deroche <webmaster@defr.org>
date Tue, 23 Dec 2008 14:28:28 +0100
parents
children 2427550111ae
rev   line source
webmaster@1 1 <?php
webmaster@1 2 // $Id: mail.inc,v 1.8 2008/01/25 17:04:00 goba Exp $
webmaster@1 3
webmaster@1 4 /**
webmaster@1 5 * Compose and optionally send an e-mail message.
webmaster@1 6 *
webmaster@1 7 * Sending an e-mail works with defining an e-mail template (subject, text
webmaster@1 8 * and possibly e-mail headers) and the replacement values to use in the
webmaster@1 9 * appropriate places in the template. Processed e-mail templates are
webmaster@1 10 * requested from hook_mail() from the module sending the e-mail. Any module
webmaster@1 11 * can modify the composed e-mail message array using hook_mail_alter().
webmaster@1 12 * Finally drupal_mail_send() sends the e-mail, which can be reused
webmaster@1 13 * if the exact same composed e-mail is to be sent to multiple recipients.
webmaster@1 14 *
webmaster@1 15 * Finding out what language to send the e-mail with needs some consideration.
webmaster@1 16 * If you send e-mail to a user, her preferred language should be fine, so
webmaster@1 17 * use user_preferred_language(). If you send email based on form values
webmaster@1 18 * filled on the page, there are two additional choices if you are not
webmaster@1 19 * sending the e-mail to a user on the site. You can either use the language
webmaster@1 20 * used to generate the page ($language global variable) or the site default
webmaster@1 21 * language. See language_default(). The former is good if sending e-mail to
webmaster@1 22 * the person filling the form, the later is good if you send e-mail to an
webmaster@1 23 * address previously set up (like contact addresses in a contact form).
webmaster@1 24 *
webmaster@1 25 * Taking care of always using the proper language is even more important
webmaster@1 26 * when sending e-mails in a row to multiple users. Hook_mail() abstracts
webmaster@1 27 * whether the mail text comes from an administrator setting or is
webmaster@1 28 * static in the source code. It should also deal with common mail tokens,
webmaster@1 29 * only receiving $params which are unique to the actual e-mail at hand.
webmaster@1 30 *
webmaster@1 31 * An example:
webmaster@1 32 *
webmaster@1 33 * @code
webmaster@1 34 * function example_notify($accounts) {
webmaster@1 35 * foreach ($accounts as $account) {
webmaster@1 36 * $params['account'] = $account;
webmaster@1 37 * // example_mail() will be called based on the first drupal_mail() parameter.
webmaster@1 38 * drupal_mail('example', 'notify', $account->mail, user_preferred_language($account), $params);
webmaster@1 39 * }
webmaster@1 40 * }
webmaster@1 41 *
webmaster@1 42 * function example_mail($key, &$message, $params) {
webmaster@1 43 * $language = $message['language'];
webmaster@1 44 * $variables = user_mail_tokens($params['account'], $language);
webmaster@1 45 * switch($key) {
webmaster@1 46 * case 'notice':
webmaster@1 47 * $message['subject'] = t('Notification from !site', $variables, $language->language);
webmaster@1 48 * $message['body'] = t("Dear !username\n\nThere is new content available on the site.", $variables, $language->language);
webmaster@1 49 * break;
webmaster@1 50 * }
webmaster@1 51 * }
webmaster@1 52 * @endcode
webmaster@1 53 *
webmaster@1 54 * @param $module
webmaster@1 55 * A module name to invoke hook_mail() on. The {$module}_mail() hook will be
webmaster@1 56 * called to complete the $message structure which will already contain common
webmaster@1 57 * defaults.
webmaster@1 58 * @param $key
webmaster@1 59 * A key to identify the e-mail sent. The final e-mail id for e-mail altering
webmaster@1 60 * will be {$module}_{$key}.
webmaster@1 61 * @param $to
webmaster@1 62 * The e-mail address or addresses where the message will be sent to. The
webmaster@1 63 * formatting of this string must comply with RFC 2822. Some examples are:
webmaster@1 64 * user@example.com
webmaster@1 65 * user@example.com, anotheruser@example.com
webmaster@1 66 * User <user@example.com>
webmaster@1 67 * User <user@example.com>, Another User <anotheruser@example.com>
webmaster@1 68 * @param $language
webmaster@1 69 * Language object to use to compose the e-mail.
webmaster@1 70 * @param $params
webmaster@1 71 * Optional parameters to build the e-mail.
webmaster@1 72 * @param $from
webmaster@1 73 * Sets From, Reply-To, Return-Path and Error-To to this value, if given.
webmaster@1 74 * @param $send
webmaster@1 75 * Send the message directly, without calling drupal_mail_send() manually.
webmaster@1 76 * @return
webmaster@1 77 * The $message array structure containing all details of the
webmaster@1 78 * message. If already sent ($send = TRUE), then the 'result' element
webmaster@1 79 * will contain the success indicator of the e-mail, failure being already
webmaster@1 80 * written to the watchdog. (Success means nothing more than the message being
webmaster@1 81 * accepted at php-level, which still doesn't guarantee it to be delivered.)
webmaster@1 82 */
webmaster@1 83 function drupal_mail($module, $key, $to, $language, $params = array(), $from = NULL, $send = TRUE) {
webmaster@1 84 $default_from = variable_get('site_mail', ini_get('sendmail_from'));
webmaster@1 85
webmaster@1 86 // Bundle up the variables into a structured array for altering.
webmaster@1 87 $message = array(
webmaster@1 88 'id' => $module .'_'. $key,
webmaster@1 89 'to' => $to,
webmaster@1 90 'from' => isset($from) ? $from : $default_from,
webmaster@1 91 'language' => $language,
webmaster@1 92 'params' => $params,
webmaster@1 93 'subject' => '',
webmaster@1 94 'body' => array()
webmaster@1 95 );
webmaster@1 96
webmaster@1 97 // Build the default headers
webmaster@1 98 $headers = array(
webmaster@1 99 'MIME-Version' => '1.0',
webmaster@1 100 'Content-Type' => 'text/plain; charset=UTF-8; format=flowed; delsp=yes',
webmaster@1 101 'Content-Transfer-Encoding' => '8Bit',
webmaster@1 102 'X-Mailer' => 'Drupal'
webmaster@1 103 );
webmaster@1 104 if ($default_from) {
webmaster@1 105 // To prevent e-mail from looking like spam, the addresses in the Sender and
webmaster@1 106 // Return-Path headers should have a domain authorized to use the originating
webmaster@1 107 // SMTP server. Errors-To is redundant, but shouldn't hurt.
webmaster@1 108 $headers['From'] = $headers['Reply-To'] = $headers['Sender'] = $headers['Return-Path'] = $headers['Errors-To'] = $default_from;
webmaster@1 109 }
webmaster@1 110 if ($from) {
webmaster@1 111 $headers['From'] = $headers['Reply-To'] = $from;
webmaster@1 112 }
webmaster@1 113 $message['headers'] = $headers;
webmaster@1 114
webmaster@1 115 // Build the e-mail (get subject and body, allow additional headers) by
webmaster@1 116 // invoking hook_mail() on this module. We cannot use module_invoke() as
webmaster@1 117 // we need to have $message by reference in hook_mail().
webmaster@1 118 if (function_exists($function = $module .'_mail')) {
webmaster@1 119 $function($key, $message, $params);
webmaster@1 120 }
webmaster@1 121
webmaster@1 122 // Invoke hook_mail_alter() to allow all modules to alter the resulting e-mail.
webmaster@1 123 drupal_alter('mail', $message);
webmaster@1 124
webmaster@1 125 // Concatenate and wrap the e-mail body.
webmaster@1 126 $message['body'] = is_array($message['body']) ? drupal_wrap_mail(implode("\n\n", $message['body'])) : drupal_wrap_mail($message['body']);
webmaster@1 127
webmaster@1 128 // Optionally send e-mail.
webmaster@1 129 if ($send) {
webmaster@1 130 $message['result'] = drupal_mail_send($message);
webmaster@1 131
webmaster@1 132 // Log errors
webmaster@1 133 if (!$message['result']) {
webmaster@1 134 watchdog('mail', 'Error sending e-mail (from %from to %to).', array('%from' => $message['from'], '%to' => $message['to']), WATCHDOG_ERROR);
webmaster@1 135 drupal_set_message(t('Unable to send e-mail. Please contact the site admin, if the problem persists.'), 'error');
webmaster@1 136 }
webmaster@1 137 }
webmaster@1 138
webmaster@1 139 return $message;
webmaster@1 140 }
webmaster@1 141
webmaster@1 142 /**
webmaster@1 143 * Send an e-mail message, using Drupal variables and default settings.
webmaster@1 144 * More information in the <a href="http://php.net/manual/en/function.mail.php">
webmaster@1 145 * PHP function reference for mail()</a>. See drupal_mail() for information on
webmaster@1 146 * how $message is composed.
webmaster@1 147 *
webmaster@1 148 * @param $message
webmaster@1 149 * Message array with at least the following elements:
webmaster@1 150 * - id
webmaster@1 151 * A unique identifier of the e-mail type. Examples: 'contact_user_copy',
webmaster@1 152 * 'user_password_reset'.
webmaster@1 153 * - to
webmaster@1 154 * The mail address or addresses where the message will be sent to. The
webmaster@1 155 * formatting of this string must comply with RFC 2822. Some examples are:
webmaster@1 156 * user@example.com
webmaster@1 157 * user@example.com, anotheruser@example.com
webmaster@1 158 * User <user@example.com>
webmaster@1 159 * User <user@example.com>, Another User <anotheruser@example.com>
webmaster@1 160 * - subject
webmaster@1 161 * Subject of the e-mail to be sent. This must not contain any newline
webmaster@1 162 * characters, or the mail may not be sent properly.
webmaster@1 163 * - body
webmaster@1 164 * Message to be sent. Accepts both CRLF and LF line-endings.
webmaster@1 165 * E-mail bodies must be wrapped. You can use drupal_wrap_mail() for
webmaster@1 166 * smart plain text wrapping.
webmaster@1 167 * - headers
webmaster@1 168 * Associative array containing all mail headers.
webmaster@1 169 * @return
webmaster@1 170 * Returns TRUE if the mail was successfully accepted for delivery,
webmaster@1 171 * FALSE otherwise.
webmaster@1 172 */
webmaster@1 173 function drupal_mail_send($message) {
webmaster@1 174 // Allow for a custom mail backend.
webmaster@1 175 if (variable_get('smtp_library', '') && file_exists(variable_get('smtp_library', ''))) {
webmaster@1 176 include_once './'. variable_get('smtp_library', '');
webmaster@1 177 return drupal_mail_wrapper($message);
webmaster@1 178 }
webmaster@1 179 else {
webmaster@1 180 $mimeheaders = array();
webmaster@1 181 foreach ($message['headers'] as $name => $value) {
webmaster@1 182 $mimeheaders[] = $name .': '. mime_header_encode($value);
webmaster@1 183 }
webmaster@1 184 return mail(
webmaster@1 185 $message['to'],
webmaster@1 186 mime_header_encode($message['subject']),
webmaster@1 187 // Note: e-mail uses CRLF for line-endings, but PHP's API requires LF.
webmaster@1 188 // They will appear correctly in the actual e-mail that is sent.
webmaster@1 189 str_replace("\r", '', $message['body']),
webmaster@1 190 join("\n", $mimeheaders)
webmaster@1 191 );
webmaster@1 192 }
webmaster@1 193 }
webmaster@1 194
webmaster@1 195 /**
webmaster@1 196 * Perform format=flowed soft wrapping for mail (RFC 3676).
webmaster@1 197 *
webmaster@1 198 * We use delsp=yes wrapping, but only break non-spaced languages when
webmaster@1 199 * absolutely necessary to avoid compatibility issues.
webmaster@1 200 *
webmaster@1 201 * We deliberately use LF rather than CRLF, see drupal_mail().
webmaster@1 202 *
webmaster@1 203 * @param $text
webmaster@1 204 * The plain text to process.
webmaster@1 205 * @param $indent (optional)
webmaster@1 206 * A string to indent the text with. Only '>' characters are repeated on
webmaster@1 207 * subsequent wrapped lines. Others are replaced by spaces.
webmaster@1 208 */
webmaster@1 209 function drupal_wrap_mail($text, $indent = '') {
webmaster@1 210 // Convert CRLF into LF.
webmaster@1 211 $text = str_replace("\r", '', $text);
webmaster@1 212 // See if soft-wrapping is allowed.
webmaster@1 213 $clean_indent = _drupal_html_to_text_clean($indent);
webmaster@1 214 $soft = strpos($clean_indent, ' ') === FALSE;
webmaster@1 215 // Check if the string has line breaks.
webmaster@1 216 if (strpos($text, "\n") !== FALSE) {
webmaster@1 217 // Remove trailing spaces to make existing breaks hard.
webmaster@1 218 $text = preg_replace('/ +\n/m', "\n", $text);
webmaster@1 219 // Wrap each line at the needed width.
webmaster@1 220 $lines = explode("\n", $text);
webmaster@1 221 array_walk($lines, '_drupal_wrap_mail_line', array('soft' => $soft, 'length' => strlen($indent)));
webmaster@1 222 $text = implode("\n", $lines);
webmaster@1 223 }
webmaster@1 224 else {
webmaster@1 225 // Wrap this line.
webmaster@1 226 _drupal_wrap_mail_line($text, 0, array('soft' => $soft, 'length' => strlen($indent)));
webmaster@1 227 }
webmaster@1 228 // Empty lines with nothing but spaces.
webmaster@1 229 $text = preg_replace('/^ +\n/m', "\n", $text);
webmaster@1 230 // Space-stuff special lines.
webmaster@1 231 $text = preg_replace('/^(>| |From)/m', ' $1', $text);
webmaster@1 232 // Apply indentation. We only include non-'>' indentation on the first line.
webmaster@1 233 $text = $indent . substr(preg_replace('/^/m', $clean_indent, $text), strlen($indent));
webmaster@1 234
webmaster@1 235 return $text;
webmaster@1 236 }
webmaster@1 237
webmaster@1 238 /**
webmaster@1 239 * Transform an HTML string into plain text, preserving the structure of the
webmaster@1 240 * markup. Useful for preparing the body of a node to be sent by e-mail.
webmaster@1 241 *
webmaster@1 242 * The output will be suitable for use as 'format=flowed; delsp=yes' text
webmaster@1 243 * (RFC 3676) and can be passed directly to drupal_mail() for sending.
webmaster@1 244 *
webmaster@1 245 * We deliberately use LF rather than CRLF, see drupal_mail().
webmaster@1 246 *
webmaster@1 247 * This function provides suitable alternatives for the following tags:
webmaster@1 248 * <a> <em> <i> <strong> <b> <br> <p> <blockquote> <ul> <ol> <li> <dl> <dt>
webmaster@1 249 * <dd> <h1> <h2> <h3> <h4> <h5> <h6> <hr>
webmaster@1 250 *
webmaster@1 251 * @param $string
webmaster@1 252 * The string to be transformed.
webmaster@1 253 * @param $allowed_tags (optional)
webmaster@1 254 * If supplied, a list of tags that will be transformed. If omitted, all
webmaster@1 255 * all supported tags are transformed.
webmaster@1 256 * @return
webmaster@1 257 * The transformed string.
webmaster@1 258 */
webmaster@1 259 function drupal_html_to_text($string, $allowed_tags = NULL) {
webmaster@1 260 // Cache list of supported tags.
webmaster@1 261 static $supported_tags;
webmaster@1 262 if (empty($supported_tags)) {
webmaster@1 263 $supported_tags = array('a', 'em', 'i', 'strong', 'b', 'br', 'p', 'blockquote', 'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr');
webmaster@1 264 }
webmaster@1 265
webmaster@1 266 // Make sure only supported tags are kept.
webmaster@1 267 $allowed_tags = isset($allowed_tags) ? array_intersect($supported_tags, $allowed_tags) : $supported_tags;
webmaster@1 268
webmaster@1 269 // Make sure tags, entities and attributes are well-formed and properly nested.
webmaster@1 270 $string = _filter_htmlcorrector(filter_xss($string, $allowed_tags));
webmaster@1 271
webmaster@1 272 // Apply inline styles.
webmaster@1 273 $string = preg_replace('!</?(em|i)>!i', '/', $string);
webmaster@1 274 $string = preg_replace('!</?(strong|b)>!i', '*', $string);
webmaster@1 275
webmaster@1 276 // Replace inline <a> tags with the text of link and a footnote.
webmaster@1 277 // 'See <a href="http://drupal.org">the Drupal site</a>' becomes
webmaster@1 278 // 'See the Drupal site [1]' with the URL included as a footnote.
webmaster@1 279 _drupal_html_to_mail_urls(NULL, TRUE);
webmaster@1 280 $pattern = '@(<a[^>]+?href="([^"]*)"[^>]*?>(.+?)</a>)@i';
webmaster@1 281 $string = preg_replace_callback($pattern, '_drupal_html_to_mail_urls', $string);
webmaster@1 282 $urls = _drupal_html_to_mail_urls();
webmaster@1 283 $footnotes = '';
webmaster@1 284 if (count($urls)) {
webmaster@1 285 $footnotes .= "\n";
webmaster@1 286 for ($i = 0, $max = count($urls); $i < $max; $i++) {
webmaster@1 287 $footnotes .= '['. ($i + 1) .'] '. $urls[$i] ."\n";
webmaster@1 288 }
webmaster@1 289 }
webmaster@1 290
webmaster@1 291 // Split tags from text.
webmaster@1 292 $split = preg_split('/<([^>]+?)>/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
webmaster@1 293 // Note: PHP ensures the array consists of alternating delimiters and literals
webmaster@1 294 // and begins and ends with a literal (inserting $null as required).
webmaster@1 295
webmaster@1 296 $tag = FALSE; // Odd/even counter (tag or no tag)
webmaster@1 297 $casing = NULL; // Case conversion function
webmaster@1 298 $output = '';
webmaster@1 299 $indent = array(); // All current indentation string chunks
webmaster@1 300 $lists = array(); // Array of counters for opened lists
webmaster@1 301 foreach ($split as $value) {
webmaster@1 302 $chunk = NULL; // Holds a string ready to be formatted and output.
webmaster@1 303
webmaster@1 304 // Process HTML tags (but don't output any literally).
webmaster@1 305 if ($tag) {
webmaster@1 306 list($tagname) = explode(' ', strtolower($value), 2);
webmaster@1 307 switch ($tagname) {
webmaster@1 308 // List counters
webmaster@1 309 case 'ul':
webmaster@1 310 array_unshift($lists, '*');
webmaster@1 311 break;
webmaster@1 312 case 'ol':
webmaster@1 313 array_unshift($lists, 1);
webmaster@1 314 break;
webmaster@1 315 case '/ul':
webmaster@1 316 case '/ol':
webmaster@1 317 array_shift($lists);
webmaster@1 318 $chunk = ''; // Ensure blank new-line.
webmaster@1 319 break;
webmaster@1 320
webmaster@1 321 // Quotation/list markers, non-fancy headers
webmaster@1 322 case 'blockquote':
webmaster@1 323 // Format=flowed indentation cannot be mixed with lists.
webmaster@1 324 $indent[] = count($lists) ? ' "' : '>';
webmaster@1 325 break;
webmaster@1 326 case 'li':
webmaster@1 327 $indent[] = is_numeric($lists[0]) ? ' '. $lists[0]++ .') ' : ' * ';
webmaster@1 328 break;
webmaster@1 329 case 'dd':
webmaster@1 330 $indent[] = ' ';
webmaster@1 331 break;
webmaster@1 332 case 'h3':
webmaster@1 333 $indent[] = '.... ';
webmaster@1 334 break;
webmaster@1 335 case 'h4':
webmaster@1 336 $indent[] = '.. ';
webmaster@1 337 break;
webmaster@1 338 case '/blockquote':
webmaster@1 339 if (count($lists)) {
webmaster@1 340 // Append closing quote for inline quotes (immediately).
webmaster@1 341 $output = rtrim($output, "> \n") ."\"\n";
webmaster@1 342 $chunk = ''; // Ensure blank new-line.
webmaster@1 343 }
webmaster@1 344 // Fall-through
webmaster@1 345 case '/li':
webmaster@1 346 case '/dd':
webmaster@1 347 array_pop($indent);
webmaster@1 348 break;
webmaster@1 349 case '/h3':
webmaster@1 350 case '/h4':
webmaster@1 351 array_pop($indent);
webmaster@1 352 case '/h5':
webmaster@1 353 case '/h6':
webmaster@1 354 $chunk = ''; // Ensure blank new-line.
webmaster@1 355 break;
webmaster@1 356
webmaster@1 357 // Fancy headers
webmaster@1 358 case 'h1':
webmaster@1 359 $indent[] = '======== ';
webmaster@1 360 $casing = 'drupal_strtoupper';
webmaster@1 361 break;
webmaster@1 362 case 'h2':
webmaster@1 363 $indent[] = '-------- ';
webmaster@1 364 $casing = 'drupal_strtoupper';
webmaster@1 365 break;
webmaster@1 366 case '/h1':
webmaster@1 367 case '/h2':
webmaster@1 368 $casing = NULL;
webmaster@1 369 // Pad the line with dashes.
webmaster@1 370 $output = _drupal_html_to_text_pad($output, ($tagname == '/h1') ? '=' : '-', ' ');
webmaster@1 371 array_pop($indent);
webmaster@1 372 $chunk = ''; // Ensure blank new-line.
webmaster@1 373 break;
webmaster@1 374
webmaster@1 375 // Horizontal rulers
webmaster@1 376 case 'hr':
webmaster@1 377 // Insert immediately.
webmaster@1 378 $output .= drupal_wrap_mail('', implode('', $indent)) ."\n";
webmaster@1 379 $output = _drupal_html_to_text_pad($output, '-');
webmaster@1 380 break;
webmaster@1 381
webmaster@1 382 // Paragraphs and definition lists
webmaster@1 383 case '/p':
webmaster@1 384 case '/dl':
webmaster@1 385 $chunk = ''; // Ensure blank new-line.
webmaster@1 386 break;
webmaster@1 387 }
webmaster@1 388 }
webmaster@1 389 // Process blocks of text.
webmaster@1 390 else {
webmaster@1 391 // Convert inline HTML text to plain text.
webmaster@1 392 $value = trim(preg_replace('/\s+/', ' ', decode_entities($value)));
webmaster@1 393 if (strlen($value)) {
webmaster@1 394 $chunk = $value;
webmaster@1 395 }
webmaster@1 396 }
webmaster@1 397
webmaster@1 398 // See if there is something waiting to be output.
webmaster@1 399 if (isset($chunk)) {
webmaster@1 400 // Apply any necessary case conversion.
webmaster@1 401 if (isset($casing)) {
webmaster@1 402 $chunk = $casing($chunk);
webmaster@1 403 }
webmaster@1 404 // Format it and apply the current indentation.
webmaster@1 405 $output .= drupal_wrap_mail($chunk, implode('', $indent)) ."\n";
webmaster@1 406 // Remove non-quotation markers from indentation.
webmaster@1 407 $indent = array_map('_drupal_html_to_text_clean', $indent);
webmaster@1 408 }
webmaster@1 409
webmaster@1 410 $tag = !$tag;
webmaster@1 411 }
webmaster@1 412
webmaster@1 413 return $output . $footnotes;
webmaster@1 414 }
webmaster@1 415
webmaster@1 416 /**
webmaster@1 417 * Helper function for array_walk in drupal_wrap_mail().
webmaster@1 418 *
webmaster@1 419 * Wraps words on a single line.
webmaster@1 420 */
webmaster@1 421 function _drupal_wrap_mail_line(&$line, $key, $values) {
webmaster@1 422 // Use soft-breaks only for purely quoted or unindented text.
webmaster@1 423 $line = wordwrap($line, 77 - $values['length'], $values['soft'] ? " \n" : "\n");
webmaster@1 424 // Break really long words at the maximum width allowed.
webmaster@1 425 $line = wordwrap($line, 996 - $values['length'], $values['soft'] ? " \n" : "\n");
webmaster@1 426 }
webmaster@1 427
webmaster@1 428 /**
webmaster@1 429 * Helper function for drupal_html_to_text().
webmaster@1 430 *
webmaster@1 431 * Keeps track of URLs and replaces them with placeholder tokens.
webmaster@1 432 */
webmaster@1 433 function _drupal_html_to_mail_urls($match = NULL, $reset = FALSE) {
webmaster@1 434 global $base_url, $base_path;
webmaster@1 435 static $urls = array(), $regexp;
webmaster@1 436
webmaster@1 437 if ($reset) {
webmaster@1 438 // Reset internal URL list.
webmaster@1 439 $urls = array();
webmaster@1 440 }
webmaster@1 441 else {
webmaster@1 442 if (empty($regexp)) {
webmaster@1 443 $regexp = '@^'. preg_quote($base_path, '@') .'@';
webmaster@1 444 }
webmaster@1 445 if ($match) {
webmaster@1 446 list(, , $url, $label) = $match;
webmaster@1 447 // Ensure all URLs are absolute.
webmaster@1 448 $urls[] = strpos($url, '://') ? $url : preg_replace($regexp, $base_url .'/', $url);
webmaster@1 449 return $label .' ['. count($urls) .']';
webmaster@1 450 }
webmaster@1 451 }
webmaster@1 452 return $urls;
webmaster@1 453 }
webmaster@1 454
webmaster@1 455 /**
webmaster@1 456 * Helper function for drupal_wrap_mail() and drupal_html_to_text().
webmaster@1 457 *
webmaster@1 458 * Replace all non-quotation markers from a given piece of indentation with spaces.
webmaster@1 459 */
webmaster@1 460 function _drupal_html_to_text_clean($indent) {
webmaster@1 461 return preg_replace('/[^>]/', ' ', $indent);
webmaster@1 462 }
webmaster@1 463
webmaster@1 464 /**
webmaster@1 465 * Helper function for drupal_html_to_text().
webmaster@1 466 *
webmaster@1 467 * Pad the last line with the given character.
webmaster@1 468 */
webmaster@1 469 function _drupal_html_to_text_pad($text, $pad, $prefix = '') {
webmaster@1 470 // Remove last line break.
webmaster@1 471 $text = substr($text, 0, -1);
webmaster@1 472 // Calculate needed padding space and add it.
webmaster@1 473 if (($p = strrpos($text, "\n")) === FALSE) {
webmaster@1 474 $p = -1;
webmaster@1 475 }
webmaster@1 476 $n = max(0, 79 - (strlen($text) - $p));
webmaster@1 477 // Add prefix and padding, and restore linebreak.
webmaster@1 478 return $text . $prefix . str_repeat($pad, $n - strlen($prefix)) ."\n";
webmaster@1 479 }