/[drupal]/contributions/modules/invisimail/invisimail.module
ViewVC logotype

Diff of /contributions/modules/invisimail/invisimail.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.3.4.7, Thu Jun 18 21:25:01 2009 UTC revision 1.3.4.8, Mon Jun 29 22:19:44 2009 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: invisimail.module,v 1.3.4.6 2009/03/31 22:48:38 crell Exp $  // $Id: invisimail.module,v 1.3.4.7 2009/06/18 21:25:01 crell Exp $
3    
4    define('INVISIMAIL_MAILTO_ASCII', '&#109;&#97;&#105;&#108;&#116;&#111;&#58;');
5    
6  /**  /**
7   * @file   * @file
# Line 98  function invisimail_filter($op, $delta = Line 100  function invisimail_filter($op, $delta =
100  }  }
101    
102  function invisimail($string, $format) {  function invisimail($string, $format) {
103    $pattern = '!(<p>|<li>|<br />|[\s\(])([A-Za-z0-9._-]+@[A-Za-z0-9._-]+\.[A-Za-z]{2,4})([.,]?)(?=(</p>|</li>|<br />|[\s/)]))!i';    // The check for the user/name portion of the email address. This is
104    // the callback needs to know what filter we're using    // encapsulable regex that looks for at least one valid character (in most
105    // however there's no way to hand off that variable    // cases, a space), preceded by one invalid character, followed by at least
106    // so we'll set a global variable    // one valid character.
107    $GLOBALS['invisimail_format'] = $format;    $valid_user_chars = 'a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\'';
108      $user = "(?<![$valid_user_chars])[$valid_user_chars]+";
109      // For the domain portion of an email addy, you can have a string domain,
110      // an ipv4 address, or an ipv6 address. These three regex capture each of
111      // those possibilities, respectively.
112      $domain = '(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.?)+';
113      $ipv4 = '[0-9]{1,3}(?:\.[0-9]{1,3}){3}';
114      $ipv6 = '[0-9a-fA-F]{1,4}(?:[0-9a-fA-F]{1,4}){7}';
115      // Now we stick it all together into a generalized, encapsulated, portable,
116      // and non-subitem-capturing (hence all the '(?:', which mark subpatterns as
117      // non-capturing) regex for grabbing email addresses.
118      $mail = "(?:$user)+\@(?:$domain|(?:\[(?:$ipv4|$ipv6)\]))";
119      // PCRE pattern modifiers; 'i' enables case-insensitivity, and 'S' enables
120      // the additional pattern analysis, as our regex is one that can benefit
121      // (it is a non-anchored pattern without a single fixed starting character.
122      // see http://us2.php.net/manual/en/reference.pcre.pattern.modifiers.php).
123      // Global case insensitivity is a little sloppy to use, but selectively
124      // toggling it within only some of the subpatterns isn't really worth the
125      // effort.
126      $modifiers = 'iS';
127      // The final pattern. We deal with these as an entire group because invisimail
128      // allows options that require us to deal with both an href and its text
129      // in relation to one another.
130      $pattern = "@(<a .*href=['\"](mailto:$mail)['\"].*>)?((?>(?<!mailto:))$mail)@$modifiers";
131    
132      // The callback needs to know about the filter we're using, but there's no way
133      // to hand off that variable through preg_replace_callback. So we set it as a
134      // global variable.
135      $GLOBALS['invisimail_format'] = array(
136        'js' => variable_get('invisimail_js_'.$format, FALSE),
137        'link' => variable_get('invisimail_link_'.$format, FALSE),
138      );
139    
140    return preg_replace_callback($pattern, 'invisimail_callback', $string);    return preg_replace_callback($pattern, 'invisimail_callback', $string);
141  }  }
142    
143    /**
144     * Callback function used by preg_replace_callback.
145     *
146     * Expects the regex pattern defined in invisimail() to be used.
147     *
148     * @param array $matches
149     *  An array of matched patterns from our regex. Any match will have four keys,
150     *  numbered 0-3, which correspond to the capturing groups in our regex. For all
151     *  these examples, assume the following string:
152     *  <p><a href="mailto:user@domain.com">user@domain.com</a></p>
153     *    - 0: The entire matched string. This will include the email address, as
154     *      well as that email address' corresponding href mailto iff it exists. In
155     *      the example, it would be
156     *        <a href="mailto:user@domain.com">user@domain.com
157     *    - 1: The full string of the <a> tag portion of the match, iff that portion
158     *      was matched; otherwise an empty string. In the example, it would be
159     *        <a href="mailto:user@domain.com">
160     *    - 2: The mailto + email address string from the href portion of the match,
161     *      iff an href was found. In the example, it would be:
162     *        mailto:user@domain.com
163     *    - 3: The email address itself. In the example, just:
164     *      user@domain.com
165     *
166     * @return string
167     *   The full ASCII-encoded string that will replace the entire match.
168     */
169  function invisimail_callback($matches) {  function invisimail_callback($matches) {
170    $format = $GLOBALS['invisimail_format'];    $format = $GLOBALS['invisimail_format'];
   $js = variable_get('invisimail_js_'.$format, FALSE);  
   $link = variable_get('invisimail_link_'.$format, FALSE);  
171    
172    return $matches[1] . invisimail_ascii_encode($matches[2], $js, $link) . $matches[3];    // If $matches[1] is empty, no link portion was matched for this item, so
173      // it's a simple replace operation.
174      if (empty($matches[1])) {
175        return invisimail_ascii_encode($matches[3], $format['js'], $format['link']);
176      }
177      // We DO have an existing link portion. Do our best to preserve it; that means
178      // ignoring the js setting, since it makes for heinous string transformations.
179      return str_replace(array($matches[2], $matches[3]),
180        array(_invisimail_encode_string($matches[2], FALSE), _invisimail_encode_string($matches[3], FALSE)),
181        $matches[0]);
182    }
183    
184    function invisimail_encode_add_link($string, $js, $text) {
185      $encode = _invisimail_encode_string($string, $js);
186    
187      $text = is_null($text) ? $encode : $text;
188    
189      if ($js) {
190        $output = "<script type='text/javascript'><!--
191        document.write('";
192        $output .= '<a href="' . INVISIMAIL_MAILTO_ASCII . "'+'$encode'+'\">'+'$text'+'</a>";
193        $output .= "');
194        //-->
195        </script>";
196      }
197      else {
198        $output = '<a href="' . INVISIMAIL_MAILTO_ASCII . "$encode\">$text</a>";
199      }
200      return $output;
201  }  }
202    
203  /**  /**
204   * This function does the actual encoding.   * ASCII-encode an email address.
205   *   *
206   * @param $string   * @param $string
207   *   A string which contains only an email addres to be encoded.   *   A string containing _only_ an email address to be encoded.
208   * @param $js   * @param $js
209   *   Optional: A boolean which sets whether Javascript is used for encoding.   *   Optional: A boolean which sets whether Javascript is used for encoding.
210   * @param $link   * @param $link
# Line 127  function invisimail_callback($matches) { Line 212  function invisimail_callback($matches) {
212   * @param $text   * @param $text
213   *   Optional: The text to be used for the link.   *   Optional: The text to be used for the link.
214   * @return   * @return
215   *   An ascii encoded email address.   *   An ascii encoded email address, optionally with link included.
216   */   */
217  function invisimail_ascii_encode($string, $js = FALSE, $link = FALSE, $text = NULL) {  function invisimail_ascii_encode($string, $js = FALSE, $link = FALSE, $text = NULL) {
218      return $link ? invisimail_encode_add_link($string, $js, $text) : _invisimail_encode_string($string, $js);
219    }
220    
221    if ($text == NULL) {  /**
222      $text = $string;   * Performs ASCII encoding on the provided string.
223    }   *
224     * @param string $string
225    if ($js) {   * @param bool $js
226      $output = "<script type='text/javascript'><!--   * @return string
227      document.write('";   */
228    }  function _invisimail_encode_string($string, $js) {
229      $encode = '';
230    for ($i=0; $i < strlen($string); $i++)         {    for ($i=0; $i < strlen($string); $i++)   {
231      $char = substr($string, $i, 1);      $char = substr($string, $i, 1);
232      $encode .= '&#'.ord($char).';';      $encode .= '&#'.ord($char).';';
233      if ($js) {      if ($js) {
# Line 150  function invisimail_ascii_encode($string Line 237  function invisimail_ascii_encode($string
237        }        }
238      }      }
239    }    }
240      return $encode;
   if ($link && !$js) {  
     // ascii in this next line is "mailto:"  
     $output .= "<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;$encode\">$encode</a>";  
   }  
   elseif ($link && $js) {  
     $output .= "<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;'+'$encode'+'\">'+'$encode'+'</a>";  
   }  
   else {  
     $output .= $encode;  
   }  
   
   if ($js) {  
     $output .= "');  
     //-->  
     </script>";  
   }  
   
   return $output;  
241  }  }
242    
243    
# Line 217  function theme_invisimail_formatter_invi Line 286  function theme_invisimail_formatter_invi
286   * Settings form for the invisimail CCK formatter.   * Settings form for the invisimail CCK formatter.
287   *   *
288   */   */
289  function invismail_formatter_settings() {  function invisimail_formatter_settings() {
290    return system_settings_form(_invisimail_settings('formatter'));    return system_settings_form(_invisimail_settings('formatter'));
291  }  }
292    

Legend:
Removed from v.1.3.4.7  
changed lines
  Added in v.1.3.4.8

  ViewVC Help
Powered by ViewVC 1.1.2