Zarafa Alert Script : Recurrent Meeting
From Zarafa wiki
- !/usr/bin/php
<? /**
* This script can be used to fix all recurring items in Calendar which fall between 25oct to 31oct * When calling from command line you have to pass usernames in space separated list to the script, * if you want to fix recurring items for all users then pass "-a" as argument to the script * * Usage: * for selected users * php fix_recurring_items.php -u <username1> <username2> ... * for all users * php fix_recurring_items.php -a */
// comment this line for debugging error_reporting(0);
// mapi include files include('/usr/share/php/mapi/mapi.util.php'); include('/usr/share/php/mapi/mapidefs.php'); include('/usr/share/php/mapi/mapicode.php'); include('/usr/share/php/mapi/mapitags.php'); include('/usr/share/php/mapi/mapiguid.php'); include('/usr/share/php/mapi/class.recurrence.php');
// config options $ADMINUSERNAME = "SYSTEM"; $ADMINPASSWORD = ""; $SERVER = "file:///var/run/zarafa"; $USAGEMESSAGE = "Usage:\n\tfor selected users \n\t\tphp fix_recurring_items.php -u <username1> <username2> ...\n\tfor all users \n\t\tphp fix_recurring_items.php -a\n";
// properties
$proptags = Array();
$proptags["entryid"] = PR_ENTRYID;
$proptags["subject"] = PR_SUBJECT;
$proptags["meetingstatus"] = "PT_LONG:PSETID_Appointment:0x8217";
$proptags["commonstart"] = "PT_SYSTIME:PSETID_Common:0x8516";
$proptags["commonend"] = "PT_SYSTIME:PSETID_Common:0x8517";
$proptags["recurring"] = "PT_BOOLEAN:PSETID_Appointment:0x8223";
$proptags["timezone_data"] = "PT_BINARY:PSETID_Appointment:0x8233";
$proptags["clipstart"] = "PT_SYSTIME:PSETID_Appointment:0x8235";
$proptags["clipend"] = "PT_SYSTIME:PSETID_Appointment:0x8236";
$proptags["startrecurdate"] = "PT_LONG:PSETID_Meeting:0xD";
$proptags["startrecurtime"] = "PT_LONG:PSETID_Meeting:0xE";
$proptags["endrecurdate"] = "PT_LONG:PSETID_Meeting:0xF";
$proptags["endrecurtime"] = "PT_LONG:PSETID_Meeting:0x10";
if($argc < 2) { exit($USAGEMESSAGE); }
// use SYSTEM account for login $session = mapi_logon_zarafa($ADMINUSERNAME, $ADMINPASSWORD, $SERVER); if(!$session) { exit("Can't login into zarafa server\n"); }
// get all stores of SYSTEM account $msgStoresTable = mapi_getmsgstorestable($session); $msgStores = mapi_table_queryallrows($msgStoresTable, array(PR_DEFAULT_STORE, PR_ENTRYID));
// get default store foreach ($msgStores as $row) { if($row[PR_DEFAULT_STORE]) { $storeEntryid = $row[PR_ENTRYID]; } }
if(!$storeEntryid) { exit("Can't find default store\n"); }
// open default store $store = mapi_openmsgstore($session, $storeEntryid); if(!$store) { exit("Unable to open system store\n"); }
// set named properties $GLOBALS['proptags'] = getPropIdsFromStrings($store, $proptags);
if(strcasecmp($argv[1], "-a") == 0) { // get all zarafa users and remove property data $userList = array();
// for multi company setup $companyList = mapi_zarafa_getcompanylist($store); if(mapi_last_hresult() == NOERROR && is_array($companyList)) { // multi company setup, get all users from all companies foreach($companyList as $companyName => $companyData) { $userList = array_merge($userList, mapi_zarafa_getuserlist($store, $companyData["companyid"])); } } else { // single company setup, get list of all zarafa users $userList = mapi_zarafa_getuserlist($store); }
if(count($userList) <= 0) { exit("Unable to get user list\n"); }
foreach($userList as $userName => $userData) { // check for valid users if($userName == "SYSTEM") { continue; }
print "Searching recurring items for user - ". $userName . "\n\n";
$result = findRecurringItems($session, $store, $userName);
if($result) { print $result ." recurring item are fixed for user - " . $userName . "\n\n"; } else { print "No defective recurring items found for user - " . $userName . "\n\n"; } } } else if(strcasecmp($argv[1], "-u") == 0) { // only clear properties for selected users if($argc == 2) { exit("No user specified\n\n" . $USAGEMESSAGE); }
for($index = 2; $index < $argc; $index++) { // start with argv[2] print "Searching recurring items for user - ". $argv[$index] . "\n\n";
$result = findRecurringItems($session, $store, $argv[$index]); if($result) { print $result ." recurring item are fixed for user - " . $argv[$index] . "\n\n"; } else { print "No defective recurring items found for user - " . $argv[$index] . "\n\n"; } } } else { exit("Unknown option specified\n\n" . $USAGEMESSAGE); }
/**************** Internal Functions ******************/
/**
* findRecurringItems * * Finds recurring items between 25 Oct to 31 Oct for specified username and store * @param session mapi session * @param resource store mapi store of given username * @param string userName username of user to search for. * @returns boolean/number false if no recurring item is fixed else no. of recurring items fixed */
function findRecurringItems($session, $store, $userName) { $result = false; $itemCount = 0;
// create entryid of user's store $userStoreEntryId = mapi_msgstore_createentryid($store, $userName); if(!$userStoreEntryId) { print "\tError in creating entryid for user's store - " . $userName . "\n"; return false; }
// open user's store $userStore = mapi_openmsgstore($session, $userStoreEntryId); if(!$userStore) { print "\tError in opening user's store - " . $userName . "\n"; return false; }
// get user's root store $userRootStore = mapi_msgstore_openentry($userStore, null); $userRootStoreProps = mapi_getprops($userRootStore, array(PR_IPM_APPOINTMENT_ENTRYID));
// Open the user's calendar Folder $userCalendar = mapi_msgstore_openentry($userStore, $userRootStoreProps[PR_IPM_APPOINTMENT_ENTRYID]);
// get rows $calContentTable = mapi_folder_getcontentstable($userCalendar);
// Restriction to find all recurrings items $res = Array(RES_AND, Array( Array(RES_PROPERTY, Array(RELOP => RELOP_EQ, ULPROPTAG => $GLOBALS['proptags']['recurring'], VALUE => true // Item should be recurring ) ), Array(RES_PROPERTY, Array(RELOP => RELOP_GE, ULPROPTAG => $GLOBALS['proptags']['commonstart'], VALUE => gmmktime(0, 0, 0, 10, 25, 2010) ) ), Array(RES_PROPERTY, Array(RELOP => RELOP_LE, ULPROPTAG => $GLOBALS['proptags']['commonstart'], VALUE => gmmktime(0, 0, 0, 11, 1, 2010) ) ) ) );
$rows = mapi_table_queryallrows($calContentTable, $GLOBALS['proptags'], $res);
// Now loop through each recurring item and find which one is falling in 25 - 31 OCT daterange. foreach ($rows as $row) { $result = processRecurringItem($userStore, $row); if ($result) $itemCount++; }
return $itemCount ? $itemCount : $result; }
/**
* processRecurringItem * * Checks if given message is broken, if broken then fixes borken properties on message as well as in recurrence blob * @param resource store mapi store of given username * @param array itemProps message properties of recurring item * @return boolean returns true if found broken and fixed else false. */
function processRecurringItem($userStore, $itemProps) { print "\tProcessing item - '". $itemProps[PR_SUBJECT] ."' \n"; // Open message $message = mapi_msgstore_openentry($userStore, $itemProps[PR_ENTRYID]);
$recurr = new Recurrence($userStore, $message); $tz = $recurr->parseTimezone($itemProps[$GLOBALS['proptags']['timezone_data']]);
// Calculate 'ClipStart' based on 'CommonStart' $localCommonStart = $recurr->fromGMT($tz, $itemProps[$GLOBALS['proptags']['commonstart']]); //Get commonStart in LOCAL time $clipStart = $recurr->dayStartOf($localCommonStart); //Get start of day of localtime $clipStart = $recurr->toGMT($tz, $clipStart); //Convert back to GMT time
if ($clipStart != $itemProps[$GLOBALS['proptags']['clipstart']]) {
print "\t\tRecurring item - '". $itemProps[PR_SUBJECT] ."' found broken.\n\t\tFixing - '". $itemProps[PR_SUBJECT] ."'\n";
//This recurring item is broken
$props = Array(); $props[$GLOBALS['proptags']['clipstart']] = $clipStart;
// Calculate 'StartRecurDate' and 'StartRecurTime' $gmStartDate = $recurr->gmtime($localCommonStart); $props[$GLOBALS['proptags']['startrecurdate']] = ((intval($gmStartDate['tm_year'], 10)+1900) * 512) + ((intval($gmStartDate['tm_mon'], 10)+1) * 32) + intval($gmStartDate['tm_mday'], 10); $props[$GLOBALS['proptags']['startrecurtime']] = (intval($gmStartDate['tm_hour'], 10) * 4096) + (intval($gmStartDate['tm_min'], 10) * 64) + intval($gmStartDate['tm_sec'], 10);
// Calculate 'EndRecurDate' and 'EndRecurTime' $localCommonEnd = $recurr->fromGMT($tz, $itemProps[$GLOBALS['proptags']['commonend']]); $gmEndDate = $recurr->gmtime($localCommonEnd); $props[$GLOBALS['proptags']['endrecurdate']] = ((intval($gmEndDate['tm_year'], 10)+1900) * 512) + ((intval($gmEndDate['tm_mon'], 10)+1) * 32) + intval($gmEndDate['tm_mday'], 10); $props[$GLOBALS['proptags']['endrecurtime']] = (intval($gmEndDate['tm_hour'], 10) * 4096) + (intval($gmEndDate['tm_min'], 10) * 64) + intval($gmEndDate['tm_sec'], 10);
// Calculate Duration $duration = $localCommonEnd - $localCommonStart;
// Fix 'StartOcc' and 'EndOcc' in recurrence blob $recurr->recur['startocc'] = ($gmStartDate['tm_hour'] * 60) + ($gmStartDate['tm_min']); $recurr->recur['endocc'] = $recurr->recur['startocc'] + ($duration / 60);
// Save recurrence $recurr->saveRecurrence();
// Calculate 'ClipEnd' with the help of 'RecurEnd' and 'EndOcc' from recurr blob. if ($recurr->recur['term'] != 0x23) { // Do nothing if recurrence doesn' end $clipEnd = $recurr->recur['end'] + ($recurr->recur['endocc'] * 60); $clipEnd = $recurr->fromGMT($tz, $clipEnd); $clipEnd = $recurr->dayStartOf($clipEnd); $clipEnd = $recurr->toGMT($tz, $clipEnd);
$props[$GLOBALS['proptags']['clipend']] = $clipEnd; }
// Commit changes mapi_setprops($message, $props); mapi_savechanges($message);
print "\t\tRecurring item - '". $itemProps[PR_SUBJECT] ."' is now fixed.\n";
return true; }
print "\t\tRecurring item - '". $itemProps[PR_SUBJECT] ."' seems good do not need any processing.\n"; print "\n"; return false; } ?>