source: trunk/zpush/lib/utils/utils.php @ 8131

Revision 8131, 34.2 KB checked in by cristiano, 11 years ago (diff)

Ticket #3209 - Integrar módulo de sincronização Z-push ao Expresso

Line 
1<?php
2/***********************************************
3* File      :   utils.php
4* Project   :   Z-Push
5* Descr     :   Several utility functions
6*
7* Created   :   03.04.2008
8*
9* Copyright 2007 - 2012 Zarafa Deutschland GmbH
10*
11* This program is free software: you can redistribute it and/or modify
12* it under the terms of the GNU Affero General Public License, version 3,
13* as published by the Free Software Foundation with the following additional
14* term according to sec. 7:
15*
16* According to sec. 7 of the GNU Affero General Public License, version 3,
17* the terms of the AGPL are supplemented with the following terms:
18*
19* "Zarafa" is a registered trademark of Zarafa B.V.
20* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
21* The licensing of the Program under the AGPL does not imply a trademark license.
22* Therefore any rights, title and interest in our trademarks remain entirely with us.
23*
24* However, if you propagate an unmodified version of the Program you are
25* allowed to use the term "Z-Push" to indicate that you distribute the Program.
26* Furthermore you may use our trademarks where it is necessary to indicate
27* the intended purpose of a product or service provided you use it in accordance
28* with honest practices in industrial or commercial matters.
29* If you want to propagate modified versions of the Program under the name "Z-Push",
30* you may only do so if you have a written permission by Zarafa Deutschland GmbH
31* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
32*
33* This program is distributed in the hope that it will be useful,
34* but WITHOUT ANY WARRANTY; without even the implied warranty of
35* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36* GNU Affero General Public License for more details.
37*
38* You should have received a copy of the GNU Affero General Public License
39* along with this program.  If not, see <http://www.gnu.org/licenses/>.
40*
41* Consult LICENSE file for details
42************************************************/
43
44class Utils {
45    /**
46     * Prints a variable as string
47     * If a boolean is sent, 'true' or 'false' is displayed
48     *
49     * @param string $var
50     * @access public
51     * @return string
52     */
53    static public function PrintAsString($var) {
54      return ($var)?(($var===true)?'true':$var):(($var===false)?'false':(($var==='')?'empty':$var));
55//return ($var)?(($var===true)?'true':$var):'false';
56    }
57
58    /**
59     * Splits a "domain\user" string into two values
60     * If the string cotains only the user, domain is returned empty
61     *
62     * @param string    $domainuser
63     *
64     * @access public
65     * @return array    index 0: user  1: domain
66     */
67    static public function SplitDomainUser($domainuser) {
68        $pos = strrpos($domainuser, '\\');
69        if($pos === false){
70            $user = $domainuser;
71            $domain = '';
72        }
73        else{
74            $domain = substr($domainuser,0,$pos);
75            $user = substr($domainuser,$pos+1);
76        }
77        return array($user, $domain);
78    }
79
80    /**
81     * iPhone defines standard summer time information for current year only,
82     * starting with time change in February. Dates from the 1st January until
83     * the time change are undefined and the server uses GMT or its current time.
84     * The function parses the ical attachment and replaces DTSTART one year back
85     * in VTIMEZONE section if the event takes place in this undefined time.
86     * See also http://developer.berlios.de/mantis/view.php?id=311
87     *
88     * @param string    $ical               iCalendar data
89     *
90     * @access public
91     * @return string
92     */
93    static public function IcalTimezoneFix($ical) {
94        $eventDate = substr($ical, (strpos($ical, ":", strpos($ical, "DTSTART", strpos($ical, "BEGIN:VEVENT")))+1), 8);
95        $posStd = strpos($ical, "DTSTART:", strpos($ical, "BEGIN:STANDARD")) + strlen("DTSTART:");
96        $posDst = strpos($ical, "DTSTART:", strpos($ical, "BEGIN:DAYLIGHT")) + strlen("DTSTART:");
97        $beginStandard = substr($ical, $posStd , 8);
98        $beginDaylight = substr($ical, $posDst , 8);
99
100        if (($eventDate < $beginStandard) && ($eventDate < $beginDaylight) ) {
101            ZLog::Write(LOGLEVEL_DEBUG,"icalTimezoneFix for event on $eventDate, standard:$beginStandard, daylight:$beginDaylight");
102            $year = intval(date("Y")) - 1;
103            $ical = substr_replace($ical, $year, (($beginStandard < $beginDaylight) ? $posDst : $posStd), strlen($year));
104        }
105
106        return $ical;
107    }
108
109    /**
110     * Build an address string from the components
111     *
112     * @param string    $street     the street
113     * @param string    $zip        the zip code
114     * @param string    $city       the city
115     * @param string    $state      the state
116     * @param string    $country    the country
117     *
118     * @access public
119     * @return string   the address string or null
120     */
121    static public function BuildAddressString($street, $zip, $city, $state, $country) {
122        $out = "";
123
124        if (isset($country) && $street != "") $out = $country;
125
126        $zcs = "";
127        if (isset($zip) && $zip != "") $zcs = $zip;
128        if (isset($city) && $city != "") $zcs .= (($zcs)?" ":"") . $city;
129        if (isset($state) && $state != "") $zcs .= (($zcs)?" ":"") . $state;
130        if ($zcs) $out = $zcs . "\r\n" . $out;
131
132        if (isset($street) && $street != "") $out = $street . (($out)?"\r\n\r\n". $out: "") ;
133
134        return ($out)?$out:null;
135    }
136
137    /**
138     * Build the fileas string from the components according to the configuration.
139     *
140     * @param string $lastname
141     * @param string $firstname
142     * @param string $middlename
143     * @param string $company
144     *
145     * @access public
146     * @return string fileas
147     */
148    static public function BuildFileAs($lastname = "", $firstname = "", $middlename = "", $company = "") {
149        if (defined('FILEAS_ORDER')) {
150            $fileas = $lastfirst = $firstlast = "";
151            $names = trim ($firstname . " " . $middlename);
152            $lastname = trim($lastname);
153            $company = trim($company);
154
155            // lastfirst is "lastname, firstname middlename"
156            // firstlast is "firstname middlename lastname"
157            if (strlen($lastname) > 0) {
158                $lastfirst = $lastname;
159                if (strlen($names) > 0){
160                    $lastfirst .= ", $names";
161                    $firstlast = "$names $lastname";
162                }
163                else {
164                    $firstlast = $lastname;
165                }
166            }
167            elseif (strlen($names) > 0) {
168                $lastfirst = $firstlast = $names;
169            }
170
171            // if fileas with a company is selected
172            // but company is emtpy then it will
173            // fallback to firstlast or lastfirst
174            // (depending on which is selected for company)
175            switch (FILEAS_ORDER) {
176                case SYNC_FILEAS_COMPANYONLY:
177                    if (strlen($company) > 0) {
178                        $fileas = $company;
179                    }
180                    elseif (strlen($firstlast) > 0)
181                        $fileas = $lastfirst;
182                    break;
183                case SYNC_FILEAS_COMPANYLAST:
184                    if (strlen($company) > 0) {
185                        $fileas = $company;
186                        if (strlen($lastfirst) > 0)
187                            $fileas .= "($lastfirst)";
188                    }
189                    elseif (strlen($lastfirst) > 0)
190                        $fileas = $lastfirst;
191                    break;
192                case SYNC_FILEAS_COMPANYFIRST:
193                    if (strlen($company) > 0) {
194                        $fileas = $company;
195                        if (strlen($firstlast) > 0) {
196                            $fileas .= " ($firstlast)";
197                        }
198                    }
199                    elseif (strlen($firstlast) > 0) {
200                        $fileas = $firstlast;
201                    }
202                    break;
203                case SYNC_FILEAS_FIRSTCOMPANY:
204                    if (strlen($firstlast) > 0) {
205                        $fileas = $firstlast;
206                        if (strlen($company) > 0) {
207                            $fileas .= " ($company)";
208                        }
209                    }
210                    elseif (strlen($company) > 0) {
211                        $fileas = $company;
212                    }
213                    break;
214                case SYNC_FILEAS_LASTCOMPANY:
215                    if (strlen($lastfirst) > 0) {
216                        $fileas = $lastfirst;
217                        if (strlen($company) > 0) {
218                            $fileas .= " ($company)";
219                        }
220                    }
221                    elseif (strlen($company) > 0) {
222                        $fileas = $company;
223                    }
224                    break;
225                case SYNC_FILEAS_LASTFIRST:
226                    if (strlen($lastfirst) > 0) {
227                        $fileas = $lastfirst;
228                    }
229                    break;
230                default:
231                    $fileas = $firstlast;
232                    break;
233            }
234            if (strlen($fileas) == 0)
235                ZLog::Write(LOGLEVEL_DEBUG, "Fileas is empty.");
236            return $fileas;
237        }
238        ZLog::Write(LOGLEVEL_DEBUG, "FILEAS_ORDER not defined. Add it to your config.php.");
239        return null;
240    }
241    /**
242     * Checks if the PHP-MAPI extension is available and in a requested version
243     *
244     * @param string    $version    the version to be checked ("6.30.10-18495", parts or build number)
245     *
246     * @access public
247     * @return boolean installed version is superior to the checked strin
248     */
249    static public function CheckMapiExtVersion($version = "") {
250        // compare build number if requested
251        if (preg_match('/^\d+$/', $version) && strlen($version) > 3) {
252            $vs = preg_split('/-/', phpversion("mapi"));
253            return ($version <= $vs[1]);
254        }
255
256        if (extension_loaded("mapi")){
257            if (version_compare(phpversion("mapi"), $version) == -1){
258                return false;
259            }
260        }
261        else
262            return false;
263
264        return true;
265    }
266
267    /**
268     * Parses and returns an ecoded vCal-Uid from an
269     * OL compatible GlobalObjectID
270     *
271     * @param string    $olUid      an OL compatible GlobalObjectID
272     *
273     * @access public
274     * @return string   the vCal-Uid if available in the olUid, else the original olUid as HEX
275     */
276    static public function GetICalUidFromOLUid($olUid){
277        //check if "vCal-Uid" is somewhere in outlookid case-insensitive
278        $icalUid = stristr($olUid, "vCal-Uid");
279        if ($icalUid !== false) {
280            //get the length of the ical id - go back 4 position from where "vCal-Uid" was found
281            $begin = unpack("V", substr($olUid, strlen($icalUid) * (-1) - 4, 4));
282            //remove "vCal-Uid" and packed "1" and use the ical id length
283            return substr($icalUid, 12, ($begin[1] - 13));
284        }
285        return strtoupper(bin2hex($olUid));
286    }
287
288    /**
289     * Checks the given UID if it is an OL compatible GlobalObjectID
290     * If not, the given UID is encoded inside the GlobalObjectID
291     *
292     * @param string    $icalUid    an appointment uid as HEX
293     *
294     * @access public
295     * @return string   an OL compatible GlobalObjectID
296     *
297     */
298    static public function GetOLUidFromICalUid($icalUid) {
299        if (strlen($icalUid) <= 64) {
300            $len = 13 + strlen($icalUid);
301            $OLUid = pack("V", $len);
302            $OLUid .= "vCal-Uid";
303            $OLUid .= pack("V", 1);
304            $OLUid .= $icalUid;
305            return hex2bin("040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000". bin2hex($OLUid). "00");
306        }
307        else
308           return hex2bin($icalUid);
309    }
310
311    /**
312     * Extracts the basedate of the GlobalObjectID and the RecurStartTime
313     *
314     * @param string    $goid           OL compatible GlobalObjectID
315     * @param long      $recurStartTime
316     *
317     * @access public
318     * @return long     basedate
319     */
320    static public function ExtractBaseDate($goid, $recurStartTime) {
321        $hexbase = substr(bin2hex($goid), 32, 8);
322        $day = hexdec(substr($hexbase, 6, 2));
323        $month = hexdec(substr($hexbase, 4, 2));
324        $year = hexdec(substr($hexbase, 0, 4));
325
326        if ($day && $month && $year) {
327            $h = $recurStartTime >> 12;
328            $m = ($recurStartTime - $h * 4096) >> 6;
329            $s = $recurStartTime - $h * 4096 - $m * 64;
330
331            return gmmktime($h, $m, $s, $month, $day, $year);
332        }
333        else
334            return false;
335    }
336
337    /**
338     * Converts SYNC_FILTERTYPE into a timestamp
339     *
340     * @param int       Filtertype
341     *
342     * @access public
343     * @return long
344     */
345    static public function GetCutOffDate($restrict) {
346        switch($restrict) {
347            case SYNC_FILTERTYPE_1DAY:
348                $back = 60 * 60 * 24;
349                break;
350            case SYNC_FILTERTYPE_3DAYS:
351                $back = 60 * 60 * 24 * 3;
352                break;
353            case SYNC_FILTERTYPE_1WEEK:
354                $back = 60 * 60 * 24 * 7;
355                break;
356            case SYNC_FILTERTYPE_2WEEKS:
357                $back = 60 * 60 * 24 * 14;
358                break;
359            case SYNC_FILTERTYPE_1MONTH:
360                $back = 60 * 60 * 24 * 31;
361                break;
362            case SYNC_FILTERTYPE_3MONTHS:
363                $back = 60 * 60 * 24 * 31 * 3;
364                break;
365            case SYNC_FILTERTYPE_6MONTHS:
366                $back = 60 * 60 * 24 * 31 * 6;
367                break;
368            default:
369                break;
370        }
371
372        if(isset($back)) {
373            $date = time() - $back;
374            return $date;
375        } else
376            return 0; // unlimited
377    }
378
379    /**
380     * Converts SYNC_TRUNCATION into bytes
381     *
382     * @param int       SYNC_TRUNCATION
383     *
384     * @return long
385     */
386    static public function GetTruncSize($truncation) {
387        switch($truncation) {
388            case SYNC_TRUNCATION_HEADERS:
389                return 0;
390            case SYNC_TRUNCATION_512B:
391                return 512;
392            case SYNC_TRUNCATION_1K:
393                return 1024;
394            case SYNC_TRUNCATION_2K:
395                return 2*1024;
396            case SYNC_TRUNCATION_5K:
397                return 5*1024;
398            case SYNC_TRUNCATION_10K:
399                return 10*1024;
400            case SYNC_TRUNCATION_20K:
401                return 20*1024;
402            case SYNC_TRUNCATION_50K:
403                return 50*1024;
404            case SYNC_TRUNCATION_100K:
405                return 100*1024;
406            case SYNC_TRUNCATION_ALL:
407                return 1024*1024; // We'll limit to 1MB anyway
408            default:
409                return 1024; // Default to 1Kb
410        }
411    }
412
413    /**
414     * Truncate an UTF-8 encoded sting correctly
415     *
416     * If it's not possible to truncate properly, an empty string is returned
417     *
418     * @param string $string - the string
419     * @param string $length - position where string should be cut
420     * @return string truncated string
421     */
422    static public function Utf8_truncate($string, $length) {
423        // make sure length is always an interger
424        $length = (int)$length;
425
426        if (strlen($string) <= $length)
427            return $string;
428
429        while($length >= 0) {
430            if ((ord($string[$length]) < 0x80) || (ord($string[$length]) >= 0xC0))
431                return substr($string, 0, $length);
432
433            $length--;
434        }
435        return "";
436    }
437
438    /**
439     * Indicates if the specified folder type is a system folder
440     *
441     * @param int            $foldertype
442     *
443     * @access public
444     * @return boolean
445     */
446    static public function IsSystemFolder($foldertype) {
447        return ($foldertype == SYNC_FOLDER_TYPE_INBOX || $foldertype == SYNC_FOLDER_TYPE_DRAFTS || $foldertype == SYNC_FOLDER_TYPE_WASTEBASKET || $foldertype == SYNC_FOLDER_TYPE_SENTMAIL ||
448                $foldertype == SYNC_FOLDER_TYPE_OUTBOX || $foldertype == SYNC_FOLDER_TYPE_TASK /*|| $foldertype == SYNC_FOLDER_TYPE_APPOINTMENT */|| $foldertype == SYNC_FOLDER_TYPE_CONTACT ||
449                $foldertype == SYNC_FOLDER_TYPE_NOTE || $foldertype == SYNC_FOLDER_TYPE_JOURNAL) ? true:false;
450    }
451
452    /**
453     * Our own utf7_decode function because imap_utf7_decode converts a string
454     * into ISO-8859-1 encoding which doesn't have euro sign (it will be converted
455     * into two chars: [space](ascii 32) and "¬" ("not sign", ascii 172)). Also
456     * php iconv function expects '+' as delimiter instead of '&' like in IMAP.
457     *
458     * @param string $string IMAP folder name
459     *
460     * @access public
461     * @return string
462    */
463    static public function Utf7_iconv_decode($string) {
464        //do not alter string if there aren't any '&' or '+' chars because
465        //it won't have any utf7-encoded chars and nothing has to be escaped.
466        if (strpos($string, '&') === false && strpos($string, '+') === false ) return $string;
467
468        //Get the string length and go back through it making the replacements
469        //necessary
470        $len = strlen($string) - 1;
471        while ($len > 0) {
472            //look for '&-' sequence and replace it with '&'
473            if ($len > 0 && $string{($len-1)} == '&' && $string{$len} == '-') {
474                $string = substr_replace($string, '&', $len - 1, 2);
475                $len--; //decrease $len as this char has alreasy been processed
476            }
477            //search for '&' which weren't found in if clause above and
478            //replace them with '+' as they mark an utf7-encoded char
479            if ($len > 0 && $string{($len-1)} == '&') {
480                $string = substr_replace($string, '+', $len - 1, 1);
481                $len--; //decrease $len as this char has alreasy been processed
482            }
483            //finally "escape" all remaining '+' chars
484            if ($len > 0 && $string{($len-1)} == '+') {
485                $string = substr_replace($string, '+-', $len - 1, 1);
486            }
487            $len--;
488        }
489        return $string;
490    }
491
492    /**
493     * Our own utf7_encode function because the string has to be converted from
494     * standard UTF7 into modified UTF7 (aka UTF7-IMAP).
495     *
496     * @param string $str IMAP folder name
497     *
498     * @access public
499     * @return string
500    */
501    static public function Utf7_iconv_encode($string) {
502        //do not alter string if there aren't any '&' or '+' chars because
503        //it won't have any utf7-encoded chars and nothing has to be escaped.
504        if (strpos($string, '&') === false && strpos($string, '+') === false ) return $string;
505
506        //Get the string length and go back through it making the replacements
507        //necessary
508        $len = strlen($string) - 1;
509        while ($len > 0) {
510            //look for '&-' sequence and replace it with '&'
511            if ($len > 0 && $string{($len-1)} == '+' && $string{$len} == '-') {
512                $string = substr_replace($string, '+', $len - 1, 2);
513                $len--; //decrease $len as this char has alreasy been processed
514            }
515            //search for '&' which weren't found in if clause above and
516            //replace them with '+' as they mark an utf7-encoded char
517            if ($len > 0 && $string{($len-1)} == '+') {
518                $string = substr_replace($string, '&', $len - 1, 1);
519                $len--; //decrease $len as this char has alreasy been processed
520            }
521            //finally "escape" all remaining '+' chars
522            if ($len > 0 && $string{($len-1)} == '&') {
523                $string = substr_replace($string, '&-', $len - 1, 1);
524            }
525            $len--;
526        }
527        return $string;
528    }
529
530    /**
531     * Converts an UTF-7 encoded string into an UTF-8 string.
532     *
533     * @param string $string to convert
534     *
535     * @access public
536     * @return string
537     */
538    static public function Utf7_to_utf8($string) {
539        if (function_exists("iconv")){
540            return @iconv("UTF-7", "UTF-8", $string);
541        }
542        return $string;
543    }
544
545    /**
546     * Converts an UTF-8 encoded string into an UTF-7 string.
547     *
548     * @param string $string to convert
549     *
550     * @access public
551     * @return string
552     */
553    static public function Utf8_to_utf7($string) {
554        if (function_exists("iconv")){
555            return @iconv("UTF-8", "UTF-7", $string);
556        }
557        return $string;
558    }
559
560    /**
561     * Checks for valid email addresses
562     * The used regex actually only checks if a valid email address is part of the submitted string
563     * it also returns true for the mailbox format, but this is not checked explicitly
564     *
565     * @param string $email     address to be checked
566     *
567     * @access public
568     * @return boolean
569     */
570    static public function CheckEmail($email) {
571        return (bool) preg_match('#([a-zA-Z0-9_\-])+(\.([a-zA-Z0-9_\-])+)*@((\[(((([0-1])?([0-9])?[0-9])|(2[0-4][0-9])|(2[0-5][0-5])))\.(((([0-1])?([0-9])?[0-9])|(2[0-4][0-9])|(2[0-5][0-5])))\.(((([0-1])?([0-9])?[0-9])|(2[0-4][0-9])|(2[0-5][0-5])))\.(((([0-1])?([0-9])?[0-9])|(2[0-4][0-9])|(2[0-5][0-5]))\]))|((([a-zA-Z0-9])+(([\-])+([a-zA-Z0-9])+)*\.)+([a-zA-Z])+(([\-])+([a-zA-Z0-9])+)*)|localhost)#', $email);
572    }
573
574    /**
575     * Checks if a string is base64 encoded
576     *
577     * @param string $string    the string to be checked
578     *
579     * @access public
580     * @return boolean
581     */
582    static public function IsBase64String($string) {
583        return (bool) preg_match("#^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+/]{4})?$#", $string);
584    }
585
586    /**
587     * Decodes base64 encoded query parameters. Based on dw2412 contribution.
588     *
589     * @param string $query     the query to decode
590     *
591     * @access public
592     * @return array
593     */
594    static public function DecodeBase64URI($query) {
595        /*
596         * The query string has a following structure. Number in () is position:
597         * 1 byte       - protocoll version (0)
598         * 1 byte       - command code (1)
599         * 2 bytes      - locale (2)
600         * 1 byte       - device ID length (4)
601         * variable     - device ID (4+device ID length)
602         * 1 byte       - policy key length (5+device ID length)
603         * 0 or 4 bytes - policy key (5+device ID length + policy key length)
604         * 1 byte       - device type length (6+device ID length + policy key length)
605         * variable     - device type (6+device ID length + policy key length + device type length)
606         * variable     - command parameters, array which consists of:
607         *                      1 byte      - tag
608         *                      1 byte      - length
609         *                      variable    - value of the parameter
610         *
611         */
612        $decoded = base64_decode($query);
613        $devIdLength = ord($decoded[4]); //device ID length
614        $polKeyLength = ord($decoded[5+$devIdLength]); //policy key length
615        $devTypeLength = ord($decoded[6+$devIdLength+$polKeyLength]); //device type length
616        //unpack the decoded query string values
617        $unpackedQuery = unpack("CProtVer/CCommand/vLocale/CDevIDLen/H".($devIdLength*2)."DevID/CPolKeyLen".($polKeyLength == 4 ? "/VPolKey" : "")."/CDevTypeLen/A".($devTypeLength)."DevType", $decoded);
618
619        //get the command parameters
620        $pos = 7 + $devIdLength + $polKeyLength + $devTypeLength;
621        $decoded = substr($decoded, $pos);
622        while (strlen($decoded) > 0) {
623            $paramLength = ord($decoded[1]);
624            $unpackedParam = unpack("CParamTag/CParamLength/A".$paramLength."ParamValue", $decoded);
625            $unpackedQuery[ord($decoded[0])] = $unpackedParam['ParamValue'];
626            //remove parameter from decoded query string
627            $decoded = substr($decoded, 2 + $paramLength);
628        }
629        return $unpackedQuery;
630    }
631
632    /**
633     * Returns a command string for a given command code.
634     *
635     * @param int $code
636     *
637     * @access public
638     * @return string or false if code is unknown
639     */
640    public static function GetCommandFromCode($code) {
641        switch ($code) {
642            case ZPush::COMMAND_SYNC:                 return 'Sync';
643            case ZPush::COMMAND_SENDMAIL:             return 'SendMail';
644            case ZPush::COMMAND_SMARTFORWARD:         return 'SmartForward';
645            case ZPush::COMMAND_SMARTREPLY:           return 'SmartReply';
646            case ZPush::COMMAND_GETATTACHMENT:        return 'GetAttachment';
647            case ZPush::COMMAND_FOLDERSYNC:           return 'FolderSync';
648            case ZPush::COMMAND_FOLDERCREATE:         return 'FolderCreate';
649            case ZPush::COMMAND_FOLDERDELETE:         return 'FolderDelete';
650            case ZPush::COMMAND_FOLDERUPDATE:         return 'FolderUpdate';
651            case ZPush::COMMAND_MOVEITEMS:            return 'MoveItems';
652            case ZPush::COMMAND_GETITEMESTIMATE:      return 'GetItemEstimate';
653            case ZPush::COMMAND_MEETINGRESPONSE:      return 'MeetingResponse';
654            case ZPush::COMMAND_SEARCH:               return 'Search';
655            case ZPush::COMMAND_SETTINGS:             return 'Settings';
656            case ZPush::COMMAND_PING:                 return 'Ping';
657            case ZPush::COMMAND_ITEMOPERATIONS:       return 'ItemOperations';
658            case ZPush::COMMAND_PROVISION:            return 'Provision';
659            case ZPush::COMMAND_RESOLVERECIPIENTS:    return 'ResolveRecipients';
660            case ZPush::COMMAND_VALIDATECERT:         return 'ValidateCert';
661
662            // Deprecated commands
663            case ZPush::COMMAND_GETHIERARCHY:         return 'GetHierarchy';
664            case ZPush::COMMAND_CREATECOLLECTION:     return 'CreateCollection';
665            case ZPush::COMMAND_DELETECOLLECTION:     return 'DeleteCollection';
666            case ZPush::COMMAND_MOVECOLLECTION:       return 'MoveCollection';
667            case ZPush::COMMAND_NOTIFY:               return 'Notify';
668
669            // Webservice commands
670            case ZPush::COMMAND_WEBSERVICE_DEVICE:    return 'WebserviceDevice';
671        }
672        return false;
673    }
674
675    /**
676     * Returns a command code for a given command.
677     *
678     * @param string $command
679     *
680     * @access public
681     * @return int or false if command is unknown
682     */
683    public static function GetCodeFromCommand($command) {
684        switch ($command) {
685            case 'Sync':                 return ZPush::COMMAND_SYNC;
686            case 'SendMail':             return ZPush::COMMAND_SENDMAIL;
687            case 'SmartForward':         return ZPush::COMMAND_SMARTFORWARD;
688            case 'SmartReply':           return ZPush::COMMAND_SMARTREPLY;
689            case 'GetAttachment':        return ZPush::COMMAND_GETATTACHMENT;
690            case 'FolderSync':           return ZPush::COMMAND_FOLDERSYNC;
691            case 'FolderCreate':         return ZPush::COMMAND_FOLDERCREATE;
692            case 'FolderDelete':         return ZPush::COMMAND_FOLDERDELETE;
693            case 'FolderUpdate':         return ZPush::COMMAND_FOLDERUPDATE;
694            case 'MoveItems':            return ZPush::COMMAND_MOVEITEMS;
695            case 'GetItemEstimate':      return ZPush::COMMAND_GETITEMESTIMATE;
696            case 'MeetingResponse':      return ZPush::COMMAND_MEETINGRESPONSE;
697            case 'Search':               return ZPush::COMMAND_SEARCH;
698            case 'Settings':             return ZPush::COMMAND_SETTINGS;
699            case 'Ping':                 return ZPush::COMMAND_PING;
700            case 'ItemOperations':       return ZPush::COMMAND_ITEMOPERATIONS;
701            case 'Provision':            return ZPush::COMMAND_PROVISION;
702            case 'ResolveRecipients':    return ZPush::COMMAND_RESOLVERECIPIENTS;
703            case 'ValidateCert':         return ZPush::COMMAND_VALIDATECERT;
704
705            // Deprecated commands
706            case 'GetHierarchy':         return ZPush::COMMAND_GETHIERARCHY;
707            case 'CreateCollection':     return ZPush::COMMAND_CREATECOLLECTION;
708            case 'DeleteCollection':     return ZPush::COMMAND_DELETECOLLECTION;
709            case 'MoveCollection':       return ZPush::COMMAND_MOVECOLLECTION;
710            case 'Notify':               return ZPush::COMMAND_NOTIFY;
711
712            // Webservice commands
713            case 'WebserviceDevice':     return ZPush::COMMAND_WEBSERVICE_DEVICE;
714        }
715        return false;
716    }
717
718    /**
719     * Normalize the given timestamp to the start of the day
720     *
721     * @param long      $timestamp
722     *
723     * @access private
724     * @return long
725     */
726    public static function getDayStartOfTimestamp($timestamp) {
727        return $timestamp - ($timestamp % (60 * 60 * 24));
728    }
729
730    /**
731     * Returns a formatted string output from an optional timestamp.
732     * If no timestamp is sent, NOW is used.
733     *
734     * @param long  $timestamp
735     *
736     * @access public
737     * @return string
738     */
739    public static function GetFormattedTime($timestamp = false) {
740        if (!$timestamp)
741            return @strftime("%d/%m/%Y %H:%M:%S");
742        else
743            return @strftime("%d/%m/%Y %H:%M:%S", $timestamp);
744    }
745
746
747   /**
748    * Get charset name from a codepage
749    *
750    * @see http://msdn.microsoft.com/en-us/library/dd317756(VS.85).aspx
751    *
752    * Table taken from common/codepage.cpp
753    *
754    * @param integer codepage Codepage
755    *
756    * @access public
757    * @return string iconv-compatible charset name
758    */
759    public static function GetCodepageCharset($codepage) {
760        $codepages = array(
761            20106 => "DIN_66003",
762            20108 => "NS_4551-1",
763            20107 => "SEN_850200_B",
764            950 => "big5",
765            50221 => "csISO2022JP",
766            51932 => "euc-jp",
767            51936 => "euc-cn",
768            51949 => "euc-kr",
769            949 => "euc-kr",
770            936 => "gb18030",
771            52936 => "csgb2312",
772            852 => "ibm852",
773            866 => "ibm866",
774            50220 => "iso-2022-jp",
775            50222 => "iso-2022-jp",
776            50225 => "iso-2022-kr",
777            1252 => "windows-1252",
778            28591 => "iso-8859-1",
779            28592 => "iso-8859-2",
780            28593 => "iso-8859-3",
781            28594 => "iso-8859-4",
782            28595 => "iso-8859-5",
783            28596 => "iso-8859-6",
784            28597 => "iso-8859-7",
785            28598 => "iso-8859-8",
786            28599 => "iso-8859-9",
787            28603 => "iso-8859-13",
788            28605 => "iso-8859-15",
789            20866 => "koi8-r",
790            21866 => "koi8-u",
791            932 => "shift-jis",
792            1200 => "unicode",
793            1201 => "unicodebig",
794            65000 => "utf-7",
795            65001 => "utf-8",
796            1250 => "windows-1250",
797            1251 => "windows-1251",
798            1253 => "windows-1253",
799            1254 => "windows-1254",
800            1255 => "windows-1255",
801            1256 => "windows-1256",
802            1257 => "windows-1257",
803            1258 => "windows-1258",
804            874 => "windows-874",
805            20127 => "us-ascii"
806        );
807
808        if(isset($codepages[$codepage])) {
809            return $codepages[$codepage];
810        } else {
811            // Defaulting to iso-8859-15 since it is more likely for someone to make a mistake in the codepage
812            // when using west-european charsets then when using other charsets since utf-8 is binary compatible
813            // with the bottom 7 bits of west-european
814            return "iso-8859-15";
815        }
816    }
817
818    /**
819     * Converts a string encoded with codepage into an UTF-8 string
820     *
821     * @param int $codepage
822     * @param string $string
823     *
824     * @access public
825     * @return string
826     */
827    public static function ConvertCodepageStringToUtf8($codepage, $string) {
828        if (function_exists("iconv")) {
829            $charset = self::GetCodepageCharset($codepage);
830
831            return iconv($charset, "utf-8", $string);
832        }
833        return $string;
834    }
835
836    /**
837     * Returns the best match of preferred body preference types.
838     *
839     * @param array             $bpTypes
840     *
841     * @access public
842     * @return int
843     */
844    public static function GetBodyPreferenceBestMatch($bpTypes) {
845        // The best choice is RTF, then HTML and then MIME in order to save bandwidth
846        // because MIME is a complete message including the headers and attachments
847        if (in_array(SYNC_BODYPREFERENCE_RTF, $bpTypes))  return SYNC_BODYPREFERENCE_RTF;
848        if (in_array(SYNC_BODYPREFERENCE_HTML, $bpTypes)) return SYNC_BODYPREFERENCE_HTML;
849        if (in_array(SYNC_BODYPREFERENCE_MIME, $bpTypes)) return SYNC_BODYPREFERENCE_MIME;
850        return SYNC_BODYPREFERENCE_PLAIN;
851    }
852
853    /* BEGIN fmbiete's contribution r1516, ZP-318 */
854    /**
855     * Converts a html string into a plain text string
856     *
857     * @param string $html
858     *
859     * @access public
860     * @return string
861     */
862    public static function ConvertHtmlToText($html) {
863        // remove css-style tags
864        $plaintext = preg_replace("/<style.*?<\/style>/is", "", $html);
865        // remove all other html
866        $plaintext = strip_tags($plaintext);
867
868        return $plaintext;
869    }
870    /* END fmbiete's contribution r1516, ZP-318 */
871}
872
873
874
875// TODO Win1252/UTF8 functions are deprecated and will be removed sometime
876//if the ICS backend is loaded in CombinedBackend and Zarafa > 7
877//STORE_SUPPORTS_UNICODE is true and the convertion will not be done
878//for other backends.
879function utf8_to_windows1252($string, $option = "", $force_convert = false) {
880    //if the store supports unicode return the string without converting it
881    if (!$force_convert && defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) return $string;
882
883    if (function_exists("iconv")){
884        return @iconv("UTF-8", "Windows-1252" . $option, $string);
885    }else{
886        return utf8_decode($string); // no euro support here
887    }
888}
889
890function windows1252_to_utf8($string, $option = "", $force_convert = false) {
891    //if the store supports unicode return the string without converting it
892    if (!$force_convert && defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) return $string;
893
894    if (function_exists("iconv")){
895        return @iconv("Windows-1252", "UTF-8" . $option, $string);
896    }else{
897        return utf8_encode($string); // no euro support here
898    }
899}
900
901function w2u($string) { return windows1252_to_utf8($string); }
902function u2w($string) { return utf8_to_windows1252($string); }
903
904function w2ui($string) { return windows1252_to_utf8($string, "//TRANSLIT"); }
905function u2wi($string) { return utf8_to_windows1252($string, "//TRANSLIT"); }
906
907
908?>
Note: See TracBrowser for help on using the repository browser.