contactimporter:

v1.0: 24.6.2013
 - import vcards (1 or more vcards in a file)
 - chooseable destination addressbook
This commit is contained in:
2013-06-24 20:21:09 +00:00
parent 1bb1f956d0
commit 24f2f5d974
8 changed files with 382 additions and 1094 deletions

View File

@@ -26,7 +26,7 @@ require_once('mapi/mapitags.php' );
class ContactModule extends Module {
private $DEBUG = true; // enable error_log debugging
private $DEBUG = false; // enable error_log debugging
/**
* @constructor
@@ -57,18 +57,12 @@ class ContactModule extends Module {
error_log("exec: " . $actionType);
}
switch($actionType) {
case "export":
$result = $this->exportCalendar($actionType, $actionData);
case "load":
$result = $this->loadContacts($actionType, $actionData);
break;
case "import":
$result = $this->importContacts($actionType, $actionData);
break;
case "addattachment":
$result = $this->addAttachment($actionType, $actionData);
break;
case "attachmentpath":
$result = $this->getAttachmentPath($actionType, $actionData);
break;
default:
$this->handleUnknownActionType($actionType);
}
@@ -109,219 +103,375 @@ class ContactModule extends Module {
return $pass;
}
/**
* Generates the secid file (used to verify the download path)
* @param $secid the secid, a random security token
*/
private function createSecIDFile($secid) {
$lockFile = TMP_PATH . "/secid." . $secid;
$fh = fopen($lockFile, 'w') or die("can't open secid file");
$stringData = date(DATE_RFC822);
fwrite($fh, $stringData);
fclose($fh);
}
/**
* Generates the secid file (used to verify the download path)
* @param $time a timestamp
* @param $incl_time true if date should include time
* @ return date object
*/
private function getIcalDate($time, $incl_time = true) {
return $incl_time ? date('Ymd\THis', $time) : date('Ymd', $time);
}
/**
* Add an attachment to the give contact
* @param $actionType
* @param $actionData
*/
private function addAttachment($actionType, $actionData) {
private function importContacts($actionType, $actionData) {
// Get uploaded vcf path
$vcffile = false;
if(isset($actionData["vcf_filepath"])) {
$vcffile = $actionData["vcf_filepath"];
}
// Get store id
$storeid = false;
if(isset($actionData["storeid"])) {
$storeid = $actionData["storeid"];
}
// Get message entryid
$entryid = false;
if(isset($actionData["entryid"])) {
$entryid = $actionData["entryid"];
// Get folder entryid
$folderid = false;
if(isset($actionData["folderid"])) {
$folderid = $actionData["folderid"];
}
$tmpimage = $actionData["tmpfile"];
$contactPicture = file_get_contents ($tmpimage);
// Get uids
$uids = array();
if(isset($actionData["uids"])) {
$uids = $actionData["uids"];
}
error_log($tmpdata);
$response = array();
$error = false;
$error_msg = "";
error_log("opening store");
$store = $GLOBALS["mapisession"]->openMessageStore(hex2bin($storeid));
error_log("opening message");
// Open a message from the store
// parse the vcf file a last time...
try {
$message = mapi_msgstore_openentry($store, hex2bin($entryid));
} catch (MAPIException $e) {
$e->setHandled();
error_log($e->getCode());
error_log(mapi_last_hresult());
}
$vcard = new vCard($vcffile, false, array('Collapse' => false)); // Parse it!
} catch (Exception $e) {
$error = true;
$error_msg = $e->getMessage();
}
error_log("opening attachment");
// Open attachment number 0
$attach = mapi_message_createattach($message);
$contacts = array();
// Set properties of the attachment
$properties = array(
//PR_ATTACH_SIZE => strlen($contactPicture),
PR_ATTACH_LONG_FILENAME => 'ContactPicture.jpg',
PR_ATTACHMENT_HIDDEN => false,
PR_DISPLAY_NAME => 'ContactPicture.jpg',
PR_ATTACH_METHOD => ATTACH_BY_VALUE,
PR_ATTACH_MIME_TAG => 'image/jpeg',
PR_ATTACHMENT_CONTACTPHOTO => true,
PR_ATTACH_DATA_BIN => "",
PR_ATTACHMENT_FLAGS => 1,
PR_ATTACH_EXTENSION_A => '.jpg',
PR_ATTACH_NUM => 1
);
if(!$error && count($vcard) > 0) {
$vCard = $vcard;
if (count($vCard) == 1) {
$vCard = array($vcard);
}
$contacts = $this->parseContactsToArray($vCard);
$store = $GLOBALS["mapisession"]->openMessageStore(hex2bin($storeid));
$folder = mapi_msgstore_openentry($store, hex2bin($folderid));
$importall = false;
if(count($uids) == count($contacts)) {
$importall = true;
}
$propValuesMAPI = array();
$properties = $this->getProperties();
$properties = $this->replaceStringPropertyTags($store, $properties);
$count = 0;
// iterate through all contacts and import them :)
foreach($contacts as $contact) {
if (isset($contact["display_name"]) && ($importall || in_array($contact["internal_fields"]["contact_uid"], $uids))) {
// parse the arraykeys
// TODO: this is very slow...
foreach($contact as $key => $value) {
if($key !== "internal_fields") {
$propValuesMAPI[$properties[$key]] = $value;
}
}
$propValuesMAPI[$properties["message_class"]] = "IPM.Contact";
$propValuesMAPI[$properties["icon_index"]] = "512";
$message = mapi_folder_createmessage($folder);
if(isset($contact["internal_fields"]["x_photo_path"])) {
$propValuesMAPI[$properties["picture"]] = 1; // contact has an image
error_log("setting props");
mapi_setprops($attach, $properties);
// import the photo
$contactPicture = file_get_contents($contact["internal_fields"]["x_photo_path"]);
$attach = mapi_message_createattach($message);
// Stream the file to the PR_ATTACH_DATA_BIN property
error_log("streaming file");
$stream = mapi_openproperty($attach, PR_ATTACH_DATA_BIN, IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY);
$handle = fopen($tmpimage, "r");
while (!feof($handle)) {
$contents = fread($handle, BLOCK_SIZE);
mapi_stream_write($stream, $contents);
}
// Commit the stream and save changes
mapi_stream_commit($stream);
error_log("saving attachment");
mapi_savechanges($attach);
if (mapi_last_hresult() > 0) {
error_log("Error saving attach to contact: " . get_mapi_error_name());
}
error_log("saving message");
mapi_savechanges($message);
if (mapi_last_hresult() > 0) {
error_log("Error saving contact: " . get_mapi_error_name());
}
// Open attachment number 0
error_log("final tests attachment");
$testattach = mapi_message_openattach ($message, 0);
error_log(print_r(mapi_attach_getprops($testattach),true));
// Set properties of the attachment
$propValuesIMG = array(
PR_ATTACH_SIZE => strlen($contactPicture),
PR_ATTACH_LONG_FILENAME => 'ContactPicture.jpg',
PR_ATTACHMENT_HIDDEN => false,
PR_DISPLAY_NAME => 'ContactPicture.jpg',
PR_ATTACH_METHOD => ATTACH_BY_VALUE,
PR_ATTACH_MIME_TAG => 'image/jpeg',
PR_ATTACHMENT_CONTACTPHOTO => true,
PR_ATTACH_DATA_BIN => $contactPicture,
PR_ATTACHMENT_FLAGS => 1,
PR_ATTACH_EXTENSION_A => '.jpg',
PR_ATTACH_NUM => 1
);
mapi_setprops($attach, $propValuesIMG);
mapi_savechanges($attach);
if($this->DEBUG) {
error_log("Contactpicture imported!");
}
if (mapi_last_hresult() > 0) {
error_log("Error saving attach to contact: " . get_mapi_error_name());
}
}
mapi_setprops($message, $propValuesMAPI);
mapi_savechanges($message);
if($this->DEBUG) {
error_log("New contact added: \"" . $propValuesMAPI[$properties["display_name"]] . "\".\n");
}
$count++;
}
}
$response['status'] = true;
$response['storeid'] = $storeid;
$response['entryid'] = $entryid;
$response['status'] = true;
$response['count'] = $count;
$response['message'] = "";
} else {
$response['status'] = false;
$response['count'] = 0;
$response['message'] = $error ? $error_msg : "VCF file empty!";
}
$this->addActionData($actionType, $response);
$GLOBALS["bus"]->addData($this->getResponseData());
}
private function replaceStringPropertyTags($store, $properties) {
$newProperties = array();
/**
* The main export function, creates the ics file for download
* @param $actionType
* @param $actionData
*/
private function exportContacts($actionType, $actionData) {
$secid = $this->randomstring();
$this->createSecIDFile($secid);
$tmpname = stripslashes($actionData["calendar"] . ".ics." . $this->randomstring(8));
$filename = TMP_PATH . "/" . $tmpname . "." . $secid;
if(!is_writable(TMP_PATH . "/")) {
error_log("could not write to export tmp directory!");
}
$tz = date("e"); // use php timezone (maybe set up in php.ini, date.timezone)
if($this->DEBUG) {
error_log("PHP Timezone: " . $tz);
}
$config = array(
"language" => substr($GLOBALS["settings"]->get("zarafa/v1/main/language"),0,2),
"directory" => TMP_PATH . "/",
"filename" => $tmpname . "." . $secid,
"unique_id" => "zarafa-export-plugin",
"TZID" => $tz
);
$v = new vcalendar($config);
$v->setProperty("method", "PUBLISH"); // required of some calendar software
$v->setProperty("x-wr-calname", $actionData["calendar"]); // required of some calendar software
$v->setProperty("X-WR-CALDESC", "Exported Zarafa Calendar"); // required of some calendar software
$v->setProperty("X-WR-TIMEZONE", $tz);
$ids = array("name"=>array(), "id"=>array(), "guid"=>array(), "type"=>array()); // this array stores all the information needed to retrieve a named property
$num = 0;
$xprops = array("X-LIC-LOCATION" => $tz); // required of some calendar software
iCalUtilityFunctions::createTimezone($v, $tz, $xprops); // create timezone object in calendar
foreach($actionData["data"] as $event) {
$event["props"]["description"] = $this->loadEventDescription($event);
$event["props"]["attendees"] = $this->loadAttendees($event);
$vevent = & $v->newComponent("vevent"); // create a new event object
$this->addEvent($vevent, $event["props"]);
// caching
$guids = array();
foreach($properties as $name => $val) {
if(is_string($val)) {
$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++;
} else {
// not a named property
$newProperties[$name] = $val;
}
}
$v->saveCalendar();
$response['status'] = true;
$response['fileid'] = $tmpname; // number of entries that will be exported
$response['basedir'] = TMP_PATH;
$response['secid'] = $secid;
$response['realname'] = $actionData["calendar"];
$this->addActionData($actionType, $response);
$GLOBALS["bus"]->addData($this->getResponseData());
if($this->DEBUG) {
error_log("export done, bus data written!");
if (count($ids["id"]) == 0) {
return $newProperties;
}
// get the ids
$named = mapi_getidsfromnames($store, $ids["id"], $ids["guid"]);
foreach($named as $num => $prop) {
$newProperties[$ids["name"][$num]] = mapi_prop_tag(constant($ids["type"][$num]), mapi_prop_id($prop));
}
return $newProperties;
}
/**
* The main import function, parses the uploaded vcf file
* A simple Property map initialization
*
* @return [array] the propertyarray
*/
private function getProperties() {
$properties = array();
$properties["subject"] = PR_SUBJECT;
$properties["icon_index"] = PR_ICON_INDEX;
$properties["message_class"] = PR_MESSAGE_CLASS;
$properties["display_name"] = PR_DISPLAY_NAME;
$properties["given_name"] = PR_GIVEN_NAME;
$properties["middle_name"] = PR_MIDDLE_NAME;
$properties["surname"] = PR_SURNAME;
$properties["home_telephone_number"] = PR_HOME_TELEPHONE_NUMBER;
$properties["cellular_telephone_number"] = PR_CELLULAR_TELEPHONE_NUMBER;
$properties["office_telephone_number"] = PR_OFFICE_TELEPHONE_NUMBER;
$properties["business_fax_number"] = PR_BUSINESS_FAX_NUMBER;
$properties["company_name"] = PR_COMPANY_NAME;
$properties["title"] = PR_TITLE;
$properties["department_name"] = PR_DEPARTMENT_NAME;
$properties["office_location"] = PR_OFFICE_LOCATION;
$properties["profession"] = PR_PROFESSION;
$properties["manager_name"] = PR_MANAGER_NAME;
$properties["assistant"] = PR_ASSISTANT;
$properties["nickname"] = PR_NICKNAME;
$properties["display_name_prefix"] = PR_DISPLAY_NAME_PREFIX;
$properties["spouse_name"] = PR_SPOUSE_NAME;
$properties["generation"] = PR_GENERATION;
$properties["birthday"] = PR_BIRTHDAY;
$properties["wedding_anniversary"] = PR_WEDDING_ANNIVERSARY;
$properties["sensitivity"] = PR_SENSITIVITY;
$properties["fileas"] = "PT_STRING8:PSETID_Address:0x8005";
$properties["fileas_selection"] = "PT_LONG:PSETID_Address:0x8006";
$properties["email_address_1"] = "PT_STRING8:PSETID_Address:0x8083";
$properties["email_address_display_name_1"] = "PT_STRING8:PSETID_Address:0x8080";
$properties["email_address_display_name_email_1"] = "PT_STRING8:PSETID_Address:0x8084";
$properties["email_address_type_1"] = "PT_STRING8:PSETID_Address:0x8082";
$properties["email_address_2"] = "PT_STRING8:PSETID_Address:0x8093";
$properties["email_address_display_name_2"] = "PT_STRING8:PSETID_Address:0x8090";
$properties["email_address_display_name_email_2"] = "PT_STRING8:PSETID_Address:0x8094";
$properties["email_address_type_2"] = "PT_STRING8:PSETID_Address:0x8092";
$properties["email_address_3"] = "PT_STRING8:PSETID_Address:0x80a3";
$properties["email_address_display_name_3"] = "PT_STRING8:PSETID_Address:0x80a0";
$properties["email_address_display_name_email_3"] = "PT_STRING8:PSETID_Address:0x80a4";
$properties["email_address_type_3"] = "PT_STRING8:PSETID_Address:0x80a2";
$properties["home_address"] = "PT_STRING8:PSETID_Address:0x801a";
$properties["business_address"] = "PT_STRING8:PSETID_Address:0x801b";
$properties["other_address"] = "PT_STRING8:PSETID_Address:0x801c";
$properties["mailing_address"] = "PT_LONG:PSETID_Address:0x8022";
$properties["im"] = "PT_STRING8:PSETID_Address:0x8062";
$properties["webpage"] = "PT_STRING8:PSETID_Address:0x802b";
$properties["business_home_page"] = PR_BUSINESS_HOME_PAGE;
$properties["email_address_entryid_1"] = "PT_BINARY:PSETID_Address:0x8085";
$properties["email_address_entryid_2"] = "PT_BINARY:PSETID_Address:0x8095";
$properties["email_address_entryid_3"] = "PT_BINARY:PSETID_Address:0x80a5";
$properties["address_book_mv"] = "PT_MV_LONG:PSETID_Address:0x8028";
$properties["address_book_long"] = "PT_LONG:PSETID_Address:0x8029";
$properties["oneoff_members"] = "PT_MV_BINARY:PSETID_Address:0x8054";
$properties["members"] = "PT_MV_BINARY:PSETID_Address:0x8055";
$properties["private"] = "PT_BOOLEAN:PSETID_Common:0x8506";
$properties["contacts"] = "PT_MV_STRING8:PSETID_Common:0x853a";
$properties["contacts_string"] = "PT_STRING8:PSETID_Common:0x8586";
$properties["categories"] = "PT_MV_STRING8:PS_PUBLIC_STRINGS:Keywords";
$properties["last_modification_time"] = PR_LAST_MODIFICATION_TIME;
// Detailed contacts properties
// Properties for phone numbers
$properties["assistant_telephone_number"] = PR_ASSISTANT_TELEPHONE_NUMBER;
$properties["business2_telephone_number"] = PR_BUSINESS2_TELEPHONE_NUMBER;
$properties["callback_telephone_number"] = PR_CALLBACK_TELEPHONE_NUMBER;
$properties["car_telephone_number"] = PR_CAR_TELEPHONE_NUMBER;
$properties["company_telephone_number"] = PR_COMPANY_MAIN_PHONE_NUMBER;
$properties["home2_telephone_number"] = PR_HOME2_TELEPHONE_NUMBER;
$properties["home_fax_number"] = PR_HOME_FAX_NUMBER;
$properties["isdn_number"] = PR_ISDN_NUMBER;
$properties["other_telephone_number"] = PR_OTHER_TELEPHONE_NUMBER;
$properties["pager_telephone_number"] = PR_PAGER_TELEPHONE_NUMBER;
$properties["primary_fax_number"] = PR_PRIMARY_FAX_NUMBER;
$properties["primary_telephone_number"] = PR_PRIMARY_TELEPHONE_NUMBER;
$properties["radio_telephone_number"] = PR_RADIO_TELEPHONE_NUMBER;
$properties["telex_telephone_number"] = PR_TELEX_NUMBER;
$properties["ttytdd_telephone_number"] = PR_TTYTDD_PHONE_NUMBER;
$properties["business_telephone_number"] =PR_BUSINESS_TELEPHONE_NUMBER;
// Additional fax properties
$properties["fax_1_address_type"] = "PT_STRING8:PSETID_Address:0x80B2";
$properties["fax_1_email_address"] = "PT_STRING8:PSETID_Address:0x80B3";
$properties["fax_1_original_display_name"] = "PT_STRING8:PSETID_Address:0x80B4";
$properties["fax_1_original_entryid"] = "PT_BINARY:PSETID_Address:0x80B5";
$properties["fax_2_address_type"] = "PT_STRING8:PSETID_Address:0x80C2";
$properties["fax_2_email_address"] = "PT_STRING8:PSETID_Address:0x80C3";
$properties["fax_2_original_display_name"] = "PT_STRING8:PSETID_Address:0x80C4";
$properties["fax_2_original_entryid"] = "PT_BINARY:PSETID_Address:0x80C5";
$properties["fax_3_address_type"] = "PT_STRING8:PSETID_Address:0x80D2";
$properties["fax_3_email_address"] = "PT_STRING8:PSETID_Address:0x80D3";
$properties["fax_3_original_display_name"] = "PT_STRING8:PSETID_Address:0x80D4";
$properties["fax_3_original_entryid"] = "PT_BINARY:PSETID_Address:0x80D5";
// Properties for addresses
// Home address
$properties["home_address_street"] = PR_HOME_ADDRESS_STREET;
$properties["home_address_city"] = PR_HOME_ADDRESS_CITY;
$properties["home_address_state"] = PR_HOME_ADDRESS_STATE_OR_PROVINCE;
$properties["home_address_postal_code"] = PR_HOME_ADDRESS_POSTAL_CODE;
$properties["home_address_country"] = PR_HOME_ADDRESS_COUNTRY;
// Other address
$properties["other_address_street"] = PR_OTHER_ADDRESS_STREET;
$properties["other_address_city"] = PR_OTHER_ADDRESS_CITY;
$properties["other_address_state"] = PR_OTHER_ADDRESS_STATE_OR_PROVINCE;
$properties["other_address_postal_code"] = PR_OTHER_ADDRESS_POSTAL_CODE;
$properties["other_address_country"] = PR_OTHER_ADDRESS_COUNTRY;
// Business address
$properties["business_address_street"] = "PT_STRING8:PSETID_Address:0x8045";
$properties["business_address_city"] = "PT_STRING8:PSETID_Address:0x8046";
$properties["business_address_state"] = "PT_STRING8:PSETID_Address:0x8047";
$properties["business_address_postal_code"] = "PT_STRING8:PSETID_Address:0x8048";
$properties["business_address_country"] = "PT_STRING8:PSETID_Address:0x8049";
// Mailing address
$properties["country"] = PR_COUNTRY;
$properties["city"] = PR_LOCALITY;
$properties["postal_address"] = PR_POSTAL_ADDRESS;
$properties["postal_code"] = PR_POSTAL_CODE;
$properties["state"] = PR_STATE_OR_PROVINCE;
$properties["street"] = PR_STREET_ADDRESS;
// Special Date such as birthday n anniversary appoitment's entryid is store
$properties["birthday_eventid"] = "PT_BINARY:PSETID_Address:0x804D";
$properties["anniversary_eventid"] = "PT_BINARY:PSETID_Address:0x804E";
$properties["notes"] = PR_BODY;
// hasimage
$properties["picture"] = "PT_BOOLEAN:{00062004-0000-0000-C000-000000000046}:0x8015";
return $properties;
}
/**
* Function that parses the uploaded vcf file and posts it via json
* @param $actionType
* @param $actionData
*/
private function importContacts($actionType, $actionData) {
if($this->DEBUG) {
error_log("PHP Timezone: " . $tz);
}
private function loadContacts($actionType, $actionData) {
$error = false;
$error_msg = "";
if(is_readable ($actionData["vcf_filepath"])) {
$vcard = new vCard($actionData["vcf_filepath"], false, array('Collapse' => false)); // Parse it!
error_log(print_r($vcard, true));
if(count($vcard) == 0) {
try {
$vcard = new vCard($actionData["vcf_filepath"], false, array('Collapse' => false)); // Parse it!
} catch (Exception $e) {
$error = true;
$error_msg = $e->getMessage();
}
if($error) {
$response['status'] = false;
$response['message']= "No contacts in vcf file";
$response['message']= $error_msg;
} else {
$vCard = $vcard;
if (count($vCard) == 1) {
$vCard = array($vcard);
if(count($vcard) == 0) {
$response['status'] = false;
$response['message']= "No contacts in vcf file";
} else {
$vCard = $vcard;
if (count($vCard) == 1) {
$vCard = array($vcard);
}
$response['status'] = true;
$response['parsed_file']= $actionData["vcf_filepath"];
$response['parsed'] = array (
'contacts' => $this->parseContactsToArray($vCard)
);
}
$response['status'] = true;
$response['parsed_file']= $actionData["vcf_filepath"];
$response['parsed'] = array (
'contacts' => $this->parseContactsToArray($vCard)
);
}
} else {
$response['status'] = false;
@@ -346,12 +496,17 @@ class ContactModule extends Module {
*/
private function parseContactsToArray($contacts, $csv = false) {
$carr = array();
if(!$csv) {
foreach ($contacts as $Index => $vCard) {
$properties = array();
$properties["display_name"] = $vCard -> FN[0];
$properties["fileas"] = $vCard -> FN[0];
//uid - used for front/backend communication
$properties["internal_fields"] = array();
$properties["internal_fields"]["contact_uid"] = base64_encode($Index . $properties["fileas"]);
foreach ($vCard -> N as $Name) {
$properties["given_name"] = $Name['FirstName'];
$properties["middle_name"] = $Name['AdditionalNames'];
@@ -461,7 +616,7 @@ class ContactModule extends Module {
$properties["birthday"] = strtotime($vCard -> BDAY[0]);
}
if ($vCard -> NOTE) {
$properties["body"] = $vCard -> NOTE[0];
$properties["notes"] = $vCard -> NOTE[0];
}
if ($vCard -> PHOTO) {
if(!is_writable(TMP_PATH . "/")) {
@@ -470,7 +625,7 @@ class ContactModule extends Module {
$tmppath = TMP_PATH . "/" . $this->randomstring(15);
try {
if($vCard -> SaveFile('photo', 0, $tmppath)) {
$properties["x_photo_path"] = $tmppath;
$properties["internal_fields"]["x_photo_path"] = $tmppath;
} else {
if($this->DEBUG) {
error_log("remote imagefetching not implemented");
@@ -516,145 +671,6 @@ class ContactModule extends Module {
return $out;
}
/**
* Store the file to a temporary directory, prepare it for oc upload
* @param $actionType
* @param $actionData
* @private
*/
private function getAttachmentPath($actionType, $actionData) {
// Get store id
$storeid = false;
if(isset($actionData["store"])) {
$storeid = $actionData["store"];
}
// Get message entryid
$entryid = false;
if(isset($actionData["entryid"])) {
$entryid = $actionData["entryid"];
}
// Check which type isset
$openType = "attachment";
// Get number of attachment which should be opened.
$attachNum = false;
if(isset($actionData["attachNum"])) {
$attachNum = $actionData["attachNum"];
}
// Check if storeid and entryid isset
if($storeid && $entryid) {
// Open the store
$store = $GLOBALS["mapisession"]->openMessageStore(hex2bin($storeid));
if($store) {
// Open the message
$message = mapi_msgstore_openentry($store, hex2bin($entryid));
if($message) {
$attachment = false;
// Check if attachNum isset
if($attachNum) {
// Loop through the attachNums, message in message in message ...
for($i = 0; $i < (count($attachNum) - 1); $i++)
{
// Open the attachment
$tempattach = mapi_message_openattach($message, (int) $attachNum[$i]);
if($tempattach) {
// Open the object in the attachment
$message = mapi_attach_openobj($tempattach);
}
}
// Open the attachment
$attachment = mapi_message_openattach($message, (int) $attachNum[(count($attachNum) - 1)]);
}
// Check if the attachment is opened
if($attachment) {
// Get the props of the attachment
$props = mapi_attach_getprops($attachment, array(PR_ATTACH_LONG_FILENAME, PR_ATTACH_MIME_TAG, PR_DISPLAY_NAME, PR_ATTACH_METHOD));
// Content Type
$contentType = "application/octet-stream";
// Filename
$filename = "ERROR";
// Set filename
if(isset($props[PR_ATTACH_LONG_FILENAME])) {
$filename = $props[PR_ATTACH_LONG_FILENAME];
} else if(isset($props[PR_ATTACH_FILENAME])) {
$filename = $props[PR_ATTACH_FILENAME];
} else if(isset($props[PR_DISPLAY_NAME])) {
$filename = $props[PR_DISPLAY_NAME];
}
// Set content type
if(isset($props[PR_ATTACH_MIME_TAG])) {
$contentType = $props[PR_ATTACH_MIME_TAG];
} else {
// Parse the extension of the filename to get the content type
if(strrpos($filename, ".") !== false) {
$extension = strtolower(substr($filename, strrpos($filename, ".")));
$contentType = "application/octet-stream";
if (is_readable("mimetypes.dat")){
$fh = fopen("mimetypes.dat","r");
$ext_found = false;
while (!feof($fh) && !$ext_found){
$line = fgets($fh);
preg_match("/(\.[a-z0-9]+)[ \t]+([^ \t\n\r]*)/i", $line, $result);
if ($extension == $result[1]){
$ext_found = true;
$contentType = $result[2];
}
}
fclose($fh);
}
}
}
$tmpname = tempnam(TMP_PATH, stripslashes($filename));
// Open a stream to get the attachment data
$stream = mapi_openpropertytostream($attachment, PR_ATTACH_DATA_BIN);
$stat = mapi_stream_stat($stream);
// File length = $stat["cb"]
$fhandle = fopen($tmpname,'w');
$buffer = null;
for($i = 0; $i < $stat["cb"]; $i += BLOCK_SIZE) {
// Write stream
$buffer = mapi_stream_read($stream, BLOCK_SIZE);
fwrite($fhandle,$buffer,strlen($buffer));
}
fclose($fhandle);
$response = array();
$response['tmpname'] = $tmpname;
$response['filename'] = $filename;
$response['status'] = true;
$this->addActionData($actionType, $response);
$GLOBALS["bus"]->addData($this->getResponseData());
}
}
} else {
$response['status'] = false;
$response['message'] = "Store could not be opened!";
$this->addActionData($actionType, $response);
$GLOBALS["bus"]->addData($this->getResponseData());
}
} else {
$response['status'] = false;
$response['message'] = "Wrong call, store and entryid have to be set!";
$this->addActionData($actionType, $response);
$GLOBALS["bus"]->addData($this->getResponseData());
}
}
};
?>