WordPress.org

Make WordPress Core

Ticket #9616: String.inc.php

File String.inc.php, 24.2 KB (added by Denis-de-Bernardy, 5 years ago)

on a separate note, this class has a couple of useful functions

Line 
1<?php
2
3/**
4 * @file String.inc.php
5 *
6 * Copyright (c) 2000-2008 John Willinsky
7 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
8 *
9 * @package core
10 * @class String
11 *
12 * String manipulation wrapper class.
13 *
14 * $Id: String.inc.php,v 1.17 2008/04/18 23:19:55 asmecher Exp $
15 */
16
17class String {
18
19        /**
20         * Perform initialization required for the string wrapper library.
21         */
22        function init() {
23                $clientCharset = strtolower(Config::getVar('i18n', 'client_charset'));
24
25                // FIXME Should non-UTF-8 encodings be supported with mbstring?
26                $PCRE_UTF8 = '';
27                if ($clientCharset == 'utf-8' && String::hasPCREUTF8()) {
28                        $PCRE_UTF8 = 'u';
29                }
30
31                // Check if mbstring is installed
32                // NOTE: Requires PHP >= 4.3.0
33                if (String::hasMBString()) {
34                        // mbstring routines are available
35                        define('ENABLE_MBSTRING', 1);
36
37                        // Set up required ini settings for mbstring
38                        ini_set('mbstring.internal_encoding', $clientCharset);
39                        if ($clientCharset == 'utf-8') {
40                                ini_set('mbstring.substitute_character', '12307');
41                        }
42
43                        // FIXME Do any other mbstring settings need to be set?
44                }
45
46                // Define modifier to be used in regexp_* routines
47                define('PCRE_UTF8', $PCRE_UTF8);
48        }
49
50        /**
51         * Check if server has the mbstring library.
52         * Currently requires PHP >= 4.3.0 (for mb_strtolower, mb_strtoupper, and mb_substr_count)
53         */
54        function hasMBString() {
55                return (function_exists('mb_strlen')
56                                && function_exists('mb_strpos')
57                                && function_exists('mb_strrpos')
58                                && function_exists('mb_substr')
59                                && function_exists('mb_strtolower')
60                                && function_exists('mb_strtoupper')
61                                && function_exists('mb_substr_count')
62                                && function_exists('mb_send_mail'));
63        }
64
65        /**
66         * Check if server supports the PCRE_UTF8 modifier.
67         */
68        function hasPCREUTF8() {
69                // The PCRE_UTF8 modifier is only supported on PHP >= 4.1.0 (*nix) or PHP >= 4.2.3 (win32)
70                // Evil check to see if PCRE_UTF8 is supported
71                if (@preg_match('//u', '')) {
72                        return true;
73                } else {
74                        return false;
75                }
76        }
77
78        //
79        // Wrappers for basic string manipulation routines.
80        // See the php.net documentation for usage.
81        //
82
83        function strlen($string) {
84                if (defined('ENABLE_MBSTRING')) {
85                        return mb_strlen($string);
86                } else {
87                        return strlen($string);
88                }
89        }
90
91        function strpos($haystack, $needle, $offset = 0) {
92                if (defined('ENABLE_MBSTRING')) {
93                        return mb_strpos($haystack, $needle, $offset);
94                } else {
95                        return strpos($haystack, $needle, $offset);
96                }
97        }
98
99        function strrpos($haystack, $needle) {
100                if (defined('ENABLE_MBSTRING')) {
101                        return mb_strrpos($haystack, $needle);
102                } else {
103                        return strrpos($haystack, $needle);
104                }
105        }
106
107        function substr($string, $start, $length = null) {
108                if (defined('ENABLE_MBSTRING')) {
109                        $substr = 'mb_substr';
110                } else {
111                        $substr = 'substr';
112                }
113                if (isset($length)) {
114                        return $substr($string, $start, $length);
115                } else {
116                        return $substr($string, $start);
117                }
118        }
119
120        function ucfirst($string) {
121                $fc = String::strtoupper(String::substr($string, 0, 1));
122                return $fc . String::substr($string, 1);
123        }
124
125        function strtolower($string) {
126                if (defined('ENABLE_MBSTRING')) {
127                        return mb_strtolower($string); // Requires PHP >= 4.3.0
128                } else {
129                        return strtolower($string);
130                }
131        }
132
133        function strtoupper($string) {
134                if (defined('ENABLE_MBSTRING')) {
135                        return mb_strtoupper($string); // Requires PHP >= 4.3.0
136                } else {
137                        return strtolower($string);
138                }
139        }
140
141        function substr_count($haystack, $needle) {
142                if (defined('ENABLE_MBSTRING')) {
143                        return mb_substr_count($haystack, $needle); // Requires PHP >= 4.3.0
144                } else {
145                        return substr_count($haystack, $needle);
146                }
147        }
148
149        function encode_mime_header($string) {
150                if (defined('ENABLE_MBSTRING')) {
151                        return mb_encode_mimeheader($string, ini_get('mbstring.internal_encoding'), 'B', MAIL_EOL);
152                }  else {
153                        return $string;
154                }
155        }
156
157        function mail($to, $subject, $message, $additional_headers = '', $additional_parameters = '') {
158                // Cannot use mb_send_mail as it base64 encodes the whole body of the email,
159                // making it useless for multipart emails
160                if (empty($additional_parameters)) {
161                        return mail($to, $subject, $message, $additional_headers);
162                } else {
163                        return mail($to, $subject, $message, $additional_headers, $additional_parameters);
164                }
165        }
166
167        //
168        // Wrappers for PCRE-compatible regular expression routines.
169        // See the php.net documentation for usage.
170        //
171
172        function regexp_quote($string, $delimiter = '/') {
173                return preg_quote($string, $delimiter);
174        }
175
176        function regexp_grep($pattern, $input) {
177                $pattern .= PCRE_UTF8;
178                return preg_grep($pattern, $input);
179        }
180
181        function regexp_match($pattern, $subject) {
182                $pattern .= PCRE_UTF8;
183                return preg_match($pattern, $subject);
184        }
185
186        function regexp_match_get($pattern, $subject, &$matches) {
187                // NOTE: This function was created since PHP < 5.x does not support optional reference parameters
188                $pattern .= PCRE_UTF8;
189                return preg_match($pattern, $subject, $matches);
190        }
191
192        function regexp_match_all($pattern, $subject, &$matches) {
193                $pattern .= PCRE_UTF8;
194                return preg_match_all($pattern, $subject, $matches);
195        }
196
197        function regexp_replace($pattern, $replacement, $subject, $limit = -1) {
198                $pattern .= PCRE_UTF8;
199                return preg_replace($pattern, $replacement, $subject, $limit);
200        }
201
202        function regexp_replace_callback($pattern, $callback, $subject, $limit = -1) {
203                $pattern .= PCRE_UTF8;
204                return preg_replace_callback($pattern, $callback, $subject, $limit);
205        }
206
207        function regexp_split($pattern, $subject, $limit = -1) {
208                $pattern .= PCRE_UTF8;
209                return preg_split($pattern, $subject, $limit);
210        }
211
212        function mime_content_type($filename) {
213                if (function_exists('mime_content_type')) {
214                        return mime_content_type($filename);
215                } elseif (function_exists('finfo_open')) {
216                        static $fi;
217                        if (!isset($fi)) {
218                                $fi = finfo_open(FILEINFO_MIME, Config::getVar('finfo', 'mime_database_path'));
219                        }
220                        if ($fi !== false) {
221                                return strtok(finfo_file($fi, $filename), ' ;');
222                        }
223                } 
224
225                $f = escapeshellarg($filename);
226                $result = trim(`file -bi $f`);
227                // Make sure we just return the mime type.
228                if (($i = strpos($result, ';')) !== false) {
229                        $result = trim(substr($result, 0, $i));
230                }
231                return $result;
232        }
233
234
235        /**
236         * Strip unsafe HTML from the input text. Covers XSS attacks like scripts,
237         * onclick(...) attributes, javascript: urls, and special characters.
238         * @param $input string input string
239         * @return string
240         */
241        function stripUnsafeHtml($input) {
242                // Parts of this implementation were taken from Horde:
243                // see http://cvs.horde.org/co.php/framework/MIME/MIME/Viewer/html.php.
244
245                $allowedHtml = Config::getVar('security', 'allowed_html');
246                if ($allowedHtml == '') $allowedHtml = '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <b> <i> <u> <img> <sup> <sub> <br> <p>';
247
248                $html = strip_tags($input, $allowedHtml);
249
250                // Change space entities to space characters
251                $html = preg_replace('/&#(x0*20|0*32);?/i', ' ', $html);
252
253                // Remove non-printable characters
254                $html = preg_replace('/&#x?0*([9A-D]|1[0-3]);/i', '&nbsp;', $html);
255                $html = preg_replace('/&#x?0*[9A-D]([^0-9A-F]|$)/i', '&nbsp\\1', $html);
256                $html = preg_replace('/&#0*(9|1[0-3])([^0-9]|$)/i', '&nbsp\\2', $html);
257
258                // Remove overly long numeric entities
259                $html = preg_replace('/&#x?0*[0-9A-F]{6,};?/i', '&nbsp;', $html);
260
261                /* Get all attribute="javascript:foo()" tags. This is
262                 * essentially the regex /(=|url\()("?)[^>]* script:/ but
263                 * expanded to catch camouflage with spaces and entities. */
264                $preg   = '/((&#0*61;?|&#x0*3D;?|=)|'
265                        . '((u|&#0*85;?|&#x0*55;?|&#0*117;?|&#x0*75;?)\s*'
266                        . '(r|&#0*82;?|&#x0*52;?|&#0*114;?|&#x0*72;?)\s*'
267                        . '(l|&#0*76;?|&#x0*4c;?|&#0*108;?|&#x0*6c;?)\s*'
268                        . '(\()))\s*'
269                        . '(&#0*34;?|&#x0*22;?|"|&#0*39;?|&#x0*27;?|\')?'
270                        . '[^>]*\s*'
271                        . '(s|&#0*83;?|&#x0*53;?|&#0*115;?|&#x0*73;?)\s*'
272                        . '(c|&#0*67;?|&#x0*43;?|&#0*99;?|&#x0*63;?)\s*'
273                        . '(r|&#0*82;?|&#x0*52;?|&#0*114;?|&#x0*72;?)\s*'
274                        . '(i|&#0*73;?|&#x0*49;?|&#0*105;?|&#x0*69;?)\s*'
275                        . '(p|&#0*80;?|&#x0*50;?|&#0*112;?|&#x0*70;?)\s*'
276                        . '(t|&#0*84;?|&#x0*54;?|&#0*116;?|&#x0*74;?)\s*'
277                        . '(:|&#0*58;?|&#x0*3a;?)/i';
278                $html = preg_replace($preg, '\1\8OCSCleaned', $html);
279
280                /* Get all on<foo>="bar()". NEVER allow these. */
281                $html = preg_replace('/([\s"\']+'
282                        . '(o|&#0*79;?|&#0*4f;?|&#0*111;?|&#0*6f;?)'
283                        . '(n|&#0*78;?|&#0*4e;?|&#0*110;?|&#0*6e;?)'
284                        . '\w+)\s*=/i', '\1OCSCleaned=', $html);
285
286                $pattern = array(
287                        '|<([^>]*)&{.*}([^>]*)>|',
288                        '|<([^>]*)mocha:([^>]*)>|i',
289                        '|<([^>]*)binding:([^>]*)>|i'
290                );
291                $replace = array('<&{;}\3>', '<\1OCSCleaned:\2>', '<\1OCSCleaned:\2>');
292                $html = preg_replace($pattern, $replace, $html);
293
294                return $html;
295        }
296
297        /**
298         * Detect whether a string contains non-ascii multibyte sequences in the UTF-8 range
299         * Does not require any multibyte PHP libraries
300         * @param $input string input string
301         * @return boolean
302         */
303        function isUTF8 ($str) {
304                // From http://w3.org/International/questions/qa-forms-utf-8.html
305                return preg_match('%(?:
306                                [\xC2-\xDF][\x80-\xBF]                                                          # non-overlong 2-byte
307                                |\xE0[\xA0-\xBF][\x80-\xBF]                                     # excluding overlongs
308                                |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}              # straight 3-byte
309                                |\xED[\x80-\x9F][\x80-\xBF]                                     # excluding surrogates
310                                |\xF0[\x90-\xBF][\x80-\xBF]{2}                          # planes 1-3
311                                |[\xF1-\xF3][\x80-\xBF]{3}                                              # planes 4-15
312                                |\xF4[\x80-\x8F][\x80-\xBF]{2}                          # plane 16
313                                )+%xs', $str);
314        }
315
316        /**
317         * Returns the UTF-8 string corresponding to the unicode value
318         * Does not require any multibyte PHP libraries
319         * (from php.net, courtesy - romans@void.lv)
320         * @param $input string input string
321         * @return boolean
322         */
323        function code2utf ($num) {
324                if ($num < 128) return chr($num);
325                if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128);
326                if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
327                if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
328                return '';
329        }
330
331        /**
332         * Convert UTF-8 encoded characters in a string to escaped HTML entities
333         * This is a helper function for transcoding into HTML
334         * @param $input string input string
335         * @return string
336         */
337        function utf2html ($str) {
338                $ret = "";
339                $max = strlen($str);
340                $last = 0;  // keeps the index of the last regular character
341
342                for ($i=0; $i<$max; $i++) {
343                        $c = $str{$i};
344                        $c1 = ord($c);
345                        if ($c1>>5 == 6) {                                                                              // 110x xxxx, 110 prefix for 2 bytes unicode
346                                $ret .= substr($str, $last, $i-$last);                  // append all the regular characters we've passed
347                                $c1 &= 31;                                                                                                      // remove the 3 bit two bytes prefix
348                                $c2 = ord($str{++$i});                                                          // the next byte
349                                $c2 &= 63;                                                                                                      // remove the 2 bit trailing byte prefix
350                                $c2 |= (($c1 & 3) << 6);                                                        // last 2 bits of c1 become first 2 of c2
351                                $c1 >>= 2;                                                                                                      // c1 shifts 2 to the right
352                                $ret .= "&#" . ($c1 * 0x100 + $c2) . ";";       // this is the fastest string concatenation
353                                $last = $i+1;     
354                        }
355                        elseif ($c1>>4 == 14) {                                                                 // 1110 xxxx, 110 prefix for 3 bytes unicode
356                                $ret .= substr($str, $last, $i-$last);                  // append all the regular characters we've passed
357                                $c2 = ord($str{++$i});                                                          // the next byte
358                                $c3 = ord($str{++$i});                                                          // the third byte
359                                $c1 &= 15;                                                                                              // remove the 4 bit three bytes prefix
360                                $c2 &= 63;                                                                                              // remove the 2 bit trailing byte prefix
361                                $c3 &= 63;                                                                                              // remove the 2 bit trailing byte prefix
362                                $c3 |= (($c2 & 3) << 6);                                                        // last 2 bits of c2 become first 2 of c3
363                                $c2 >>=2;                                                                                                       //c2 shifts 2 to the right
364                                $c2 |= (($c1 & 15) << 4);                                                       // last 4 bits of c1 become first 4 of c2
365                                $c1 >>= 4;                                                                                              // c1 shifts 4 to the right
366                                $ret .= '&#' . (($c1 * 0x10000) + ($c2 * 0x100) + $c3) . ';'; // this is the fastest string concatenation
367                                $last = $i+1;     
368                        }
369                }
370                $str=$ret . substr($str, $last, $i); // append the last batch of regular characters
371
372                return $str;   
373        }
374
375        /**
376         * Convert numeric HTML entities in a string to UTF-8 encoded characters
377         * This is a native alternative to the buggy html_entity_decode() using UTF8
378         * @param $input string input string
379         * @return string
380         */
381        function html2utf($str) {
382                // convert named entities to numeric entities
383                $str = strtr($str, String::getHTMLEntities());
384
385                // use PCRE-aware replace function to replace numeric entities
386                $str = String::regexp_replace('~&#x([0-9a-f]+);~ei', 'String::code2utf(hexdec("\\1"))', $str);
387                $str = String::regexp_replace('~&#([0-9]+);~e', 'String::code2utf(\\1)', $str);
388
389                return $str;
390         }
391
392        /**
393         * Convert UTF-8 numeric entities in a string to ASCII values
394         * This is a helper function for transcoding into HTML/XML
395         * @param $input string input string
396         * @return string
397         */
398        function html2ascii ($str) {
399                // define the conversion table
400                $entities = array(
401                        "&#126;" => "~",                        "&#160;" => " ",                                "&#161;" => "!",
402                        "&#166;" => "|",                                "&#177;" => "+/-",              "&#178;" => "2",
403                        "&#179;" => "3",                        "&#180;" => "'",                                "&#185;" => "1",
404                        "&#188;" => "1/4",              "&#189;" => "1/2",              "&#190;" => "3/4",
405                        "&#191;" => "?",                                "&#192;" => "A",                        "&#193;" => "A",
406                        "&#194;" => "A",                        "&#195;" => "A",                        "&#196;" => "A",
407                        "&#197;" => "A",                        "&#198;" => "AE",                       "&#199;" => "C",
408                        "&#200;" => "E",                        "&#201;" => "E",                        "&#202;" => "E",
409                        "&#203;" => "E",                        "&#204;" => "I",                                "&#205;" => "I",
410                        "&#206;" => "I",                                "&#207;" => "I",                                "&#208;" => "D",
411                        "&#209;" => "N",                        "&#210;" => "O",                        "&#211;" => "O",
412                        "&#212;" => "O",                        "&#213;" => "O",                        "&#214;" => "O",
413                        "&#215;" => "x",                        "&#216;" => "O",                        "&#217;" => "U",
414                        "&#218;" => "U",                        "&#220;" => "U",                        "&#221;" => "Y",
415                        "&#224;" => "a",                        "&#225;" => "a",                        "&#226;" => "a",
416                        "&#227;" => "a",                        "&#228;" => "a",                        "&#229;" => "a",
417                        "&#230;" => "ae",                       "&#231;" => "c",                                "&#232;" => "e",
418                        "&#233;" => "e",                        "&#234;" => "e",                        "&#235;" => "e",
419                        "&#236;" => "i",                                "&#237;" => "i",                                "&#238;" => "i",
420                        "&#239;" => "i",                                "&#240;" => "o",                        "&#241;" => "n",
421                        "&#242;" => "o",                        "&#243;" => "o",                        "&#244;" => "o",
422                        "&#245;" => "o",                        "&#246;" => "o",                        "&#248;" => "o",
423                        "&#249;" => "u",                        "&#250;" => "u",                        "&#252;" => "u",
424                        "&#253;" => "y",                                "&#255;" => "y",                                "&#338;" => "OE",
425                        "&#339;" => "oe",                       "&#352;" => "S",                        "&#353;" => "s",
426                        "&#376;" => "Y",                        "&#39;" => "'",                         "&#402;" => "f",
427                        "&#45;" => "-",                         "&#710;" => "^",                        "&#732;" => "~",
428                        "&#8194;" => " ",                       "&#8195;" => " ",                       "&#8201;" => " ",
429                        "&#8211;" => "-",                       "&#8212;" => "--",              "&#8216;" => "'",
430                        "&#8217;" => "'",                       "&#8218;" => ",",                       "&#8220;" => '"',
431                        "&#8221;" => '"',                       "&#8222;" => ",,",                      "&#8226;" => "*",
432                        "&#8230;" => "...",                     "&#8240;" => "%o",              "&#8242;" => "'",
433                        "&#8243;" => "''",                      "&#8482;" => "TM",              "&#8722;" => "-",
434                        "&#8727;" => "*",                       "&#8743;" => "/\\",             "&#8744;" => "\/",
435                        "&#8764;" => "~",                       "&#8901;" => "*",                       "&#913;" => "A",
436                        "&#914;" => "B",                        "&#917;" => "E",                        "&#918;" => "Z",
437                        "&#919;" => "H",                        "&#921;" => "|",                                "&#922;" => "K",
438                        "&#924;" => "M",                        "&#925;" => "N",                        "&#927;" => "O",
439                        "&#929;" => "P",                        "&#932;" => "T",                        "&#933;" => "Y",
440                        "&#935;" => "X",                        "&#94;" => "^",                         "&#959;" => "o",
441                        "&#961;" => "p",                        "&#962;" => "?",                                "&#977;" => "?",
442                        "&#982;" => "?");
443
444                return strtr($str, $entities);
445        }
446
447        /**
448         * Convert Windows CP-1252 numeric entities in a string to named HTML entities
449         * This is a helper function for transcoding into HTML/XML
450         * @param $input string input string
451         * @return string
452         */
453        function cp1252ToEntities ($str) {
454                // define the conversion table;  from: http://www.noqta.it/tc.html
455                $cp1252 = array(        "&#128;" => "",                                         "&#129;" => "",
456                                                                                "&#130;" => "&lsquor;",         "&#131;" => "&fnof;",
457                                                                                "&#132;" => "&ldquor;",         "&#133;" => "&hellip;",
458                                                                                "&#134;" => "&dagger;",         "&#135;" => "&Dagger;",
459                                                                                "&#136;" => "",                                         "&#137;" => "&permil;",
460                                                                                "&#138;" => "&Scaron;",         "&#139;" => "&lsaquo;",
461                                                                                "&#140;" => "&OElig;",                  "&#141;" => "",
462                                                                                "&#142;" => "",                                         "&#143;" => "",
463                                                                                "&#144;" => "",                                         "&#145;" => "&lsquo;",
464                                                                                "&#146;" => "&rsquo;",                  "&#147;" => "&ldquo;",
465                                                                                "&#148;" => "&rdquo;",          "&#149;" => "&bull;",
466                                                                                "&#150;" => "&ndash;",          "&#151;" => "&mdash;",
467                                                                                "&#152;" => "&tilde;",                  "&#153;" => "&trade;",
468                                                                                "&#154;" => "&scaron;",         "&#155;" => "&rsaquo;",
469                                                                                "&#156;" => "&oelig;",                  "&#157;" => "",
470                                                                                "&#158;" => "",                                         "&#159;" => "&Yuml;");
471
472                // corrections to map to valid ISO entities
473                $cp1252["&#130;"] = "&lsquo;";
474                $cp1252["&#132;"] = "&ldquo;";
475                $cp1252["&#146;"] = "&rsquo;";
476                $cp1252["&#148;"] = "&rdquo;";
477
478                return strtr($str, $cp1252);
479        }
480
481        /**
482         * Return an associative array of named->numeric HTML entities
483         * Required to support HTML functions without objects in PHP4/PHP5
484         * From php.net: function.get-html-translation-table.php
485         * @return string
486         */
487        function getHTMLEntities () {
488                // define the conversion table
489                $html_entities = array(
490                        "&Aacute;" => "&#193;",                 "&aacute;" => "&#225;",                 "&Acirc;" => "&#194;",
491                        "&acirc;" => "&#226;",                          "&acute;" => "&#180;",                          "&AElig;" => "&#198;",
492                        "&aelig;" => "&#230;",                          "&Agrave;" => "&#192;",                 "&agrave;" => "&#224;",
493                        "&alefsym;" => "&#8501;",               "&Alpha;" => "&#913;",                          "&alpha;" => "&#945;",
494                        "&amp;" => "&#38;",                                     "&and;" => "&#8743;",                           "&ang;" => "&#8736;",
495                        "&apos;" => "&#39;",                                    "&Aring;" => "&#197;",                          "&aring;" => "&#229;",
496                        "&asymp;" => "&#8776;",                 "&Atilde;" => "&#195;",                         "&atilde;" => "&#227;",
497                        "&Auml;" => "&#196;",                           "&auml;" => "&#228;",                           "&bdquo;" => "&#8222;",
498                        "&Beta;" => "&#914;",                           "&beta;" => "&#946;",                           "&brvbar;" => "&#166;",
499                        "&bull;" => "&#8226;",                          "&cap;" => "&#8745;",                           "&Ccedil;" => "&#199;",
500                        "&ccedil;" => "&#231;",                         "&cedil;" => "&#184;",                          "&cent;" => "&#162;",
501                        "&Chi;" => "&#935;",                                    "&chi;" => "&#967;",                                    "&circ;" => "&#94;",
502                        "&clubs;" => "&#9827;",                 "&cong;" => "&#8773;",                  "&copy;" => "&#169;",
503                        "&crarr;" => "&#8629;",                 "&cup;" => "&#8746;",                           "&curren;" => "&#164;",
504                        "&dagger;" => "&#8224;",                "&Dagger;" => "&#8225;",                "&darr;" => "&#8595;",
505                        "&dArr;" => "&#8659;",                          "&deg;" => "&#176;",                            "&Delta;" => "&#916;",
506                        "&delta;" => "&#948;",                          "&diams;" => "&#9830;",                 "&divide;" => "&#247;",
507                        "&Eacute;" => "&#201;",                 "&eacute;" => "&#233;",                 "&Ecirc;" => "&#202;",
508                        "&ecirc;" => "&#234;",                          "&Egrave;" => "&#200;",                 "&egrave;" => "&#232;",
509                        "&empty;" => "&#8709;",                 "&emsp;" => "&#8195;",                  "&ensp;" => "&#8194;",
510                        "&Epsilon;" => "&#917;",                        "&epsilon;" => "&#949;",                        "&equiv;" => "&#8801;",
511                        "&Eta;" => "&#919;",                                    "&eta;" => "&#951;",                                    "&ETH;" => "&#208;",
512                        "&eth;" => "&#240;",                                    "&Euml;" => "&#203;",                           "&euml;" => "&#235;",
513                        "&euro;" => "&#8364;",                          "&exist;" => "&#8707;",                 "&fnof;" => "&#402;",
514                        "&forall;" => "&#8704;",                        "&frac12;" => "&#189;",                 "&frac14;" => "&#188;",
515                        "&frac34;" => "&#190;",                 "&frasl;" => "&#8260;",                         "&Gamma;" => "&#915;",
516                        "&gamma;" => "&#947;",                  "&ge;" => "&#8805;",                            "&gt;" => "&#62;",
517                        "&harr;" => "&#8596;",                          "&hArr;" => "&#8660;",                          "&hearts;" => "&#9829;",
518                        "&hellip;" => "&#8230;",                        "&Iacute;" => "&#205;",                         "&iacute;" => "&#237;",
519                        "&Icirc;" => "&#206;",                          "&icirc;" => "&#238;",                          "&iexcl;" => "&#161;",
520                        "&Igrave;" => "&#204;",                 "&igrave;" => "&#236;",                 "&image;" => "&#8465;",
521                        "&infin;" => "&#8734;",                         "&int;" => "&#8747;",                           "&Iota;" => "&#921;",
522                        "&iota;" => "&#953;",                           "&iquest;" => "&#191;",                 "&isin;" => "&#8712;",
523                        "&Iuml;" => "&#207;",                           "&iuml;" => "&#239;",                           "&Kappa;" => "&#922;",
524                        "&kappa;" => "&#954;",                  "&Lambda;" => "&#923;",                 "&lambda;" => "&#955;",
525                        "&lang;" => "&#9001;",                          "&laquo;" => "&#171;",                          "&larr;" => "&#8592;",
526                        "&lArr;" => "&#8656;",                          "&lceil;" => "&#8968;",                         
527                        "&ldquo;" => "&#8220;",                 "&le;" => "&#8804;",                                    "&lfloor;" => "&#8970;",
528                        "&lowast;" => "&#8727;",                        "&loz;" => "&#9674;",                           "&lrm;" => "&#8206;",
529                        "&lsaquo;" => "&#8249;",                        "&lsquo;" => "&#8216;",                 "&lt;" => "&#60;",
530                        "&macr;" => "&#175;",                           "&mdash;" => "&#8212;",                 "&micro;" => "&#181;",
531                        "&middot;" => "&#183;",                 "&minus;" => "&#45;",                           "&Mu;" => "&#924;",
532                        "&mu;" => "&#956;",                                     "&nabla;" => "&#8711;",                 "&nbsp;" => "&#160;",
533                        "&ndash;" => "&#8211;",                 "&ne;" => "&#8800;",                            "&ni;" => "&#8715;",
534                        "&not;" => "&#172;",                                    "&notin;" => "&#8713;",                 "&nsub;" => "&#8836;",
535                        "&Ntilde;" => "&#209;",                         "&ntilde;" => "&#241;",                         "&Nu;" => "&#925;",
536                        "&nu;" => "&#957;",                                     "&Oacute;" => "&#211;",                 "&oacute;" => "&#243;",
537                        "&Ocirc;" => "&#212;",                          "&ocirc;" => "&#244;",                          "&OElig;" => "&#338;",
538                        "&oelig;" => "&#339;",                          "&Ograve;" => "&#210;",                 "&ograve;" => "&#242;",
539                        "&oline;" => "&#8254;",                 "&Omega;" => "&#937;",                  "&omega;" => "&#969;",
540                        "&Omicron;" => "&#927;",                "&omicron;" => "&#959;",                        "&oplus;" => "&#8853;",
541                        "&or;" => "&#8744;",                                    "&ordf;" => "&#170;",                           "&ordm;" => "&#186;",
542                        "&Oslash;" => "&#216;",                 "&oslash;" => "&#248;",                 "&Otilde;" => "&#213;",
543                        "&otilde;" => "&#245;",                         "&otimes;" => "&#8855;",                        "&Ouml;" => "&#214;",
544                        "&ouml;" => "&#246;",                           "&para;" => "&#182;",                           "&part;" => "&#8706;",
545                        "&permil;" => "&#8240;",                        "&perp;" => "&#8869;",                          "&Phi;" => "&#934;",
546                        "&phi;" => "&#966;",                                    "&Pi;" => "&#928;",                                     "&pi;" => "&#960;",
547                        "&piv;" => "&#982;",                                    "&plusmn;" => "&#177;",                 "&pound;" => "&#163;",
548                        "&prime;" => "&#8242;",                 "&Prime;" => "&#8243;",                 "&prod;" => "&#8719;",
549                        "&prop;" => "&#8733;",                  "&Psi;" => "&#936;",                                    "&psi;" => "&#968;",
550                        "&quot;" => "&#34;",                                    "&radic;" => "&#8730;",                 "&rang;" => "&#9002;",
551                        "&raquo;" => "&#187;",                          "&rarr;" => "&#8594;",                          "&rArr;" => "&#8658;",
552                        "&rceil;" => "&#8969;",                         "&rdquo;" => "&#8221;",                 "&real;" => "&#8476;",
553                        "&reg;" => "&#174;",                                    "&rfloor;" => "&#8971;",                        "&Rho;" => "&#929;",
554                        "&rho;" => "&#961;",                                    "&rlm;" => "&#8207;",                           "&rsaquo;" => "&#8250;",
555                        "&rsquo;" => "&#8217;",                 "&sbquo;" => "&#8218;",                 "&Scaron;" => "&#352;",
556                        "&scaron;" => "&#353;",                 "&sdot;" => "&#8901;",                          "&sect;" => "&#167;",
557                        "&shy;" => "&#173;",                                    "&Sigma;" => "&#931;",                  "&sigma;" => "&#963;",
558                        "&sigmaf;" => "&#962;",                 "&sim;" => "&#8764;",                           "&spades;" => "&#9824;",
559                        "&sub;" => "&#8834;",                           "&sube;" => "&#8838;",                  "&sum;" => "&#8721;",
560                        "&sup1;" => "&#185;",                           "&sup2;" => "&#178;",                           "&sup3;" => "&#179;",
561                        "&sup;" => "&#8835;",                           "&supe;" => "&#8839;",                  "&szlig;" => "&#223;",
562                        "&Tau;" => "&#932;",                            "&tau;" => "&#964;",                                    "&there4;" => "&#8756;",
563                        "&Theta;" => "&#920;",                          "&theta;" => "&#952;",                          "&thetasym;" => "&#977;",
564                        "&thinsp;" => "&#8201;",                        "&THORN;" => "&#222;",                  "&thorn;" => "&#254;",
565                        "&tilde;" => "&#126;",                          "&times;" => "&#215;",                          "&trade;" => "&#8482;",
566                        "&Uacute;" => "&#218;",                 "&uacute;" => "&#250;",                 "&uarr;" => "&#8593;",
567                        "&uArr;" => "&#8657;",                          "&Ucirc;" => "&#219;",                          "&ucirc;" => "&#251;",
568                        "&Ugrave;" => "&#217;",                 "&ugrave;" => "&#249;",                 "&uml;" => "&#168;",
569                        "&upsih;" => "&#978;",                          "&Upsilon;" => "&#933;",                        "&upsilon;" => "&#965;",
570                        "&Uuml;" => "&#220;",                           "&uuml;" => "&#252;",                           "&weierp;" => "&#8472;",
571                        "&Xi;" => "&#926;",                                     "&xi;" => "&#958;",                                     "&Yacute;" => "&#221;",
572                        "&yacute;" => "&#253;",                 "&yen;" => "&#165;",                                    "&yuml;" => "&#255;",
573                        "&Yuml;" => "&#376;",                           "&Zeta;" => "&#918;",                           "&zeta;" => "&#950;",
574                        "&zwj;" => "&#8205;",                           "&zwnj;" => "&#8204;");
575
576                return $html_entities;
577        }
578
579        /**
580         * Wrapper around fputcsv for systems that may or may not support it
581         * (i.e. PHP < 5.1.0); see PHP documentation for fputcsv.
582         */
583        function fputcsv(&$handle, $fields = array(), $delimiter = ',', $enclosure = '"') {
584                // From PHP website, thanks to boefje at hotmail dot com
585                if (function_exists('fputcsv')) {
586                        return fputcsv($handle, $fields, $delimiter, $enclosure);
587                }
588                $str = '';
589                $escape_char = '\\';
590                foreach ($fields as $value) {
591                        if (    strpos($value, $delimiter) !== false ||
592                                strpos($value, $enclosure) !== false ||
593                                strpos($value, "\n") !== false ||
594                                strpos($value, "\r") !== false ||
595                                strpos($value, "\t") !== false ||
596                                strpos($value, ' ') !== false
597                        ) {
598                                $str2 = $enclosure;
599                                $escaped = 0;
600                                $len = strlen($value);
601                                for ($i=0; $i<$len; $i++) {
602                                        if ($value[$i] == $escape_char) $escaped = 1;
603                                        elseif (!$escaped && $value[$i] == $enclosure) $str2 .= $enclosure;
604                                        else $escaped = 0;
605                                        $str2 .= $value[$i];
606                                }
607                                $str2 .= $enclosure;
608                                $str .= $str2 . $delimiter;
609                        } else {
610                                $str .= $value . $delimiter;
611                        }
612                }
613                $str = substr($str, 0, -1);
614                $str .= "\n";
615                return fwrite($handle, $str);
616        }
617}
618
619?>