| 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', 'mailto:'); |
| 5 |
|
|
| 6 |
/** |
/** |
| 7 |
* @file |
* @file |
| 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 |
| 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) { |
| 237 |
} |
} |
| 238 |
} |
} |
| 239 |
} |
} |
| 240 |
|
return $encode; |
|
if ($link && !$js) { |
|
|
// ascii in this next line is "mailto:" |
|
|
$output .= "<a href=\"mailto:$encode\">$encode</a>"; |
|
|
} |
|
|
elseif ($link && $js) { |
|
|
$output .= "<a href=\"mailto:'+'$encode'+'\">'+'$encode'+'</a>"; |
|
|
} |
|
|
else { |
|
|
$output .= $encode; |
|
|
} |
|
|
|
|
|
if ($js) { |
|
|
$output .= "'); |
|
|
//--> |
|
|
</script>"; |
|
|
} |
|
|
|
|
|
return $output; |
|
| 241 |
} |
} |
| 242 |
|
|
| 243 |
|
|
| 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 |
|
|