Back to index

d-push  2.0
utils.php
Go to the documentation of this file.
00001 <?php
00002 /***********************************************
00003 * File      :   utils.php
00004 * Project   :   Z-Push
00005 * Descr     :   Several utility functions
00006 *
00007 * Created   :   03.04.2008
00008 *
00009 * Copyright 2007 - 2011 Zarafa Deutschland GmbH
00010 *
00011 * This program is free software: you can redistribute it and/or modify
00012 * it under the terms of the GNU Affero General Public License, version 3,
00013 * as published by the Free Software Foundation with the following additional
00014 * term according to sec. 7:
00015 *
00016 * According to sec. 7 of the GNU Affero General Public License, version 3,
00017 * the terms of the AGPL are supplemented with the following terms:
00018 *
00019 * "Zarafa" is a registered trademark of Zarafa B.V.
00020 * "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
00021 * The licensing of the Program under the AGPL does not imply a trademark license.
00022 * Therefore any rights, title and interest in our trademarks remain entirely with us.
00023 *
00024 * However, if you propagate an unmodified version of the Program you are
00025 * allowed to use the term "Z-Push" to indicate that you distribute the Program.
00026 * Furthermore you may use our trademarks where it is necessary to indicate
00027 * the intended purpose of a product or service provided you use it in accordance
00028 * with honest practices in industrial or commercial matters.
00029 * If you want to propagate modified versions of the Program under the name "Z-Push",
00030 * you may only do so if you have a written permission by Zarafa Deutschland GmbH
00031 * (to acquire a permission please contact Zarafa at trademark@zarafa.com).
00032 *
00033 * This program is distributed in the hope that it will be useful,
00034 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00035 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00036 * GNU Affero General Public License for more details.
00037 *
00038 * You should have received a copy of the GNU Affero General Public License
00039 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00040 *
00041 * Consult LICENSE file for details
00042 ************************************************/
00043 
00044 class Utils {
00053     static public function PrintAsString($var) {
00054       return ($var)?(($var===true)?'true':$var):(($var===false)?'false':(($var==='')?'empty':$var));
00055 //return ($var)?(($var===true)?'true':$var):'false';
00056     }
00057 
00067     static public function SplitDomainUser($domainuser) {
00068         $pos = strrpos($domainuser, '\\');
00069         if($pos === false){
00070             $user = $domainuser;
00071             $domain = '';
00072         }
00073         else{
00074             $domain = substr($domainuser,0,$pos);
00075             $user = substr($domainuser,$pos+1);
00076         }
00077         return array($user, $domain);
00078     }
00079 
00093     static public function IcalTimezoneFix($ical) {
00094         $eventDate = substr($ical, (strpos($ical, ":", strpos($ical, "DTSTART", strpos($ical, "BEGIN:VEVENT")))+1), 8);
00095         $posStd = strpos($ical, "DTSTART:", strpos($ical, "BEGIN:STANDARD")) + strlen("DTSTART:");
00096         $posDst = strpos($ical, "DTSTART:", strpos($ical, "BEGIN:DAYLIGHT")) + strlen("DTSTART:");
00097         $beginStandard = substr($ical, $posStd , 8);
00098         $beginDaylight = substr($ical, $posDst , 8);
00099 
00100         if (($eventDate < $beginStandard) && ($eventDate < $beginDaylight) ) {
00101             ZLog::Write(LOGLEVEL_DEBUG,"icalTimezoneFix for event on $eventDate, standard:$beginStandard, daylight:$beginDaylight");
00102             $year = intval(date("Y")) - 1;
00103             $ical = substr_replace($ical, $year, (($beginStandard < $beginDaylight) ? $posDst : $posStd), strlen($year));
00104         }
00105 
00106         return $ical;
00107     }
00108 
00121     static public function BuildAddressString($street, $zip, $city, $state, $country) {
00122         $out = "";
00123 
00124         if (isset($country) && $street != "") $out = $country;
00125 
00126         $zcs = "";
00127         if (isset($zip) && $zip != "") $zcs = $zip;
00128         if (isset($city) && $city != "") $zcs .= (($zcs)?" ":"") . $city;
00129         if (isset($state) && $state != "") $zcs .= (($zcs)?" ":"") . $state;
00130         if ($zcs) $out = $zcs . "\r\n" . $out;
00131 
00132         if (isset($street) && $street != "") $out = $street . (($out)?"\r\n\r\n". $out: "") ;
00133 
00134         return ($out)?$out:null;
00135     }
00136 
00145     static public function CheckMapiExtVersion($version = "") {
00146         // compare build number if requested
00147         if (preg_match('/^\d+$/', $version) && strlen($version) > 3) {
00148             $vs = preg_split('/-/', phpversion("mapi"));
00149             return ($version <= $vs[1]);
00150         }
00151 
00152         if (extension_loaded("mapi")){
00153             if (version_compare(phpversion("mapi"), $version) == -1){
00154                 return false;
00155             }
00156         }
00157         else
00158             return false;
00159 
00160         return true;
00161     }
00162 
00172     static public function GetICalUidFromOLUid($olUid){
00173         //check if "vCal-Uid" is somewhere in outlookid case-insensitive
00174         $icalUid = stristr($olUid, "vCal-Uid");
00175         if ($icalUid !== false) {
00176             //get the length of the ical id - go back 4 position from where "vCal-Uid" was found
00177             $begin = unpack("V", substr($olUid, strlen($icalUid) * (-1) - 4, 4));
00178             //remove "vCal-Uid" and packed "1" and use the ical id length
00179             return substr($icalUid, 12, ($begin[1] - 13));
00180         }
00181         return strtoupper(bin2hex($olUid));
00182     }
00183 
00194     static public function GetOLUidFromICalUid($icalUid) {
00195         if (strlen($icalUid) <= 64) {
00196             $len = 13 + strlen($icalUid);
00197             $OLUid = pack("V", $len);
00198             $OLUid .= "vCal-Uid";
00199             $OLUid .= pack("V", 1);
00200             $OLUid .= $icalUid;
00201             return hex2bin("040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000". bin2hex($OLUid). "00");
00202         }
00203         else
00204            return hex2bin($icalUid);
00205     }
00206 
00216     static public function ExtractBaseDate($goid, $recurStartTime) {
00217         $hexbase = substr(bin2hex($goid), 32, 8);
00218         $day = hexdec(substr($hexbase, 6, 2));
00219         $month = hexdec(substr($hexbase, 4, 2));
00220         $year = hexdec(substr($hexbase, 0, 4));
00221 
00222         if ($day && $month && $year) {
00223             $h = $recurStartTime >> 12;
00224             $m = ($recurStartTime - $h * 4096) >> 6;
00225             $s = $recurStartTime - $h * 4096 - $m * 64;
00226 
00227             return gmmktime($h, $m, $s, $month, $day, $year);
00228         }
00229         else
00230             return false;
00231     }
00232 
00241     static public function GetCutOffDate($restrict) {
00242         switch($restrict) {
00243             case SYNC_FILTERTYPE_1DAY:
00244                 $back = 60 * 60 * 24;
00245                 break;
00246             case SYNC_FILTERTYPE_3DAYS:
00247                 $back = 60 * 60 * 24 * 3;
00248                 break;
00249             case SYNC_FILTERTYPE_1WEEK:
00250                 $back = 60 * 60 * 24 * 7;
00251                 break;
00252             case SYNC_FILTERTYPE_2WEEKS:
00253                 $back = 60 * 60 * 24 * 14;
00254                 break;
00255             case SYNC_FILTERTYPE_1MONTH:
00256                 $back = 60 * 60 * 24 * 31;
00257                 break;
00258             case SYNC_FILTERTYPE_3MONTHS:
00259                 $back = 60 * 60 * 24 * 31 * 3;
00260                 break;
00261             case SYNC_FILTERTYPE_6MONTHS:
00262                 $back = 60 * 60 * 24 * 31 * 6;
00263                 break;
00264             default:
00265                 break;
00266         }
00267 
00268         if(isset($back)) {
00269             $date = time() - $back;
00270             return $date;
00271         } else
00272             return 0; // unlimited
00273     }
00274 
00282     static public function GetTruncSize($truncation) {
00283         switch($truncation) {
00284             case SYNC_TRUNCATION_HEADERS:
00285                 return 0;
00286             case SYNC_TRUNCATION_512B:
00287                 return 512;
00288             case SYNC_TRUNCATION_1K:
00289                 return 1024;
00290             case SYNC_TRUNCATION_2K:
00291                 return 2*1024;
00292             case SYNC_TRUNCATION_5K:
00293                 return 5*1024;
00294             case SYNC_TRUNCATION_10K:
00295                 return 10*1024;
00296             case SYNC_TRUNCATION_20K:
00297                 return 20*1024;
00298             case SYNC_TRUNCATION_50K:
00299                 return 50*1024;
00300             case SYNC_TRUNCATION_100K:
00301                 return 100*1024;
00302             case SYNC_TRUNCATION_ALL:
00303                 return 1024*1024; // We'll limit to 1MB anyway
00304             default:
00305                 return 1024; // Default to 1Kb
00306         }
00307     }
00308 
00318     static public function Utf8_truncate($string, $length) {
00319         if (strlen($string) <= $length)
00320             return $string;
00321 
00322         while($length >= 0) {
00323             if ((ord($string[$length]) < 0x80) || (ord($string[$length]) >= 0xC0))
00324                 return substr($string, 0, $length);
00325 
00326             $length--;
00327         }
00328         return "";
00329     }
00330 
00339     static public function IsSystemFolder($foldertype) {
00340         return ($foldertype == SYNC_FOLDER_TYPE_INBOX || $foldertype == SYNC_FOLDER_TYPE_DRAFTS || $foldertype == SYNC_FOLDER_TYPE_WASTEBASKET || $foldertype == SYNC_FOLDER_TYPE_SENTMAIL ||
00341                 $foldertype == SYNC_FOLDER_TYPE_OUTBOX || $foldertype == SYNC_FOLDER_TYPE_TASK || $foldertype == SYNC_FOLDER_TYPE_APPOINTMENT || $foldertype == SYNC_FOLDER_TYPE_CONTACT ||
00342                 $foldertype == SYNC_FOLDER_TYPE_NOTE || $foldertype == SYNC_FOLDER_TYPE_JOURNAL) ? true:false;
00343     }
00344 
00356     static public function Utf7_iconv_decode($string) {
00357         //do not alter string if there aren't any '&' or '+' chars because
00358         //it won't have any utf7-encoded chars and nothing has to be escaped.
00359         if (strpos($string, '&') === false && strpos($string, '+') === false ) return $string;
00360 
00361         //Get the string length and go back through it making the replacements
00362         //necessary
00363         $len = strlen($string) - 1;
00364         while ($len > 0) {
00365             //look for '&-' sequence and replace it with '&'
00366             if ($len > 0 && $string{($len-1)} == '&' && $string{$len} == '-') {
00367                 $string = substr_replace($string, '&', $len - 1, 2);
00368                 $len--; //decrease $len as this char has alreasy been processed
00369             }
00370             //search for '&' which weren't found in if clause above and
00371             //replace them with '+' as they mark an utf7-encoded char
00372             if ($len > 0 && $string{($len-1)} == '&') {
00373                 $string = substr_replace($string, '+', $len - 1, 1);
00374                 $len--; //decrease $len as this char has alreasy been processed
00375             }
00376             //finally "escape" all remaining '+' chars
00377             if ($len > 0 && $string{($len-1)} == '+') {
00378                 $string = substr_replace($string, '+-', $len - 1, 1);
00379             }
00380             $len--;
00381         }
00382         return $string;
00383     }
00384 
00394     static public function Utf7_iconv_encode($string) {
00395         //do not alter string if there aren't any '&' or '+' chars because
00396         //it won't have any utf7-encoded chars and nothing has to be escaped.
00397         if (strpos($string, '&') === false && strpos($string, '+') === false ) return $string;
00398 
00399         //Get the string length and go back through it making the replacements
00400         //necessary
00401         $len = strlen($string) - 1;
00402         while ($len > 0) {
00403             //look for '&-' sequence and replace it with '&'
00404             if ($len > 0 && $string{($len-1)} == '+' && $string{$len} == '-') {
00405                 $string = substr_replace($string, '+', $len - 1, 2);
00406                 $len--; //decrease $len as this char has alreasy been processed
00407             }
00408             //search for '&' which weren't found in if clause above and
00409             //replace them with '+' as they mark an utf7-encoded char
00410             if ($len > 0 && $string{($len-1)} == '+') {
00411                 $string = substr_replace($string, '&', $len - 1, 1);
00412                 $len--; //decrease $len as this char has alreasy been processed
00413             }
00414             //finally "escape" all remaining '+' chars
00415             if ($len > 0 && $string{($len-1)} == '&') {
00416                 $string = substr_replace($string, '&-', $len - 1, 1);
00417             }
00418             $len--;
00419         }
00420         return $string;
00421     }
00422 
00431     static public function Utf7_to_utf8($string) {
00432         if (function_exists("iconv")){
00433             return @iconv("UTF-7", "UTF-8", $string);
00434         }
00435         return $string;
00436     }
00437 
00446     static public function Utf8_to_utf7($string) {
00447         if (function_exists("iconv")){
00448             return @iconv("UTF-8", "UTF-7", $string);
00449         }
00450         return $string;
00451     }
00452 
00463     static public function CheckEmail($email) {
00464         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);
00465     }
00466 
00475     static public function IsBase64String($string) {
00476         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);
00477     }
00478 
00487     static public function DecodeBase64URI($query) {
00488         /*
00489          * The query string has a following structure. Number in () is position:
00490          * 1 byte       - protocoll version (0)
00491          * 1 byte       - command code (1)
00492          * 2 bytes      - locale (2)
00493          * 1 byte       - device ID length (4)
00494          * variable     - device ID (4+device ID length)
00495          * 1 byte       - policy key length (5+device ID length)
00496          * 0 or 4 bytes - policy key (5+device ID length + policy key length)
00497          * 1 byte       - device type length (6+device ID length + policy key length)
00498          * variable     - device type (6+device ID length + policy key length + device type length)
00499          * variable     - command parameters, array which consists of:
00500          *                      1 byte      - tag
00501          *                      1 byte      - length
00502          *                      variable    - value of the parameter
00503          *
00504          */
00505         $decoded = base64_decode($query);
00506         $devIdLength = ord($decoded[4]); //device ID length
00507         $polKeyLength = ord($decoded[5+$devIdLength]); //policy key length
00508         $devTypeLength = ord($decoded[6+$devIdLength+$polKeyLength]); //device type length
00509         //unpack the decoded query string values
00510         $unpackedQuery = unpack("CProtVer/CCommand/vLocale/CDevIDLen/H".($devIdLength*2)."DevID/CPolKeyLen".($polKeyLength == 4 ? "/VPolKey" : "")."/CDevTypeLen/A".($devTypeLength)."DevType", $decoded);
00511 
00512         //get the command parameters
00513         $pos = 7 + $devIdLength + $polKeyLength + $devTypeLength;
00514         $decoded = substr($decoded, $pos);
00515         while (strlen($decoded) > 0) {
00516             $paramLength = ord($decoded[1]);
00517             $unpackedParam = unpack("CParamTag/CParamLength/A".$paramLength."ParamValue", $decoded);
00518             $unpackedQuery[ord($decoded[0])] = $unpackedParam['ParamValue'];
00519             //remove parameter from decoded query string
00520             $decoded = substr($decoded, 2 + $paramLength);
00521         }
00522         return $unpackedQuery;
00523     }
00524 
00533     public static function GetCommandFromCode($code) {
00534         switch ($code) {
00535             case ZPush::COMMAND_SYNC:                 return 'Sync';
00536             case ZPush::COMMAND_SENDMAIL:             return 'SendMail';
00537             case ZPush::COMMAND_SMARTFORWARD:         return 'SmartForward';
00538             case ZPush::COMMAND_SMARTREPLY:           return 'SmartReply';
00539             case ZPush::COMMAND_GETATTACHMENT:        return 'GetAttachment';
00540             case ZPush::COMMAND_FOLDERSYNC:           return 'FolderSync';
00541             case ZPush::COMMAND_FOLDERCREATE:         return 'FolderCreate';
00542             case ZPush::COMMAND_FOLDERDELETE:         return 'FolderDelete';
00543             case ZPush::COMMAND_FOLDERUPDATE:         return 'FolderUpdate';
00544             case ZPush::COMMAND_MOVEITEMS:            return 'MoveItems';
00545             case ZPush::COMMAND_GETITEMESTIMATE:      return 'GetItemEstimate';
00546             case ZPush::COMMAND_MEETINGRESPONSE:      return 'MeetingResponse';
00547             case ZPush::COMMAND_SEARCH:               return 'Search';
00548             case ZPush::COMMAND_SETTINGS:             return 'Settings';
00549             case ZPush::COMMAND_PING:                 return 'Ping';
00550             case ZPush::COMMAND_ITEMOPERATIONS:       return 'ItemOperations';
00551             case ZPush::COMMAND_PROVISION:            return 'Provision';
00552             case ZPush::COMMAND_RESOLVERECIPIENTS:    return 'ResolveRecipients';
00553             case ZPush::COMMAND_VALIDATECERT:         return 'ValidateCert';
00554 
00555             // Deprecated commands
00556             case ZPush::COMMAND_GETHIERARCHY:         return 'GetHierarchy';
00557             case ZPush::COMMAND_CREATECOLLECTION:     return 'CreateCollection';
00558             case ZPush::COMMAND_DELETECOLLECTION:     return 'DeleteCollection';
00559             case ZPush::COMMAND_MOVECOLLECTION:       return 'MoveCollection';
00560             case ZPush::COMMAND_NOTIFY:               return 'Notify';
00561 
00562             // Webservice commands
00563             case ZPush::COMMAND_WEBSERVICE_DEVICE:    return 'WebserviceDevice';
00564         }
00565         return false;
00566     }
00567 
00576     public static function GetCodeFromCommand($command) {
00577         switch ($command) {
00578             case 'Sync':                 return ZPush::COMMAND_SYNC;
00579             case 'SendMail':             return ZPush::COMMAND_SENDMAIL;
00580             case 'SmartForward':         return ZPush::COMMAND_SMARTFORWARD;
00581             case 'SmartReply':           return ZPush::COMMAND_SMARTREPLY;
00582             case 'GetAttachment':        return ZPush::COMMAND_GETATTACHMENT;
00583             case 'FolderSync':           return ZPush::COMMAND_FOLDERSYNC;
00584             case 'FolderCreate':         return ZPush::COMMAND_FOLDERCREATE;
00585             case 'FolderDelete':         return ZPush::COMMAND_FOLDERDELETE;
00586             case 'FolderUpdate':         return ZPush::COMMAND_FOLDERUPDATE;
00587             case 'MoveItems':            return ZPush::COMMAND_MOVEITEMS;
00588             case 'GetItemEstimate':      return ZPush::COMMAND_GETITEMESTIMATE;
00589             case 'MeetingResponse':      return ZPush::COMMAND_MEETINGRESPONSE;
00590             case 'Search':               return ZPush::COMMAND_SEARCH;
00591             case 'Settings':             return ZPush::COMMAND_SETTINGS;
00592             case 'Ping':                 return ZPush::COMMAND_PING;
00593             case 'ItemOperations':       return ZPush::COMMAND_ITEMOPERATIONS;
00594             case 'Provision':            return ZPush::COMMAND_PROVISION;
00595             case 'ResolveRecipients':    return ZPush::COMMAND_RESOLVERECIPIENTS;
00596             case 'ValidateCert':         return ZPush::COMMAND_VALIDATECERT;
00597 
00598             // Deprecated commands
00599             case 'GetHierarchy':         return ZPush::COMMAND_GETHIERARCHY;
00600             case 'CreateCollection':     return ZPush::COMMAND_CREATECOLLECTION;
00601             case 'DeleteCollection':     return ZPush::COMMAND_DELETECOLLECTION;
00602             case 'MoveCollection':       return ZPush::COMMAND_MOVECOLLECTION;
00603             case 'Notify':               return ZPush::COMMAND_NOTIFY;
00604 
00605             // Webservice commands
00606             case 'WebserviceDevice':     return ZPush::COMMAND_WEBSERVICE_DEVICE;
00607         }
00608         return false;
00609     }
00610 
00619     public static function getDayStartOfTimestamp($timestamp) {
00620         return $timestamp - ($timestamp % (60 * 60 * 24));
00621     }
00622 
00632     public static function GetFormattedTime($timestamp = false) {
00633         if (!$timestamp)
00634             return @strftime("%d/%m/%Y %H:%M:%S");
00635         else
00636             return @strftime("%d/%m/%Y %H:%M:%S", $timestamp);
00637     }
00638 }
00639 
00640 
00641 
00642 // TODO Win1252/UTF8 functions are deprecated and will be removed sometime
00643 //if the ICS backend is loaded in CombinedBackend and Zarafa > 7
00644 //STORE_SUPPORTS_UNICODE is true and the convertion will not be done
00645 //for other backends.
00646 function utf8_to_windows1252($string, $option = "", $force_convert = false) {
00647     //if the store supports unicode return the string without converting it
00648     if (!$force_convert && defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) return $string;
00649 
00650     if (function_exists("iconv")){
00651         return @iconv("UTF-8", "Windows-1252" . $option, $string);
00652     }else{
00653         return utf8_decode($string); // no euro support here
00654     }
00655 }
00656 
00657 function windows1252_to_utf8($string, $option = "", $force_convert = false) {
00658     //if the store supports unicode return the string without converting it
00659     if (!$force_convert && defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) return $string;
00660 
00661     if (function_exists("iconv")){
00662         return @iconv("Windows-1252", "UTF-8" . $option, $string);
00663     }else{
00664         return utf8_encode($string); // no euro support here
00665     }
00666 }
00667 
00668 function w2u($string) { return windows1252_to_utf8($string); }
00669 function u2w($string) { return utf8_to_windows1252($string); }
00670 
00671 function w2ui($string) { return windows1252_to_utf8($string, "//TRANSLIT"); }
00672 function u2wi($string) { return utf8_to_windows1252($string, "//TRANSLIT"); }
00673 
00674 
00675 ?>