Source of trunk/misc.php at revision HEAD (05/06/2010 11:05:16, 11795 bytes, 383 lines, language: php) [download]:
| 1 | <?php |
| 2 | |
| 3 | /* |
| 4 | ** Miscellaneous Functions |
| 5 | ** for CodewiseBlog Multi-User |
| 6 | ** |
| 7 | |
| 8 | ** Copyright (c) 2004-2009 Codewise.org |
| 9 | */ |
| 10 | |
| 11 | /* |
| 12 | ** This file is part of CodewiseBlog |
| 13 | ** |
| 14 | ** CodewiseBlog is free software; you can redistribute it and/or modify |
| 15 | ** it under the terms of the GNU General Public License as published by |
| 16 | ** the Free Software Foundation; either version 2 of the License, or |
| 17 | ** (at your option) any later version. |
| 18 | ** |
| 19 | ** CodewiseBlog is distributed in the hope that it will be useful, |
| 20 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 22 | ** GNU General Public License for more details. |
| 23 | ** |
| 24 | ** You should have received a copy of the GNU General Public License |
| 25 | ** along with CodewiseBlog; if not, write to the Free Software |
| 26 | ** Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 27 | */ |
| 28 | |
| 29 | function fortune() |
| 30 | { |
| 31 | ob_start(); passthru("fortune -s"); return(nl2br(ob_get_clean())); |
| 32 | } |
| 33 | |
| 34 | function querycount() |
| 35 | { |
| 36 | global $db; |
| 37 | |
| 38 | return count($db->queries); |
| 39 | } |
| 40 | |
| 41 | function runtime() |
| 42 | { |
| 43 | global $starttime; |
| 44 | |
| 45 | list($usec,$sec) = explode(" ",microtime()); |
| 46 | $endtime = (string) $sec + $usec; |
| 47 | |
| 48 | return number_format(($endtime - $starttime) * 1e3, 0); |
| 49 | } |
| 50 | |
| 51 | /* |
| 52 | ** Return the ISO8601 date ( 2004-02-12T15:19:21+00:00 ) of a UNIX timestamp |
| 53 | */ |
| 54 | function iso8601_date($time) |
| 55 | { |
| 56 | $zone = wordwrap(date('O',$time),3,":",2); |
| 57 | $date = date('Y-m-d\TH:i:s',$time).$zone; |
| 58 | return $date; |
| 59 | } |
| 60 | |
| 61 | function delete_session() |
| 62 | { |
| 63 | unset($_SESSION['postername']); |
| 64 | unset($_SESSION['posterlink']); |
| 65 | unset($_SESSION['tripcode']); |
| 66 | unset($_SESSION['beenhere']); |
| 67 | unset($_SESSION['controlpanel']); |
| 68 | unset($_SESSION['blogid']); |
| 69 | |
| 70 | $GLOBALS['NOTIFY'] = "Your information has been cleared.<br />"; |
| 71 | return main_page(1); |
| 72 | } |
| 73 | |
| 74 | function textprocess($text, $doautobr = TRUE) |
| 75 | { |
| 76 | $text = utf8_decode($text); |
| 77 | |
| 78 | preg_match_all("/<php>(.*)<\\/php>/Us", $text, $matches, PREG_SET_ORDER); |
| 79 | foreach($matches as $match) |
| 80 | { |
| 81 | $text = str_replace($match[0], trim(highlight_string(trim($match[1]), TRUE)), $text); |
| 82 | } |
| 83 | |
| 84 | if ($doautobr) |
| 85 | $text = str_replace("\n", "<br />", str_replace("\r", "", $text)); |
| 86 | |
| 87 | |
| 88 | foreach ($badchars[0] as $badchar) { |
| 89 | $text = str_replace($badchar, htmlentities($badchar), $text); |
| 90 | } |
| 91 | |
| 92 | /* |
| 93 | for ($i = 0; $i < strlen($text); $i++) { |
| 94 | if ($text[$i] > '\x70') { |
| 95 | $text[$i] = htmlentities($text[$i]); |
| 96 | } |
| 97 | } |
| 98 | */ |
| 99 | |
| 100 | return $text; |
| 101 | } // end of textprocess |
| 102 | |
| 103 | function in_text_filter($text, $text_filter_msg = "") |
| 104 | { |
| 105 | global $ALLOWED_TAGS; |
| 106 | |
| 107 | $new_text = $text; |
| 108 | $num_starts = array(); |
| 109 | $num_ends = array(); |
| 110 | |
| 111 | // remove illegal opening tags and, if possible, illegal open-close tag pairs as well |
| 112 | preg_match_all("/(<([A-Za-z][A-Za-z0-9-_:]*)([^>]*)>)/s", $new_text, $matches, PREG_SET_ORDER /*| PREG_OFFSET_CAPTURE*/); |
| 113 | foreach($matches as $match) |
| 114 | { |
| 115 | $full_tag = $match[1]; |
| 116 | $tag_attribs = $match[3]; |
| 117 | $tag_name = $match[2]; |
| 118 | |
| 119 | // get all the attributes and remove all but the allowed ones |
| 120 | preg_match_all("/([A-Za-z][A-Za-z0-9-_:]*)=((['\"])(.*)\\2|\S+?)/Us", $tag_attribs, $attrib_matches, PREG_SET_ORDER); |
| 121 | |
| 122 | foreach($attrib_matches as $attrib_match) |
| 123 | { |
| 124 | $full_attrib = $attrib_match[0]; |
| 125 | $attrib_name = $attrib_match[1]; |
| 126 | if(preg_match("/^['\"]$/", $attrib_match[2])) |
| 127 | $attrib_cont = $attrib_match[3]; |
| 128 | else |
| 129 | $attrib_cont = $attrib_match[2]; |
| 130 | |
| 131 | |
| 132 | { |
| 133 | $new_text = str_replace($full_tag, str_replace($full_attrib, "", $full_tag), $new_text); |
| 134 | $text_filter_msg .= "Removed illegal <code><$tag_name></code> attribute <code>$attrib_name</code><br />"; |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | if(!in_array(strtolower($tag_name), array_keys($ALLOWED_TAGS))) |
| 139 | { |
| 140 | $new_text = str_replace($full_tag, "", $new_text); |
| 141 | $text_filter_msg .= "Removed illegal <code><$tag_name></code><br />"; |
| 142 | if(substr($full_tag, strlen($full_tag) - 2) != "/>") |
| 143 | { |
| 144 | $temp = preg_replace("/<\/" . $tag_name . "[^>]*>/i", "", $new_text, 1); |
| 145 | if($temp != $new_text) |
| 146 | $text_filter_msg .= "Removed accompanying illegal closing <code><$tag_name></code><br />"; |
| 147 | $new_text = $temp; |
| 148 | } |
| 149 | } else { |
| 150 | $num_starts[strtolower($tag_name)]++; |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // remove stray closing tags |
| 155 | preg_match_all("/<\/([A-Za-z][A-Za-z0-9-_:]*)[^>]*>/s", $new_text, $matches, PREG_SET_ORDER); |
| 156 | foreach($matches as $match) |
| 157 | { |
| 158 | $full_tag = $match[0]; |
| 159 | $tag_name = $match[1]; |
| 160 | |
| 161 | if(!in_array(strtolower($tag_name), array_keys($ALLOWED_TAGS))) |
| 162 | { |
| 163 | $new_text = str_replace($full_tag, "", $new_text); |
| 164 | $text_filter_msg .= "Removed illegal closing <code><$tag_name></code><br />"; |
| 165 | continue; |
| 166 | } |
| 167 | |
| 168 | /* |
| 169 | ** check to make sure that there are only as many closing tags as there |
| 170 | ** are opening tags for each tag type |
| 171 | */ |
| 172 | $num_ends[strtolower($tag_name)]++; |
| 173 | if($num_ends[strtolower($tag_name)] > $num_starts[strtolower($tag_name)]) |
| 174 | { |
| 175 | $new_text = str_replace($full_tag, "", $new_text); |
| 176 | $num_ends[strtolower($tag_name)]--; |
| 177 | $text_filter_msg .= "Removed extra closing <code><$tag_name></code><br />"; |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | // one last pass to catch unclosed opening tags |
| 182 | preg_match_all("/<([A-Za-z][A-Za-z0-9-_:]*)[^>]*>/s", $new_text, $matches, PREG_SET_ORDER); |
| 183 | foreach($matches as $match) |
| 184 | { |
| 185 | $full_tag = $match[0]; |
| 186 | $tag_name = $match[1]; |
| 187 | |
| 188 | if($num_starts[strtolower($tag_name)] > $num_ends[strtolower($tag_name)]) |
| 189 | { |
| 190 | $new_text = str_replace($full_tag, "", $new_text); |
| 191 | $text_filter_msg .= "Removed extra opening <code><$tag_name></code><br />"; |
| 192 | } |
| 193 | // another idea: simply append a closing tag |
| 194 | // $new_text .= "</$tag_name>"; |
| 195 | } |
| 196 | |
| 197 | $new_text = preg_replace("/&(?![a-zA-Z]+;)/", "&", $new_text); |
| 198 | |
| 199 | if($new_text == $text) |
| 200 | { |
| 201 | if($text_filter_msg === "") |
| 202 | return($text); |
| 203 | else |
| 204 | return(array($text, $text_filter_msg)); |
| 205 | } else { |
| 206 | return(in_text_filter($new_text, $text_filter_msg)); |
| 207 | } |
| 208 | } // end of in_text_filter |
| 209 | |
| 210 | function tripcode($input) |
| 211 | { |
| 212 | if($input === null || $input === "" || $input === false) |
| 213 | return(null); |
| 214 | |
| 215 | $md5 = md5($input.TRIPCODE_SALT); |
| 216 | |
| 217 | $values = array(); |
| 218 | $chars = preg_split('//', $md5, -1, PREG_SPLIT_NO_EMPTY); |
| 219 | foreach($chars as $char) |
| 220 | { |
| 221 | if(preg_match("/[0-9]/", $char)) |
| 222 | { |
| 223 | array_push($values, $char); |
| 224 | } else { |
| 225 | switch($char) |
| 226 | { |
| 227 | case "a": $val=10; break; |
| 228 | case "b": $val=11; break; |
| 229 | case "c": $val=12; break; |
| 230 | case "d": $val=13; break; |
| 231 | case "e": $val=14; break; |
| 232 | case "f": $val=15; break; |
| 233 | } |
| 234 | array_push($values, $val); |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | $binary = ""; |
| 239 | for($i = 0; $i <= 30; $i += 2) |
| 240 | { |
| 241 | $a = $values[$i]; |
| 242 | $b = $values[$i + 1]; |
| 243 | |
| 244 | $c = ($a << 4) + $b; |
| 245 | |
| 246 | $binary .= chr($c); |
| 247 | } |
| 248 | |
| 249 | $final = base64_encode($binary); |
| 250 | |
| 251 | return substr($final, 0, -2); |
| 252 | } // end of tripcode() |
| 253 | |
| 254 | function mail_db_error($error) |
| 255 | { |
| 256 | $message = "CodewiseBlog encountered the following database error at " . date(DATE_FORMAT, time()) . ":\n\n" . $error; |
| 257 | $message .= "\n\n\$_SERVER:\n" . var_export($_SERVER, true) . "\n\n\$_GET:\n" . var_export($_GET, true) . "\n\n\$_POST:\n" . var_export($_POST, true); |
| 258 | |
| 259 | if(EMAIL) |
| 260 | |
| 261 | |
| 262 | preg_match("/\A(.+)<br \/>\n(.+)<br \/>\n(.*<br \/>\n)*(.*)\Z/", $error, $matches); |
| 263 | $errortype = $matches[1]; |
| 264 | $mysqlout = $matches[2]; |
| 265 | $fatal = ($matches[4] == "<b>FATAL</b>"); |
| 266 | if($fatal): |
| 267 | ?> |
| 268 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| 269 | <html> |
| 270 | <head> |
| 271 | <title>Database Error</title> |
| 272 | <link rel="stylesheet" href="skin_blueEye/stylesheet.css" /> |
| 273 | </head> |
| 274 | <body> |
| 275 | <?php |
| 276 | endif; |
| 277 | ?> |
| 278 | <h1>Database Error</h1> |
| 279 | <b><?php echo $errortype;?> - <?php echo $mysqlout; ?></b><br /> |
| 280 | <?php if($fatal) echo "<b>FATAL</b><br />\n"; ?> |
| 281 | <br /> |
| 282 | <?php if($okay) echo "The admin has been notified.\n"; else echo "Unable to email the admin.\n"; ?> |
| 283 | <?php if($fatal): ?> |
| 284 | </body> |
| 285 | </html> |
| 286 | <?php |
| 287 | else: |
| 288 | echo "<br /><br />"; |
| 289 | endif; |
| 290 | } // end of mail_db_error() |
| 291 | |
| 292 | function ordinal($n) |
| 293 | { |
| 294 | if(substr($n, -2, 1) == "1") // teens always end in 'th' |
| 295 | return "${n}th"; |
| 296 | if(substr($n, -1, 1) == "1") // ...1st |
| 297 | return "{$n}st"; |
| 298 | elseif(substr($n, -1, 1) == "2") // ...2nd |
| 299 | return "{$n}nd"; |
| 300 | elseif(substr($n, -1, 1) == "3") // ...3rd |
| 301 | return "{$n}rd"; |
| 302 | else // ...th |
| 303 | return "{$n}th"; |
| 304 | } |
| 305 | |
| 306 | /* |
| 307 | ** This function will clip text as close to (without going over) the specified |
| 308 | ** character limit as possible without messing up html or breaking words. IT |
| 309 | ** MAY, HOWEVER, LEAVE TAGS OPEN, so be careful. |
| 310 | */ |
| 311 | function text_clip($text, $limit = 500, $append = " ...") |
| 312 | { |
| 313 | if(strlen($text) <= $limit) |
| 314 | { |
| 315 | return($text); |
| 316 | } else { |
| 317 | $content = ""; |
| 318 | $tags = array(); // stack for holding tags that are open at time of clip |
| 319 | $parts = preg_split("/(<[^>]+>)/",$text,-1,PREG_SPLIT_DELIM_CAPTURE); |
| 320 | foreach($parts as $part) |
| 321 | { |
| 322 | if(strlen($content) + strlen($part) <= $limit - strlen($append)) |
| 323 | { |
| 324 | if(substr($part,0,2) == "</") // html end tag |
| 325 | array_pop($tags); // pop the tag |
| 326 | else if (substr($part,0,1) == "<") // html start tag |
| 327 | array_push($tags, substr($part,1,-1)); // add tag to the stack |
| 328 | $content .= $part; |
| 329 | continue; |
| 330 | } else { |
| 331 | if(substr($part,0,1) == "<") // html tag part |
| 332 | { |
| 333 | $content .= $append; |
| 334 | for($i = count($tags) - 1; $i >= 0; $i--) |
| 335 | $content .= "</" . $tags[$i] . ">"; |
| 336 | break; |
| 337 | } else { // text part |
| 338 | $words = preg_split("/( )/",$part,-1,PREG_SPLIT_DELIM_CAPTURE); |
| 339 | foreach($words as $word) |
| 340 | { |
| 341 | if(strlen($content) + strlen($word) <= $limit - strlen($append)) |
| 342 | { |
| 343 | $content .= $word; |
| 344 | continue; |
| 345 | } else { |
| 346 | $content .= $append; |
| 347 | break 2; |
| 348 | } |
| 349 | } |
| 350 | } |
| 351 | } |
| 352 | } |
| 353 | } |
| 354 | |
| 355 | return($content); |
| 356 | } |
| 357 | |
| 358 | function uuidgen() |
| 359 | { |
| 360 | return md5($_SERVER['SERVER_ADDR'] . getmypid() . uniqid(mt_rand(), true)); |
| 361 | } |
| 362 | |
| 363 | function array_psearch($array, $preg) |
| 364 | { |
| 365 | foreach ($array as $key => $value) { |
| 366 | if (preg_match($preg, $value)) { |
| 367 | return array($key, $value); |
| 368 | } |
| 369 | } |
| 370 | return FALSE; |
| 371 | } |
| 372 | |
| 373 | function vdump($var) |
| 374 | { |
| 375 | echo "<pre>"; |
| 376 | ob_start(); |
| 377 | var_dump($var); |
| 378 | echo htmlspecialchars(ob_get_clean()); |
| 379 | echo "</pre>"; |
| 380 | } |
| 381 | |
| 382 | ?> |
| 383 |