Back to index

d-push  2.0
mapi.util.php
Go to the documentation of this file.
00001 <?php
00002 /*
00003  * Copyright 2005 - 2012  Zarafa B.V.
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU Affero General Public License, version 3,
00007  * as published by the Free Software Foundation with the following additional
00008  * term according to sec. 7:
00009  *
00010  * According to sec. 7 of the GNU Affero General Public License, version
00011  * 3, the terms of the AGPL are supplemented with the following terms:
00012  *
00013  * "Zarafa" is a registered trademark of Zarafa B.V. The licensing of
00014  * the Program under the AGPL does not imply a trademark license.
00015  * Therefore any rights, title and interest in our trademarks remain
00016  * entirely with us.
00017  *
00018  * However, if you propagate an unmodified version of the Program you are
00019  * allowed to use the term "Zarafa" to indicate that you distribute the
00020  * Program. Furthermore you may use our trademarks where it is necessary
00021  * to indicate the intended purpose of a product or service provided you
00022  * use it in accordance with honest practices in industrial or commercial
00023  * matters.  If you want to propagate modified versions of the Program
00024  * under the name "Zarafa" or "Zarafa Server", you may only do so if you
00025  * have a written permission by Zarafa B.V. (to acquire a permission
00026  * please contact Zarafa at trademark@zarafa.com).
00027  *
00028  * The interactive user interface of the software displays an attribution
00029  * notice containing the term "Zarafa" and/or the logo of Zarafa.
00030  * Interactive user interfaces of unmodified and modified versions must
00031  * display Appropriate Legal Notices according to sec. 5 of the GNU
00032  * Affero General Public License, version 3, when you propagate
00033  * unmodified or modified versions of the Program. In accordance with
00034  * sec. 7 b) of the GNU Affero General Public License, version 3, these
00035  * Appropriate Legal Notices must retain the logo of Zarafa or display
00036  * the words "Initial Development by Zarafa" if the display of the logo
00037  * is not reasonably feasible for technical reasons. The use of the logo
00038  * of Zarafa in Legal Notices is allowed for unmodified and modified
00039  * versions of the software.
00040  *
00041  * This program is distributed in the hope that it will be useful,
00042  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00043  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00044  * GNU Affero General Public License for more details.
00045  *
00046  * You should have received a copy of the GNU Affero General Public License
00047  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00048  *
00049  */
00050 
00051 
00068 function makeGuid($guid)
00069 {
00070     // remove the { and } from the string and explode it into an array
00071     $guidArray = explode('-', substr($guid, 1,strlen($guid)-2));
00072 
00073     // convert to hex!
00074     $data1[0] = intval(substr($guidArray[0], 0, 4),16); // we need to split the unsigned long
00075     $data1[1] = intval(substr($guidArray[0], 4, 4),16);
00076     $data2 = intval($guidArray[1], 16);
00077     $data3 = intval($guidArray[2], 16);
00078 
00079     $data4[0] = intval(substr($guidArray[3], 0, 2),16);
00080     $data4[1] = intval(substr($guidArray[3], 2, 2),16);
00081 
00082     for($i=0; $i < 6; $i++)
00083     {
00084         $data4[] = intval(substr($guidArray[4], $i*2, 2),16);
00085     }
00086 
00087     return pack("vvvvCCCCCCCC", $data1[1], $data1[0], $data2, $data3, $data4[0],$data4[1],$data4[2],$data4[3],$data4[4],$data4[5],$data4[6],$data4[7]);
00088 }
00089 
00096 function get_mapi_error_name($errcode=null)
00097 {
00098     if ($errcode === null){
00099         $errcode = mapi_last_hresult();
00100     }
00101 
00102     if ($errcode !== 0){
00103         $allConstants = get_defined_constants(true);
00104 
00105         foreach($allConstants['user'] as $key => $value){
00106             $prefix = substr($key, 0, 7);
00107             if ($prefix == "MAPI_E_" || $prefix == "MAPI_W_") {
00114                 if ($errcode == (int) $value){
00115                     return $key;
00116                 }
00117             }
00118         }
00119     } else {
00120         return "NOERROR";
00121     }
00122 
00123     // error code not found, return hex value (this is a fix for 64-bit systems, we can't use the dechex() function for this)
00124     $result = unpack("H*", pack("N", $errcode));
00125     return "0x" . $result[1];
00126 }
00127 
00135 function getPropIdsFromStrings($store, $mapping)
00136 {
00137     $props = array();
00138 
00139     $ids = array("name"=>array(), "id"=>array(), "guid"=>array(), "type"=>array()); // this array stores all the information needed to retrieve a named property
00140     $num = 0;
00141 
00142     // caching
00143     $guids = array();
00144 
00145     foreach($mapping as $name=>$val){
00146         if(is_string($val)) {
00147             $split = explode(":", $val);
00148 
00149             if(count($split) != 3){ // invalid string, ignore
00150                 trigger_error(sprintf("Invalid property: %s \"%s\"",$name,$val), E_USER_NOTICE);
00151                 continue;
00152             }
00153 
00154             if(substr($split[2], 0, 2) == "0x") {
00155                 $id = hexdec(substr($split[2], 2));
00156             } else {
00157                 $id = $split[2];
00158             }
00159 
00160             // have we used this guid before?
00161             if (!defined($split[1])){
00162                 if (!array_key_exists($split[1], $guids)){
00163                     $guids[$split[1]] = makeguid($split[1]);
00164                 }
00165                 $guid = $guids[$split[1]];
00166             }else{
00167                 $guid = constant($split[1]);
00168             }
00169 
00170             // temp store info about named prop, so we have to call mapi_getidsfromnames just one time
00171             $ids["name"][$num] = $name;
00172             $ids["id"][$num] = $id;
00173             $ids["guid"][$num] = $guid;
00174             $ids["type"][$num] = $split[0];
00175             $num++;
00176         }else{
00177             // not a named property
00178             $props[$name] = $val;
00179         }
00180     }
00181 
00182     if (empty($ids["id"])){
00183         return $props;
00184     }
00185 
00186     // get the ids
00187     $named = mapi_getidsfromnames($store, $ids["id"], $ids["guid"]);
00188     foreach($named as $num=>$prop){
00189         $props[$ids["name"][$num]] = mapi_prop_tag(constant($ids["type"][$num]), mapi_prop_id($prop));
00190     }
00191 
00192     return $props;
00193 }
00194 
00206 function propIsError($property, $propArray)
00207 {
00208     if (array_key_exists(mapi_prop_tag(PT_ERROR, mapi_prop_id($property)), $propArray)) {
00209         return $propArray[mapi_prop_tag(PT_ERROR, mapi_prop_id($property))];
00210     } else {
00211         return false;
00212     }
00213 }
00214 
00215 /******** Macro Functions for PR_DISPLAY_TYPE_EX values *********/
00219 function DTE_IS_REMOTE_VALID($value) {
00220     return !!($value & DTE_FLAG_REMOTE_VALID);
00221 }
00222 
00226 function DTE_IS_ACL_CAPABLE($value) {
00227     return !!($value & DTE_FLAG_ACL_CAPABLE);
00228 }
00229 
00230 function DTE_REMOTE($value) {
00231     return (($value & DTE_MASK_REMOTE) >> 8);
00232 }
00233 
00234 function DTE_LOCAL($value) {
00235     return ($value & DTE_MASK_LOCAL);
00236 }
00237 
00254 function getCalendarItems($store, $calendar, $viewstart, $viewend, $propsrequested){
00255     $result = array();
00256     $properties = getPropIdsFromStrings($store, Array( "duedate" => "PT_SYSTIME:PSETID_Appointment:0x820e",
00257                                                "startdate" =>  "PT_SYSTIME:PSETID_Appointment:0x820d",
00258                                                "enddate_recurring" => "PT_SYSTIME:PSETID_Appointment:0x8236",
00259                                                "recurring" => "PT_BOOLEAN:PSETID_Appointment:0x8223",
00260                                                "recurring_data" => "PT_BINARY:PSETID_Appointment:0x8216",
00261                                                "timezone_data" => "PT_BINARY:PSETID_Appointment:0x8233",
00262                                                "label" => "PT_LONG:PSETID_Appointment:0x8214"
00263                                                 ));
00264 
00265     // Create a restriction that will discard rows of appointments that are definitely not in our
00266     // requested time frame
00267 
00268     $table = mapi_folder_getcontentstable($calendar);
00269 
00270     $restriction =
00271         // OR
00272         Array(RES_OR,
00273                  Array(
00274                        Array(RES_AND,    // Normal items: itemEnd must be after viewStart, itemStart must be before viewEnd
00275                              Array(
00276                                    Array(RES_PROPERTY,
00277                                          Array(RELOP => RELOP_GT,
00278                                                ULPROPTAG => $properties["duedate"],
00279                                                VALUE => $viewstart
00280                                                )
00281                                          ),
00282                                    Array(RES_PROPERTY,
00283                                          Array(RELOP => RELOP_LT,
00284                                                ULPROPTAG => $properties["startdate"],
00285                                                VALUE => $viewend
00286                                                )
00287                                          )
00288                                    )
00289                              ),
00290                        // OR
00291                        Array(RES_PROPERTY,
00292                              Array(RELOP => RELOP_EQ,
00293                                    ULPROPTAG => $properties["recurring"],
00294                                    VALUE => true
00295                                    )
00296                              )
00297                        ) // EXISTS OR
00298                  );        // global OR
00299 
00300     // Get requested properties, plus whatever we need
00301     $proplist = array(PR_ENTRYID, $properties["recurring"], $properties["recurring_data"], $properties["timezone_data"]);
00302     $proplist = array_merge($proplist, $propsrequested);
00303     $propslist = array_unique($proplist);
00304 
00305     $rows = mapi_table_queryallrows($table, $proplist, $restriction);
00306 
00307     // $rows now contains all the items that MAY be in the window; a recurring item needs expansion before including in the output.
00308 
00309     foreach($rows as $row) {
00310         $items = array();
00311 
00312         if(isset($row[$properties["recurring"]]) && $row[$properties["recurring"]]) {
00313             // Recurring item
00314             $rec = new Recurrence($store, $row);
00315 
00316             // GetItems guarantees that the item overlaps the interval <$viewstart, $viewend>
00317             $occurrences = $rec->getItems($viewstart, $viewend);
00318             foreach($occurrences as $occurrence) {
00319                 // The occurrence takes all properties from the main row, but overrides some properties (like start and end obviously)
00320                 $item = $occurrence + $row;
00321                 array_push($items, $item);
00322             }
00323 
00324         } else {
00325             // Normal item, it matched the search criteria and therefore overlaps the interval <$viewstart, $viewend>
00326             array_push($items, $row);
00327         }
00328 
00329         $result = array_merge($result,$items);
00330     }
00331 
00332     // All items are guaranteed to overlap the interval <$viewstart, $viewend>. Note that we may be returning a few extra
00333     // properties that the caller did not request (recurring, etc). This shouldn't be a problem though.
00334     return $result;
00335 }
00336 ?>