function foldersize($store, $entryid) { $size = 0; $folder = mapi_msgstore_openentry($store, $entryid); if (!$folder) { print "Unable to open folder."; return false; } $table = mapi_folder_getcontentstable($folder); if (!$table) { print "Unable to open table."; return false; } while (1) { $rows = mapi_table_queryrows($table, array(PR_MESSAGE_SIZE), 0, 100); if (count($rows) == 0) { break; } foreach ($rows as $row) { if (isset($row[PR_MESSAGE_SIZE])) { $size += $row[PR_MESSAGE_SIZE]; } } } return $size; }
/** * Publishes the infomation * @paam timestamp $starttime Time from which to publish data (usually now) * @paam integer $length Amount of seconds from $starttime we should publish */ function publishFB($starttime, $length) { $start = $starttime; $end = $starttime + $length; // Get all the items in the calendar that we need $calendaritems = array(); $restrict = array(RES_OR, array(array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_GE, ULPROPTAG => $this->proptags["startdate"], VALUE => $start)), array(RES_PROPERTY, array(RELOP => RELOP_LE, ULPROPTAG => $this->proptags["startdate"], VALUE => $end)))), array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_GE, ULPROPTAG => $this->proptags["duedate"], VALUE => $start)), array(RES_PROPERTY, array(RELOP => RELOP_LE, ULPROPTAG => $this->proptags["duedate"], VALUE => $end)))), array(RES_AND, array(array(RES_PROPERTY, array(RELOP => RELOP_LT, ULPROPTAG => $this->proptags["startdate"], VALUE => $start)), array(RES_PROPERTY, array(RELOP => RELOP_GT, ULPROPTAG => $this->proptags["duedate"], VALUE => $end)))), array(RES_OR, array(array(RES_AND, array(array(RES_EXIST, array(ULPROPTAG => $this->proptags["enddate_recurring"])), array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => $this->proptags["recurring"], VALUE => true)), array(RES_PROPERTY, array(RELOP => RELOP_GE, ULPROPTAG => $this->proptags["enddate_recurring"], VALUE => $start)))), array(RES_AND, array(array(RES_NOT, array(array(RES_EXIST, array(ULPROPTAG => $this->proptags["enddate_recurring"])))), array(RES_PROPERTY, array(RELOP => RELOP_LE, ULPROPTAG => $this->proptags["startdate"], VALUE => $end)), array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => $this->proptags["recurring"], VALUE => true)))))))); // global OR $contents = mapi_folder_getcontentstable($this->calendar); mapi_table_restrict($contents, $restrict); while (1) { $rows = mapi_table_queryrows($contents, array_values($this->proptags), 0, 50); if (!is_array($rows)) { break; } if (empty($rows)) { break; } foreach ($rows as $row) { $occurrences = array(); if (isset($row[$this->proptags['recurring']]) && $row[$this->proptags['recurring']]) { $recur = new Recurrence($this->store, $row); $occurrences = $recur->getItems($starttime, $starttime + $length); } else { $occurrences[] = $row; } $calendaritems = array_merge($calendaritems, $occurrences); } } // $calendaritems now contains all the calendar items in the specified time // frame. We now need to merge these into a flat array of begin/end/status // objects. This also filters out all the 'free' items (status 0) $freebusy = $this->mergeItemsFB($calendaritems); // $freebusy now contains the start, end and status of all items, merged. // Get the FB interface try { $fbsupport = mapi_freebusysupport_open($this->session, $this->store); } catch (MAPIException $e) { if ($e->getCode() == MAPI_E_NOT_FOUND) { $e->setHandled(); if (function_exists("dump")) { dump("Error in opening freebusysupport object."); } } } // Open updater for this user if (isset($fbsupport)) { $updaters = mapi_freebusysupport_loadupdate($fbsupport, array($this->entryid)); $updater = $updaters[0]; // Send the data mapi_freebusyupdate_reset($updater); mapi_freebusyupdate_publish($updater, $freebusy); mapi_freebusyupdate_savechanges($updater, $start - 24 * 60 * 60, $end); // We're finished mapi_freebusysupport_close($fbsupport); } }
/** * Reads an appointment object from MAPI * * @param mixed $mapimessage * @param ContentParameters $contentparameters * * @access private * @return SyncAppointment */ private function getAppointment($mapimessage, $contentparameters) { $message = new SyncAppointment(); // Standard one-to-one mappings first $this->getPropsFromMAPI($message, $mapimessage, MAPIMapping::GetAppointmentMapping()); // Appointment specific props $appointmentprops = MAPIMapping::GetAppointmentProperties(); $messageprops = $this->getProps($mapimessage, $appointmentprops); //set the body according to contentparameters and supported AS version $this->setMessageBody($mapimessage, $contentparameters, $message); // Set reminder time if reminderset is true if (isset($messageprops[$appointmentprops["reminderset"]]) && $messageprops[$appointmentprops["reminderset"]] == true) { if ($messageprops[$appointmentprops["remindertime"]] == 0x5ae980e1) { $message->reminder = 15; } else { $message->reminder = $messageprops[$appointmentprops["remindertime"]]; } } if (!isset($message->uid)) { $message->uid = bin2hex($messageprops[$appointmentprops["sourcekey"]]); } else { $message->uid = Utils::GetICalUidFromOLUid($message->uid); } // Always set organizer information because some devices do not work properly without it if (isset($messageprops[$appointmentprops["representingentryid"]]) && isset($messageprops[$appointmentprops["representingname"]])) { $message->organizeremail = w2u($this->getSMTPAddressFromEntryID($messageprops[$appointmentprops["representingentryid"]])); $message->organizername = w2u($messageprops[$appointmentprops["representingname"]]); } if (isset($messageprops[$appointmentprops["timezonetag"]])) { $tz = $this->getTZFromMAPIBlob($messageprops[$appointmentprops["timezonetag"]]); } else { // set server default timezone (correct timezone should be configured!) $tz = TimezoneUtil::GetFullTZ(); } $message->timezone = base64_encode($this->getSyncBlobFromTZ($tz)); if (isset($messageprops[$appointmentprops["isrecurring"]]) && $messageprops[$appointmentprops["isrecurring"]]) { // Process recurrence $message->recurrence = new SyncRecurrence(); $this->getRecurrence($mapimessage, $messageprops, $message, $message->recurrence, $tz); } // Do attendees $reciptable = mapi_message_getrecipienttable($mapimessage); // Only get first 256 recipients, to prevent possible load issues. $rows = mapi_table_queryrows($reciptable, array(PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS, PR_ADDRTYPE, PR_RECIPIENT_TRACKSTATUS, PR_RECIPIENT_TYPE), 0, 256); // Exception: we do not synchronize appointments with more than 250 attendees if (count($rows) > 250) { $message->id = bin2hex($messageprops[$appointmentprops["sourcekey"]]); $mbe = new SyncObjectBrokenException("Appointment has too many attendees"); $mbe->SetSyncObject($message); throw $mbe; } if (count($rows) > 0) { $message->attendees = array(); } foreach ($rows as $row) { $attendee = new SyncAttendee(); $attendee->name = w2u($row[PR_DISPLAY_NAME]); //smtp address is always a proper email address if (isset($row[PR_SMTP_ADDRESS])) { $attendee->email = w2u($row[PR_SMTP_ADDRESS]); } elseif (isset($row[PR_ADDRTYPE]) && isset($row[PR_EMAIL_ADDRESS])) { //if address type is SMTP, it's also a proper email address if ($row[PR_ADDRTYPE] == "SMTP") { $attendee->email = w2u($row[PR_EMAIL_ADDRESS]); } elseif ($row[PR_ADDRTYPE] == "ZARAFA") { $userinfo = mapi_zarafa_getuser_by_name($this->store, $row[PR_EMAIL_ADDRESS]); if (is_array($userinfo) && isset($userinfo["emailaddress"])) { $attendee->email = w2u($userinfo["emailaddress"]); } } } //set attendee's status and type if they're available if (isset($row[PR_RECIPIENT_TRACKSTATUS])) { $attendee->attendeestatus = $row[PR_RECIPIENT_TRACKSTATUS]; } if (isset($row[PR_RECIPIENT_TYPE])) { $attendee->attendeetype = $row[PR_RECIPIENT_TYPE]; } // Some attendees have no email or name (eg resources), and if you // don't send one of those fields, the phone will give an error ... so // we don't send it in that case. // also ignore the "attendee" if the email is equal to the organizers' email if (isset($attendee->name) && isset($attendee->email) && $attendee->email != "" && (!isset($message->organizeremail) || isset($message->organizeremail) && $attendee->email != $message->organizeremail)) { array_push($message->attendees, $attendee); } } // Status 0 = no meeting, status 1 = organizer, status 2/3/4/5 = tentative/accepted/declined/notresponded if (isset($messageprops[$appointmentprops["meetingstatus"]]) && $messageprops[$appointmentprops["meetingstatus"]] > 1) { // Work around iOS6 cancellation issue when there are no attendees for this meeting. Just add ourselves as the sole attendee. if (count($message->attendees) == 0) { if (!isset($message->attendees) || !is_array($message->attendees)) { $message->attendees = array(); } ZLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIProvider->getAppointment: adding ourself as an attendee for iOS6 workaround")); $attendee = new SyncAttendee(); $meinfo = mapi_zarafa_getuser_by_name($this->store, Request::GetAuthUser()); if (is_array($meinfo)) { $attendee->email = w2u($meinfo["emailaddress"]); $attendee->name = w2u($meinfo["fullname"]); $attendee->attendeetype = MAPI_TO; array_push($message->attendees, $attendee); } } } if (!isset($message->nativebodytype)) { $message->nativebodytype = $this->getNativeBodyType($messageprops); } return $message; }
/** * A wrapper for mapi_inetmapi_imtoinet function * * @param MAPIMessage $mapimessage * @param SyncObject $message * * @access private * @return boolean */ private function imtoinet($mapimessage, &$message) { // if it is a signed message get a full attachment generated by ZCP $props = mapi_getprops($mapimessage, array(PR_MESSAGE_CLASS)); if (isset($props[PR_MESSAGE_CLASS]) && $props[PR_MESSAGE_CLASS] && strpos(strtolower($props[PR_MESSAGE_CLASS]), 'multipartsigned')) { // find the required attachment $attachtable = mapi_message_getattachmenttable($mapimessage); mapi_table_restrict($attachtable, MAPIUtils::GetSignedAttachmentRestriction()); if (mapi_table_getrowcount($attachtable) == 1) { $rows = mapi_table_queryrows($attachtable, array(PR_ATTACH_NUM, PR_ATTACH_SIZE), 0, 1); if (isset($rows[0][PR_ATTACH_NUM])) { $mapiattach = mapi_message_openattach($mapimessage, $rows[0][PR_ATTACH_NUM]); $stream = mapi_openpropertytostream($mapiattach, PR_ATTACH_DATA_BIN); $streamsize = $rows[0][PR_ATTACH_SIZE]; } } } elseif (function_exists("mapi_inetmapi_imtoinet")) { $addrbook = $this->getAddressbook(); $stream = mapi_inetmapi_imtoinet($this->session, $addrbook, $mapimessage, array('use_tnef' => -1)); $mstreamstat = mapi_stream_stat($stream); $streamsize = $mstreamstat["cb"]; } if (isset($stream) && isset($streamsize)) { if (Request::GetProtocolVersion() >= 12.0) { if (!isset($message->asbody)) { $message->asbody = new SyncBaseBody(); } //TODO data should be wrapped in a MapiStreamWrapper $message->asbody->data = mapi_stream_read($stream, $streamsize); $message->asbody->estimatedDataSize = $streamsize; $message->asbody->truncated = 0; } else { $message->mimetruncated = 0; //TODO mimedata should be a wrapped in a MapiStreamWrapper $message->mimedata = mapi_stream_read($stream, $streamsize); $message->mimesize = $streamsize; } unset($message->body, $message->bodytruncated); return true; } else { ZLog::Write(LOGLEVEL_ERROR, sprintf("Error opening attachment for imtoinet")); } return false; }
function delete_duplicate_messages($store, $entryid) { global $total_deleted; $folder = mapi_msgstore_openentry($store, $entryid); if (!$folder) { print "Unable to open folder."; return false; } $table = mapi_folder_getcontentstable($folder); if (!$table) { print "Unable to open table."; return false; } $org_hash = null; $dup_messages = array(); $dup_count = 0; $result = mapi_table_sort($table, array(PR_SUBJECT => TABLE_SORT_ASCEND)); if ($result == false) { die("Could not sort table\n"); } while (1) { // query messages from folders content table $rows = mapi_table_queryrows($table, array(PR_MESSAGE_SIZE, PR_CLIENT_SUBMIT_TIME, PR_BODY, PR_HTML, PR_ENTRYID, PR_SUBJECT), 0, 50); if (count($rows) == 0) { break; } // we got the messages foreach ($rows as $row) { // hash message body (plaintext + html + subject) $md5_subject = md5($row[PR_SUBJECT]); $md5_body = md5($row[PR_BODY]); $md5_html = md5($row[PR_HTML]); // concat hashes, just in case there are messages with // no HTML or plaintext content. $cur_hash = $md5_body . $md5_html . $md5_subject; // when we have accumulated enough messages, perform a burst delete if ($dup_count == 50) { echo " [i] Deleting {$dup_count} duplicates..."; delete_messages($folder, $dup_messages); // reset the delete-queue $dup_messages = array(); $dup_count = 0; $total_deleted += 100; echo "done.\n"; echo "Deleted {$total_deleted} messages so far.\n\n"; } // duplicate messages are adjacent, so we push the first message with // a distinct hash and mark all following messages with this hash // for deletion. if ($org_hash != $cur_hash) { $org_hash = $cur_hash; } else { $dup_messages[] = $row[PR_ENTRYID]; $dup_count++; echo " [i] For {$org_hash} adding DUP {$md5_eid} to delete list\n"; } } } // final cleanup $dup_count = count($dup_messages); if ($dup_count) { $total_deleted += $dup_count; echo " [i] Finally deleting {$dup_count} duplicates. \n"; delete_messages($folder, $dup_messages); $dup_messages = array(); echo "Deleted {$total_deleted} messages so far.\n\n"; } }
/** * Get the private contact folder of all users */ function getPrivateContactFolders($session, $defaultstore) { $addrbook = mapi_openaddressbook($session); $addr_entryid = mapi_ab_getdefaultdir($addrbook); $abcontainer = mapi_ab_openentry($addrbook, $addr_entryid); $contentstable = mapi_folder_getcontentstable($abcontainer); // restrict table on only MAPI_MAILUSER accounts mapi_table_restrict($contentstable, array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => PR_OBJECT_TYPE, VALUE => array(PR_OBJECT_TYPE => MAPI_MAILUSER)))); // sort table on display name mapi_table_sort($contentstable, array(PR_DISPLAY_NAME => TABLE_SORT_ASCEND)); $users = mapi_table_queryrows($contentstable, array(PR_ACCOUNT, PR_ENTRYID, PR_DISPLAY_NAME), 0, mapi_table_getrowcount($contentstable)); $contactArray = array(); for ($i = 0; $i < sizeof($users); $i++) { $store_entryid = mapi_msgstore_createentryid($defaultstore, $users[$i][PR_ACCOUNT]); $store = mapi_openmsgstore($session, $store_entryid); $rootcontainer = mapi_msgstore_openentry($store); if ($rootcontainer) { $props = mapi_getprops($rootcontainer, array(PR_IPM_CONTACT_ENTRYID)); if (isset($props[PR_IPM_CONTACT_ENTRYID])) { $entryid = $props[PR_IPM_CONTACT_ENTRYID]; $folder = mapi_msgstore_openentry($store, $entryid); if ($folder) { $table = mapi_folder_getcontentstable($folder); $totalrow = mapi_table_getrowcount($table); $rows = array(); $contacts = array(); $properties = getContactProperties($defaultstore); if ($totalrow > 0) { $rows = mapi_table_queryrows($table, $properties, 0, $totalrow); for ($j = 0; $j < sizeof($rows); $j++) { $rows[$j][268370178] = md5($rows[$j][268370178]); } for ($k = 0; $k < sizeof($rows); $k++) { // do not add private contacts if (!array_key_exists(-2119827445, $rows[$k]) || array_key_exists(-2119827445, $rows[$k]) && $rows[$k][-2119827445] != 1) { foreach ($rows[$k] as $key => $value) { $attribute = mapKey($key); if ($attribute != "") { $contacts[$k][$attribute] = $value; } } } } $contactArray[] = array("username" => $users[$i][PR_ACCOUNT], "contacts" => $contacts); } } } } } // print_r($contactArray); return $contactArray; }
/** * Creates a search folder if it not exists or opens an existing one * and returns it. * * @param mapiFolderObject $searchFolderRoot * * @return mapiFolderObject */ private function createSearchFolder($searchFolderRoot) { $folderName = "Z-Push Search Folder " . @getmypid(); $searchFolders = mapi_folder_gethierarchytable($searchFolderRoot); $restriction = array(RES_CONTENT, array(FUZZYLEVEL => FL_PREFIX, ULPROPTAG => PR_DISPLAY_NAME, VALUE => array(PR_DISPLAY_NAME => $folderName))); //restrict the hierarchy to the z-push search folder only mapi_table_restrict($searchFolders, $restriction); if (mapi_table_getrowcount($searchFolders)) { $searchFolder = mapi_table_queryrows($searchFolders, array(PR_ENTRYID), 0, 1); return mapi_msgstore_openentry($this->store, $searchFolder[0][PR_ENTRYID]); } return mapi_folder_createfolder($searchFolderRoot, $folderName, null, 0, FOLDER_SEARCH); }
function getSearchResults($searchquery, $searchrange) { // only return users from who the displayName or the username starts with $name //TODO: use PR_ANR for this restriction instead of PR_DISPLAY_NAME and PR_ACCOUNT $addrbook = mapi_openaddressbook($this->_session); $ab_entryid = mapi_ab_getdefaultdir($addrbook); $ab_dir = mapi_ab_openentry($addrbook, $ab_entryid); $table = mapi_folder_getcontentstable($ab_dir); $restriction = $this->_getSearchRestriction(u2w($searchquery)); mapi_table_restrict($table, $restriction); mapi_table_sort($table, array(PR_DISPLAY_NAME => TABLE_SORT_ASCEND)); //range for the search results, default symbian range end is 50, wm 99, //so we'll use that of nokia $rangestart = 0; $rangeend = 50; if ($searchrange != '0') { $pos = strpos($searchrange, '-'); $rangestart = substr($searchrange, 0, $pos); $rangeend = substr($searchrange, $pos + 1); } $items = array(); $querycnt = mapi_table_getrowcount($table); //do not return more results as requested in range $querylimit = $rangeend + 1 < $querycnt ? $rangeend + 1 : $querycnt; $items['range'] = $rangestart . '-' . ($querylimit - 1); $items['searchtotal'] = $querycnt; if ($querycnt > 0) { $abentries = mapi_table_queryrows($table, array(PR_ACCOUNT, PR_DISPLAY_NAME, PR_SMTP_ADDRESS, PR_BUSINESS_TELEPHONE_NUMBER, PR_GIVEN_NAME, PR_SURNAME, PR_MOBILE_TELEPHONE_NUMBER, PR_HOME_TELEPHONE_NUMBER, PR_TITLE, PR_COMPANY_NAME, PR_OFFICE_LOCATION), $rangestart, $querylimit); } for ($i = 0; $i < $querylimit; $i++) { $items[$i][SYNC_GAL_DISPLAYNAME] = w2u($abentries[$i][PR_DISPLAY_NAME]); if (strlen(trim($items[$i][SYNC_GAL_DISPLAYNAME])) == 0) { $items[$i][SYNC_GAL_DISPLAYNAME] = w2u($abentries[$i][PR_ACCOUNT]); } $items[$i][SYNC_GAL_ALIAS] = w2u($abentries[$i][PR_ACCOUNT]); //it's not possible not get first and last name of an user //from the gab and user functions, so we just set lastname //to displayname and leave firstname unset //this was changed in Zarafa 6.40, so we try to get first and //last name and fall back to the old behaviour if these values are not set if (isset($abentries[$i][PR_GIVEN_NAME])) { $items[$i][SYNC_GAL_FIRSTNAME] = w2u($abentries[$i][PR_GIVEN_NAME]); } if (isset($abentries[$i][PR_SURNAME])) { $items[$i][SYNC_GAL_LASTNAME] = w2u($abentries[$i][PR_SURNAME]); } if (!isset($items[$i][SYNC_GAL_LASTNAME])) { $items[$i][SYNC_GAL_LASTNAME] = $items[$i][SYNC_GAL_DISPLAYNAME]; } $items[$i][SYNC_GAL_EMAILADDRESS] = w2u($abentries[$i][PR_SMTP_ADDRESS]); //check if an user has an office number or it might produce warnings in the log if (isset($abentries[$i][PR_BUSINESS_TELEPHONE_NUMBER])) { $items[$i][SYNC_GAL_PHONE] = w2u($abentries[$i][PR_BUSINESS_TELEPHONE_NUMBER]); } //check if an user has a mobile number or it might produce warnings in the log if (isset($abentries[$i][PR_MOBILE_TELEPHONE_NUMBER])) { $items[$i][SYNC_GAL_MOBILEPHONE] = w2u($abentries[$i][PR_MOBILE_TELEPHONE_NUMBER]); } //check if an user has a home number or it might produce warnings in the log if (isset($abentries[$i][PR_HOME_TELEPHONE_NUMBER])) { $items[$i][SYNC_GAL_HOMEPHONE] = w2u($abentries[$i][PR_HOME_TELEPHONE_NUMBER]); } if (isset($abentries[$i][PR_COMPANY_NAME])) { $items[$i][SYNC_GAL_COMPANY] = w2u($abentries[$i][PR_COMPANY_NAME]); } if (isset($abentries[$i][PR_TITLE])) { $items[$i][SYNC_GAL_TITLE] = w2u($abentries[$i][PR_TITLE]); } if (isset($abentries[$i][PR_OFFICE_LOCATION])) { $items[$i][SYNC_GAL_OFFICE] = w2u($abentries[$i][PR_OFFICE_LOCATION]); } } return $items; }
function buildEMLAttachment($attach) { $msgembedded = mapi_attach_openobj($attach); $msgprops = mapi_getprops($msgembedded, array(PR_MESSAGE_CLASS, PR_CLIENT_SUBMIT_TIME, PR_DISPLAY_TO, PR_SUBJECT, PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_EMAIL_ADDRESS)); $msgembeddedrcpttable = mapi_message_getrecipienttable($msgembedded); $msgto = $msgprops[PR_DISPLAY_TO]; if ($msgembeddedrcpttable) { $msgembeddedrecipients = mapi_table_queryrows($msgembeddedrcpttable, array(PR_ADDRTYPE, PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS, PR_RECIPIENT_TYPE, PR_RECIPIENT_FLAGS, PR_PROPOSEDNEWTIME, PR_PROPOSENEWTIME_START, PR_PROPOSENEWTIME_END, PR_RECIPIENT_TRACKSTATUS), 0, 99999999); foreach ($msgembeddedrecipients as $rcpt) { if ($rcpt[PR_DISPLAY_NAME] == $msgprops[PR_DISPLAY_TO]) { $msgto = $rcpt[PR_DISPLAY_NAME]; if (isset($rcpt[PR_EMAIL_ADDRESS]) && $rcpt[PR_EMAIL_ADDRESS] != $msgprops[PR_DISPLAY_TO]) { $msgto .= " <" . $rcpt[PR_EMAIL_ADDRESS] . ">"; } break; } } } $msgsubject = $msgprops[PR_SUBJECT]; $msgfrom = $msgprops[PR_SENT_REPRESENTING_NAME]; if (isset($msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS]) && $msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS] != $msgprops[PR_SENT_REPRESENTING_NAME]) { $msgfrom .= " <" . $msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS] . ">"; } $msgtime = $msgprops[PR_CLIENT_SUBMIT_TIME]; $msgembeddedbody = eml_ReadMessage($msgembedded); $msgembeddedattachtable = mapi_message_getattachmenttable($msgembedded); $msgembeddedattachtablerows = mapi_table_queryallrows($msgembeddedattachtable, array(PR_ATTACH_NUM, PR_ATTACH_METHOD)); if ($msgembeddedattachtablerows) { $boundary = '=_zpush_static'; $headercontenttype = "multipart/mixed"; $msgembeddedbody['body'] = "Unfortunately your mobile is not able to handle MIME Messages\n" . "--" . $boundary . "\n" . "Content-Type: " . $msgembeddedbody['content'] . "; charset=utf-8\n" . "Content-Transfer-Encoding: quoted-printable\n\n" . $msgembeddedbody['body'] . "\n"; foreach ($msgembeddedattachtablerows as $msgembeddedattachtablerow) { $msgembeddedattach = mapi_message_openattach($msgembedded, $msgembeddedattachtablerow[PR_ATTACH_NUM]); if (!$msgembeddedattach) { debugLog("Unable to open attachment number {$attachnum}"); } else { $msgembeddedattachprops = mapi_getprops($msgembeddedattach, array(PR_ATTACH_MIME_TAG, PR_ATTACH_LONG_FILENAME, PR_ATTACH_FILENAME, PR_DISPLAY_NAME)); if (isset($msgembeddedattachprops[PR_ATTACH_LONG_FILENAME])) { $attachfilename = w2u($msgembeddedattachprops[PR_ATTACH_LONG_FILENAME]); } else { if (isset($msgembeddedattachprops[PR_ATTACH_FILENAME])) { $attachfilename = w2u($msgembeddedattachprops[PR_ATTACH_FILENAME]); } else { if (isset($msgembeddedattachprops[PR_DISPLAY_NAME])) { $attachfilename = w2u($msgembeddedattachprops[PR_DISPLAY_NAME]); } else { $attachfilename = w2u("untitled"); } } } if ($msgembeddedattachtablerow[PR_ATTACH_METHOD] == ATTACH_EMBEDDED_MSG) { $attachfilename .= w2u(".eml"); } $msgembeddedbody['body'] .= "--" . $boundary . "\n" . "Content-Type: " . $msgembeddedattachprops[PR_ATTACH_MIME_TAG] . ";\n" . " name=\"" . $attachfilename . "\"\n" . "Content-Transfer-Encoding: base64\n" . "Content-Disposition: attachment;\n" . " filename=\"" . $attachfilename . "\"\n\n"; $msgembeddedattachstream = mapi_openpropertytostream($msgembeddedattach, PR_ATTACH_DATA_BIN); $msgembeddedattachment = ""; while (1) { $msgembeddedattachdata = mapi_stream_read($msgembeddedattachstream, 4096); if (byte_strlen($msgembeddedattachdata) == 0) { break; } $msgembeddedattachment .= $msgembeddedattachdata; } $msgembeddedbody['body'] .= chunk_split(base64_encode($msgembeddedattachment)) . "\n"; unset($msgembeddedattachment); } } $msgembeddedbody['body'] .= "--" . $boundary . "--\n"; } else { $headercontenttype = $msgembeddedbody['content'] . "; charset=utf-8"; $boundary = ''; } $msgembeddedheader = "Subject: " . $msgsubject . "\n" . "From: " . $msgfrom . "\n" . "To: " . $msgto . "\n" . "Date: " . gmstrftime("%a, %d %b %Y %T +0000", $msgprops[PR_CLIENT_SUBMIT_TIME]) . "\n" . "MIME-Version: 1.0\n" . "Content-Type: " . $headercontenttype . ";\n" . ($boundary ? " boundary=\"" . $boundary . "\"\n" : "") . "\n"; $stream = mapi_stream_create(); mapi_stream_setsize($stream, byte_strlen($msgembeddedheader . $msgembeddedbody['body'])); mapi_stream_write($stream, $msgembeddedheader . $msgembeddedbody['body']); mapi_stream_seek($stream, 0, STREAM_SEEK_SET); return $stream; }
function getSearchResults($searchquery, $searchrange) { // only return users from who the displayName or the username starts with $name //TODO: use PR_ANR for this restriction instead of PR_DISPLAY_NAME and PR_ACCOUNT $addrbook = mapi_openaddressbook($this->_session); $ab_entryid = mapi_ab_getdefaultdir($addrbook); $ab_dir = mapi_ab_openentry($addrbook, $ab_entryid); $table = mapi_folder_getcontentstable($ab_dir); $restriction = $this->_getSearchRestriction(u2w($searchquery)); mapi_table_restrict($table, $restriction); mapi_table_sort($table, array(PR_DISPLAY_NAME => TABLE_SORT_ASCEND)); //range for the search results, default symbian range end is 50, wm 99, //so we'll use that of nokia $rangestart = 0; $rangeend = 50; if ($searchrange != '0') { $pos = strpos($searchrange, '-'); $rangestart = substr($searchrange, 0, $pos); $rangeend = substr($searchrange, $pos + 1); } $items = array(); $querycnt = mapi_table_getrowcount($table); //do not return more results as requested in range $querylimit = $rangeend + 1 < $querycnt ? $rangeend + 1 : $querycnt; $items['range'] = $rangestart . '-' . ($querylimit - 1); $abentries = mapi_table_queryrows($table, array(PR_ACCOUNT, PR_DISPLAY_NAME, PR_SMTP_ADDRESS, PR_BUSINESS_TELEPHONE_NUMBER), $rangestart, $querylimit); for ($i = 0; $i < $querylimit; $i++) { $items[$i]["username"] = w2u($abentries[$i][PR_ACCOUNT]); $items[$i]["fullname"] = w2u($abentries[$i][PR_DISPLAY_NAME]); if (strlen(trim($items[$i]["fullname"])) == 0) { $items[$i]["fullname"] = $items[$i]["username"]; } $items[$i]["emailaddress"] = w2u($abentries[$i][PR_SMTP_ADDRESS]); $items[$i]["nameid"] = $searchquery; //check if an user has a business phone or it might produce warnings in the log $items[$i]["businessphone"] = isset($abentries[$i][PR_BUSINESS_TELEPHONE_NUMBER]) ? w2u($abentries[$i][PR_BUSINESS_TELEPHONE_NUMBER]) : ""; } return $items; }
function readResolveRecipientfromGAL($emailaddress) { $ab = mapi_openaddressbook($this->_session); $ab_entryid = mapi_ab_getdefaultdir($ab); $ab_dir = mapi_ab_openentry($ab, $ab_entryid); $table = mapi_folder_getcontentstable($ab_dir); $restriction = array(RES_PROPERTY, array(RELOP => RELOP_EQ, ULPROPTAG => PR_SMTP_ADDRESS, VALUE => $emailaddress)); mapi_table_restrict($table, $restriction); $rows = mapi_table_queryrows($table, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_SMTP_ADDRESS, PR_USER_CERTIFICATE), 0, 999); return $rows; }
/** * Resolves recipient from the GAL and gets his certificates. * * @param string $to * @return SyncResolveRecipient|boolean */ private function resolveRecipientGAL($to) { $addrbook = $this->getAddressbook(); $ab_entryid = mapi_ab_getdefaultdir($addrbook); if ($ab_entryid) { $ab_dir = mapi_ab_openentry($addrbook, $ab_entryid); } if ($ab_dir) { $table = mapi_folder_getcontentstable($ab_dir); } // if (!$table) // throw new StatusException(sprintf("ZarafaBackend->resolveRecipient(): could not open addressbook: 0x%X", mapi_last_hresult()), SYNC_RESOLVERECIPSSTATUS_RESPONSE_UNRESOLVEDRECIP); if (!$table) { ZLog::Write(LOGLEVEL_WARN, sprintf("Unable to open addressbook:0x%X", mapi_last_hresult())); return false; } $restriction = MAPIUtils::GetSearchRestriction(u2w($to)); mapi_table_restrict($table, $restriction); $querycnt = mapi_table_getrowcount($table); if ($querycnt > 0) { $abentries = mapi_table_queryrows($table, array(PR_DISPLAY_NAME, PR_EMS_AB_TAGGED_X509_CERT), 0, 1); $certificates = isset($abentries[0][PR_EMS_AB_TAGGED_X509_CERT]) && is_array($abentries[0][PR_EMS_AB_TAGGED_X509_CERT]) && count($abentries[0][PR_EMS_AB_TAGGED_X509_CERT]) ? $this->getCertificates($abentries[0][PR_EMS_AB_TAGGED_X509_CERT], $querycnt) : false; if ($certificates === false) { // the recipient does not have a valid certificate, set the appropriate status ZLog::Write(LOGLEVEL_INFO, sprintf("No certificates found for '%s'", $to)); $certificates = $this->getCertificates(false); } $recipient = $this->createResolveRecipient(SYNC_RESOLVERECIPIENTS_TYPE_GAL, w2u($abentries[0][PR_DISPLAY_NAME]), $to, $certificates); return $recipient; } else { ZLog::Write(LOGLEVEL_WARN, sprintf("No recipient found for: '%s'", $to)); return SYNC_RESOLVERECIPSSTATUS_RESPONSE_UNRESOLVEDRECIP; } return false; }
/** * Resolves recipient from the GAL and gets his certificates. * * @param string $to * @param int $maxAmbiguousRecipients * @return array|boolean */ private function resolveRecipientGAL($to, $maxAmbiguousRecipients) { ZLog::Write(LOGLEVEL_WBXML, sprintf("Resolving recipient '%s' in GAL", $to)); $addrbook = $this->getAddressbook(); // FIXME: create a function to get the adressbook contentstable $ab_entryid = mapi_ab_getdefaultdir($addrbook); if ($ab_entryid) { $ab_dir = mapi_ab_openentry($addrbook, $ab_entryid); } if ($ab_dir) { $table = mapi_folder_getcontentstable($ab_dir); } if (!$table) { ZLog::Write(LOGLEVEL_WARN, sprintf("Unable to open addressbook:0x%X", mapi_last_hresult())); return false; } $restriction = MAPIUtils::GetSearchRestriction(u2w($to)); mapi_table_restrict($table, $restriction); $querycnt = mapi_table_getrowcount($table); if ($querycnt > 0) { $recipientGal = array(); $rowsToQuery = $maxAmbiguousRecipients; // some devices request 0 ambiguous recipients if ($querycnt == 1 && $maxAmbiguousRecipients == 0) { $rowsToQuery = 1; } elseif ($querycnt > 1 && $maxAmbiguousRecipients == 0) { ZLog::Write(LOGLEVEL_INFO, sprintf("GAL search found %d recipients but the device hasn't requested ambiguous recipients", $querycnt)); return $recipientGal; } // get the certificate every time because caching the certificate is less expensive than opening addressbook entry again $abentries = mapi_table_queryrows($table, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_EMS_AB_TAGGED_X509_CERT, PR_OBJECT_TYPE), 0, $rowsToQuery); for ($i = 0, $nrEntries = count($abentries); $i < $nrEntries; $i++) { if ($abentries[$i][PR_OBJECT_TYPE] == MAPI_DISTLIST) { // dist lists must be expanded into their members ZLog::Write(LOGLEVEL_DEBUG, sprintf("'%s' is a dist list. Expand it to members.", $to)); $distList = mapi_ab_openentry($addrbook, $abentries[$i][PR_ENTRYID]); $distListContent = mapi_folder_getcontentstable($distList); $distListMembers = mapi_table_queryallrows($distListContent, array(PR_ENTRYID, PR_DISPLAY_NAME, PR_EMS_AB_TAGGED_X509_CERT)); for ($j = 0, $nrDistListMembers = mapi_table_getrowcount($distListContent); $j < $nrDistListMembers; $j++) { ZLog::Write(LOGLEVEL_WBXML, sprintf("distlist's '%s' member", $to, $distListMembers[$j][PR_DISPLAY_NAME])); $recipientGal[] = $this->createResolveRecipient(SYNC_RESOLVERECIPIENTS_TYPE_GAL, $to, $distListMembers[$j], $nrDistListMembers); } } elseif ($abentries[$i][PR_OBJECT_TYPE] == MAPI_MAILUSER) { $recipientGal[] = $this->createResolveRecipient(SYNC_RESOLVERECIPIENTS_TYPE_GAL, $to, $abentries[$i]); } } ZLog::Write(LOGLEVEL_WBXML, "Found a recipient in GAL"); return $recipientGal; } else { ZLog::Write(LOGLEVEL_WARN, sprintf("No recipient found for: '%s' in GAL", $to)); return SYNC_RESOLVERECIPSSTATUS_RESPONSE_UNRESOLVEDRECIP; } return false; }
function getSearchResultsGAL($searchquery) { // only return users from who the displayName or the username starts with $name //TODO: use PR_ANR for this restriction instead of PR_DISPLAY_NAME and PR_ACCOUNT $addrbook = mapi_openaddressbook($this->_session); $ab_entryid = mapi_ab_getdefaultdir($addrbook); $ab_dir = mapi_ab_openentry($addrbook, $ab_entryid); $table = mapi_folder_getcontentstable($ab_dir); $restriction = $this->_getSearchRestriction(u2w($searchquery)); mapi_table_restrict($table, $restriction); mapi_table_sort($table, array(PR_DISPLAY_NAME => TABLE_SORT_ASCEND)); // CHANGED dw2412 AS V12.0 Support (to menetain single return way... $items['rows'] = array(); for ($i = 0; $i < mapi_table_getrowcount($table); $i++) { $user_data = mapi_table_queryrows($table, array(PR_ACCOUNT, PR_DISPLAY_NAME, PR_SMTP_ADDRESS, PR_BUSINESS_TELEPHONE_NUMBER), $i, 1); $item = array(); $item["username"] = w2u($user_data[0][PR_ACCOUNT]); $item["fullname"] = w2u($user_data[0][PR_DISPLAY_NAME]); if (strlen(trim($item["fullname"])) == 0) { $item["fullname"] = $item["username"]; } $item["emailaddress"] = w2u($user_data[0][PR_SMTP_ADDRESS]); $item["nameid"] = $searchquery; $item["businessphone"] = isset($user_data[0][PR_BUSINESS_TELEPHONE_NUMBER]) ? w2u($user_data[0][PR_BUSINESS_TELEPHONE_NUMBER]) : ""; //do not return users without email if (strlen(trim($item["emailaddress"])) == 0) { continue; } // CHANGED dw2412 AS V12.0 Support (to menetain single return way... array_push($items['rows'], $item); } $items['status'] = 1; return $items; }