/usr/share/kopano/php/mapi/mapi.util.php is in php-mapi 8.5.5-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | <?php
/*
* Copyright 2005 - 2016 Zarafa and its licensors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Function to make a MAPIGUID from a php string.
* The C++ definition for the GUID is:
* struct GUID {
* unsigned long Data1;
* unsigned short Data2;
* unsigned short Data3;
* unsigned char Data4[8];
* };
*
* A GUID is normally represented in the following form:
* {00062008-0000-0000-C000-000000000046}
*
* @param String GUID
*/
function makeGuid($guid)
{
return pack("vvvv", hexdec(substr($guid, 5, 4)), hexdec(substr($guid, 1, 4)), hexdec(substr($guid, 10, 4)), hexdec(substr($guid, 15, 4))) . hex2bin(substr($guid, 20, 4)) . hex2bin(substr($guid, 25, 12));
}
/**
* Function to get a human readable string from a MAPI error code
*
*@param int $errcode the MAPI error code, if not given, we use mapi_last_hresult
*@return string The defined name for the MAPI error code
*/
function get_mapi_error_name($errcode=null)
{
if ($errcode === null){
$errcode = mapi_last_hresult();
}
if ($errcode === 0)
return "NOERROR";
// get_defined_constants(true) is preferred, but crashes PHP
// https://bugs.php.net/bug.php?id=61156
$allConstants = get_defined_constants();
foreach ($allConstants as $key => $value) {
/**
* If PHP encounters a number beyond the bounds of the integer type,
* it will be interpreted as a float instead, so when comparing these error codes
* we have to manually typecast value to integer, so float will be converted in integer,
* but still its out of bound for integer limit so it will be auto adjusted to minus value
*/
if ($errcode != (int) $value)
continue;
// Check that we have an actual MAPI error or warning definition
$prefix = substr($key, 0, 7);
if ($prefix == "MAPI_E_" || $prefix == "MAPI_W_")
return $key;
}
// error code not found, return hex value (this is a fix for 64-bit systems, we can't use the dechex() function for this)
$result = unpack("H*", pack("N", $errcode));
return "0x" . $result[1];
}
/**
* Parses properties from an array of strings. Each "string" may be either an ULONG, which is a direct property ID,
* or a string with format "PT_TYPE:{GUID}:StringId" or "PT_TYPE:{GUID}:0xXXXX" for named
* properties.
*
* @returns array of properties
*/
function getPropIdsFromStrings($store, $mapping)
{
$props = array();
$ids = array("name"=>array(), "id"=>array(), "guid"=>array(), "type"=>array()); // this array stores all the information needed to retrieve a named property
$num = 0;
// caching
$guids = array();
foreach($mapping as $name=>$val){
if (!is_string($val)) {
// not a named property
$props[$name] = $val;
continue;
}
$split = explode(":", $val);
if (count($split) != 3) { // invalid string, ignore
trigger_error(sprintf("Invalid property: %s \"%s\"", $name, $val), E_USER_NOTICE);
continue;
}
if (substr($split[2], 0, 2) == "0x")
$id = hexdec(substr($split[2], 2));
else
$id = $split[2];
// have we used this guid before?
if (!defined($split[1])) {
if (!array_key_exists($split[1], $guids))
$guids[$split[1]] = makeguid($split[1]);
$guid = $guids[$split[1]];
} else {
$guid = constant($split[1]);
}
// temp store info about named prop, so we have to call mapi_getidsfromnames just one time
$ids["name"][$num] = $name;
$ids["id"][$num] = $id;
$ids["guid"][$num] = $guid;
$ids["type"][$num] = $split[0];
$num++;
}
if (empty($ids["id"]))
return $props;
// get the ids
$named = mapi_getidsfromnames($store, $ids["id"], $ids["guid"]);
foreach($named as $num=>$prop)
$props[$ids["name"][$num]] = mapi_prop_tag(constant($ids["type"][$num]), mapi_prop_id($prop));
return $props;
}
/**
* Check whether a call to mapi_getprops returned errors for some properties.
* mapi_getprops function tries to get values of properties requested but somehow if
* if a property value can not be fetched then it changes type of property tag as PT_ERROR
* and returns error for that particular property, probable errors
* that can be returned as value can be MAPI_E_NOT_FOUND, MAPI_E_NOT_ENOUGH_MEMORY
*
* @param long $property Property to check for error
* @param Array $propArray An array of properties
* @return mixed Gives back false when there is no error, if there is, gives the error
*/
function propIsError($property, $propArray)
{
if (array_key_exists(mapi_prop_tag(PT_ERROR, mapi_prop_id($property)), $propArray))
return $propArray[mapi_prop_tag(PT_ERROR, mapi_prop_id($property))];
return false;
}
/******** Macro Functions for PR_DISPLAY_TYPE_EX values *********/
/**
* check addressbook object is a remote mailuser
*/
function DTE_IS_REMOTE_VALID($value) {
return !!($value & DTE_FLAG_REMOTE_VALID);
}
/**
* check addressbook object is able to receive permissions
*/
function DTE_IS_ACL_CAPABLE($value) {
return !!($value & DTE_FLAG_ACL_CAPABLE);
}
function DTE_REMOTE($value) {
return (($value & DTE_MASK_REMOTE) >> 8);
}
function DTE_LOCAL($value) {
return ($value & DTE_MASK_LOCAL);
}
/**
* Note: Static function, more like a utility function.
*
* Gets all the items (including recurring items) in the specified calendar in the given timeframe. Items are
* included as a whole if they overlap the interval <$start, $end> (non-inclusive). This means that if the interval
* is <08:00 - 14:00>, the item [6:00 - 8:00> is NOT included, nor is the item [14:00 - 16:00>. However, the item
* [7:00 - 9:00> is included as a whole, and is NOT capped to [8:00 - 9:00>.
*
* @param $store resource The store in which the calendar resides
* @param $calendar resource The calendar to get the items from
* @param $viewstart int Timestamp of beginning of view window
* @param $viewend int Timestamp of end of view window
* @param $propsrequested array Array of properties to return
* @param $rows array Array of rowdata as if they were returned directly from mapi_table_queryrows. Each recurring item is
* expanded so that it seems that there are only many single appointments in the table.
*/
function getCalendarItems($store, $calendar, $viewstart, $viewend, $propsrequested){
$result = array();
$properties = getPropIdsFromStrings($store, Array( "duedate" => "PT_SYSTIME:PSETID_Appointment:0x820e",
"startdate" => "PT_SYSTIME:PSETID_Appointment:0x820d",
"enddate_recurring" => "PT_SYSTIME:PSETID_Appointment:0x8236",
"recurring" => "PT_BOOLEAN:PSETID_Appointment:0x8223",
"recurring_data" => "PT_BINARY:PSETID_Appointment:0x8216",
"timezone_data" => "PT_BINARY:PSETID_Appointment:0x8233",
"label" => "PT_LONG:PSETID_Appointment:0x8214"
));
// Create a restriction that will discard rows of appointments that are definitely not in our
// requested time frame
$table = mapi_folder_getcontentstable($calendar);
$restriction =
// OR
Array(RES_OR,
Array(
Array(RES_AND, // Normal items: itemEnd must be after viewStart, itemStart must be before viewEnd
Array(
Array(RES_PROPERTY,
Array(RELOP => RELOP_GT,
ULPROPTAG => $properties["duedate"],
VALUE => $viewstart
)
),
Array(RES_PROPERTY,
Array(RELOP => RELOP_LT,
ULPROPTAG => $properties["startdate"],
VALUE => $viewend
)
)
)
),
// OR
Array(RES_PROPERTY,
Array(RELOP => RELOP_EQ,
ULPROPTAG => $properties["recurring"],
VALUE => true
)
)
) // EXISTS OR
); // global OR
// Get requested properties, plus whatever we need
$proplist = array(PR_ENTRYID, $properties["recurring"], $properties["recurring_data"], $properties["timezone_data"]);
$proplist = array_merge($proplist, $propsrequested);
$propslist = array_unique($proplist);
$rows = mapi_table_queryallrows($table, $proplist, $restriction);
// $rows now contains all the items that MAY be in the window; a recurring item needs expansion before including in the output.
foreach($rows as $row) {
$items = array();
if(isset($row[$properties["recurring"]]) && $row[$properties["recurring"]]) {
// Recurring item
$rec = new Recurrence($store, $row);
// GetItems guarantees that the item overlaps the interval <$viewstart, $viewend>
$occurrences = $rec->getItems($viewstart, $viewend);
foreach($occurrences as $occurrence) {
// The occurrence takes all properties from the main row, but overrides some properties (like start and end obviously)
$item = $occurrence + $row;
array_push($items, $item);
}
} else {
// Normal item, it matched the search criteria and therefore overlaps the interval <$viewstart, $viewend>
array_push($items, $row);
}
$result = array_merge($result,$items);
}
// All items are guaranteed to overlap the interval <$viewstart, $viewend>. Note that we may be returning a few extra
// properties that the caller did not request (recurring, etc). This shouldn't be a problem though.
return $result;
}
/**
* Get the main calendar
*/
function getCalendar($store)
{
$inbox = mapi_msgstore_getreceivefolder($store);
$inboxprops = mapi_getprops($inbox, array(PR_IPM_APPOINTMENT_ENTRYID));
if(!isset($inboxprops[PR_IPM_APPOINTMENT_ENTRYID]))
return false;
$calendar = mapi_msgstore_openentry($store, $inboxprops[PR_IPM_APPOINTMENT_ENTRYID]);
return $calendar;
}
/**
* Get the default store for this session
*/
function getDefaultStore($session)
{
$msgstorestable = mapi_getmsgstorestable($session);
$msgstores = mapi_table_queryallrows($msgstorestable, array(PR_DEFAULT_STORE, PR_ENTRYID));
foreach ($msgstores as $row) {
if($row[PR_DEFAULT_STORE]) {
$storeentryid = $row[PR_ENTRYID];
break;
}
}
if(!$storeentryid) {
print "Can't find default store\n";
return false;
}
$store = mapi_openmsgstore($session, $storeentryid);
return $store;
}
function forceUTF8($category)
{
$old_locale = setlocale($category, "");
if(!isset($old_locale) || !$old_locale) {
print "Unable to initialize locale\n";
exit(1);
}
$dot = strpos($old_locale, ".");
if($dot) {
if(strrchr($old_locale, ".") == ".UTF-8" || strrchr($old_locale, ".") == ".utf8")
return true;
$old_locale = substr($old_locale, 0, $dot);
}
$new_locale = $old_locale . ".UTF-8";
$old_locale = setlocale($category, $new_locale);
if(!$old_locale) {
$new_locale = "en_US.UTF-8";
$old_locale = setlocale($category, $new_locale);
}
if(!$old_locale) {
print "Unable to set locale $new_locale\n";
exit(1);
}
return true;
}
|