calendarimporter 2.1.0:

- ics sync is now implemented
This commit is contained in:
Christoph Haas 2014-05-14 23:30:00 +00:00
parent 38855391f0
commit c387565a45
19 changed files with 430 additions and 114 deletions

14
backend/README.txt Normal file
View File

@ -0,0 +1,14 @@
Backend setup:
1. Create a Admin User in Zarafa:
zarafa-admin -c adminuser -e admin@domain.com -f "Calendar Sync Admin" -p topsecretpw -a 1
2. Edit the config.php to fit your needs.
3. Setup cron to run your script every 10 minutes (or whatever...)
4. If you get an error, make sure that the mapi module is loaded for php-cli:
* Add: /etc/php5/cli/conf.d/50-mapi.ini
* Content: extension=mapi.so
Never run the backend script as root!

1
backend/config.php Normal file
View File

@ -0,0 +1 @@
<?php // config options $ADMINUSERNAME = "admin"; $ADMINPASSWORD = "admin"; $SERVER = "file:///var/run/zarafa"; $CALDAVURL = "http://localhost:8080/ical/"; $TEMPDIR = "/tmp/"; ?>

165
backend/functions.php Normal file
View File

@ -0,0 +1,165 @@
<?php
/**
* functions.php, zarafa calender to ics im/exporter backend
*
* Author: Christoph Haas <christoph.h@sprinternet.at>
* Copyright (C) 2012-2014 Christoph Haas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* gets the data from a URL */
function curl_get_data($url, $username = NULL, $password = NULL) {
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
if($username != NULL && $password != NULL) {
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
}
$data = curl_exec($ch);
$http_status = intval(curl_getinfo($ch, CURLINFO_HTTP_CODE));
curl_close($ch);
if($http_status > 210 || $http_status < 200)
return NULL;
return $data;
}
/* gets all zarafa users */
function get_user_ics_list($userStore) {
// get settings
// first check if property exist and we can open that using mapi_openproperty
$storeProps = mapi_getprops($userStore, array(PR_EC_WEBACCESS_SETTINGS_JSON));
// Check if property exists, if it doesn not exist then we can continue with empty set of settings
if (isset($storeProps[PR_EC_WEBACCESS_SETTINGS_JSON]) || propIsError(PR_EC_WEBACCESS_SETTINGS_JSON, $storeProps) == MAPI_E_NOT_ENOUGH_MEMORY) {
// read the settings property
$stream = mapi_openproperty($userStore, PR_EC_WEBACCESS_SETTINGS_JSON, IID_IStream, 0, 0);
if ($stream == false) {
echo "Error opening settings property\n";
}
$settings_string = "";
$stat = mapi_stream_stat($stream);
mapi_stream_seek($stream, 0, STREAM_SEEK_SET);
for ($i = 0; $i < $stat['cb']; $i += 1024) {
$settings_string .= mapi_stream_read($stream, 1024);
}
if(empty($settings_string)) {
// property exists but without any content so ignore it and continue with
// empty set of settings
return;
}
$settings = json_decode($settings_string, true);
if (empty($settings) || empty($settings['settings'])) {
echo "Error retrieving existing settings\n";
}
$calcontext = $settings["settings"]["zarafa"]["v1"]["contexts"]["calendar"];
if(isset($calcontext["icssync"])) {
foreach($calcontext["icssync"] as $syncitem) {
echo "Found sync url: " . $syncitem["icsurl"] . " for calendar: " . $syncitem["calendar"] . "\n";
}
return $calcontext["icssync"];
}
return NULL;
}
}
/* updates the webapp settings */
function update_last_sync_date($userStore, $icsentry) {
// get settings
// first check if property exist and we can open that using mapi_openproperty
$storeProps = mapi_getprops($userStore, array(PR_EC_WEBACCESS_SETTINGS_JSON));
// Check if property exists, if it doesn not exist then we can continue with empty set of settings
if (isset($storeProps[PR_EC_WEBACCESS_SETTINGS_JSON]) || propIsError(PR_EC_WEBACCESS_SETTINGS_JSON, $storeProps) == MAPI_E_NOT_ENOUGH_MEMORY) {
// read the settings property
$stream = mapi_openpropertytostream($userStore, PR_EC_WEBACCESS_SETTINGS_JSON, MAPI_MODIFY);
if ($stream == false) {
echo "Error opening settings property\n";
}
$settings_string = "";
$stat = mapi_stream_stat($stream);
mapi_stream_seek($stream, 0, STREAM_SEEK_SET);
for ($i = 0; $i < $stat['cb']; $i += 1024) {
$settings_string .= mapi_stream_read($stream, 1024);
}
if(empty($settings_string)) {
// property exists but without any content so ignore it and continue with
// empty set of settings
return;
}
$settings = json_decode($settings_string, true);
if (empty($settings) || empty($settings['settings'])) {
echo "Error retrieving existing settings\n";
}
$settings["settings"]["zarafa"]["v1"]["contexts"]["calendar"]["icssync"][$icsentry]["lastsync"] = date('Y-m-d H:i:s');
$newsettings = json_encode($settings);
mapi_stream_setsize($stream, strlen($newsettings));
mapi_stream_seek($stream, 0, STREAM_SEEK_SET);
mapi_stream_write($stream, $newsettings);
$res = mapi_stream_commit ($stream);
return $res;
}
return false;
}
/* upload a file */
function upload_ics_to_caldav($filename, $caldavurl, $username, $calendarname, $authuser = NULL, $authpass = NULL) {
$url = $caldavurl . $username . "/" . rawurlencode($calendarname) . "/";
$post = array('file'=>'@'.$filename);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$fp = fopen($filename, 'r');
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize ($filename));
if($authuser != NULL && $authpass != NULL) {
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$authuser:$authpass");
}
$result=curl_exec($ch);
$http_status = intval(curl_getinfo($ch, CURLINFO_HTTP_CODE));
curl_close($ch);
echo "uploading file to: " . $url . " (" . $http_status . ")\n";
return $http_status;
}
?>

150
backend/sync.php Normal file
View File

@ -0,0 +1,150 @@
#!/usr/bin/php
<?php
/**
* sync.php, zarafa calender to ics im/exporter backend
*
* Author: Christoph Haas <christoph.h@sprinternet.at>
* Copyright (C) 2012-2014 Christoph Haas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
if(php_sapi_name() !== 'cli') {
die("Script must be run from commandline!");
}
/**
* Make sure that the zarafa mapi extension is enabled in cli mode:
* Add: /etc/php5/cli/conf.d/50-mapi.ini
* Content: extension=mapi.so
*/
// MAPI includes
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('config.php');
include('functions.php');
// log in to zarafa
$session = mapi_logon_zarafa($ADMINUSERNAME, $ADMINPASSWORD, $SERVER);
if($session === FALSE) {
exit("Logon failed with error " .mapi_last_hresult() . "\n");
}
// load all stores for the admin user
$storeTable = mapi_getmsgstorestable($session);
if($storeTable === FALSE) {
exit("Storetable could not be opened. Error " .mapi_last_hresult() . "\n");
}
$storesList = mapi_table_queryallrows($storeTable, array(PR_ENTRYID, PR_DEFAULT_STORE));
// get admin users default store
foreach ($storesList 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");
}
// get a userlist
$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");
}
// loop over all users
foreach($userList as $userName => $userData) {
// check for valid users
if($userName == "SYSTEM" ||$userName == $ADMINUSERNAME) {
continue;
}
echo "###Getting sync settings for user: " . $userName . "\n";
$userEntryId = mapi_msgstore_createentryid($store, $userName);
$userStore = mapi_openmsgstore($session, $userEntryId);
if(!$userStore) {
echo "Can't open user store\n";
continue;
}
$syncItems = get_user_ics_list($userStore);
if($syncItems != NULL && count($syncItems) > 0) {
foreach($syncItems as $syncItemName => $syncItem) {
//check update intervall
$lastUpdate = strtotime($syncItem["lastsync"]);
$updateIntervall = intval($syncItem["intervall"]) * 60; // we need seconds
$currenttime = time();
if(($lastUpdate + $updateIntervall) <= $currenttime) {
echo "Update intervall OK ($currenttime): " . ($lastUpdate + $updateIntervall) . "\n";
$tmpFilename = $TEMPDIR . uniqid($userName . $syncItem["calendar"], true) . ".ics";
$user = NULL;
$pass= NULL;
if($syncItem["user"] != NULL && !empty($syncItem["user"]))
$user = $syncItem["user"];
if($syncItem["pass"] != NULL && !empty($syncItem["pass"]))
$pass= base64_decode($syncItem["pass"]);
$icsData = curl_get_data($syncItem["icsurl"], $user, $pass);
if($icsData != NULL) {
file_put_contents($tmpFilename, $icsData);
echo "Got valid data for " . $syncItem["icsurl"] . " stored in " . $tmpFilename . "\n";
$result = upload_ics_to_caldav($tmpFilename, $CALDAVURL, $userName, $syncItem["calendar"], $ADMINUSERNAME, $ADMINPASSWORD);
if(intval($result) == 200) {
echo "Import completed: $result\n";
$result = update_last_sync_date($userStore, $syncItemName);
$res = $result ? "true":"false";
echo "Updated Zarafa settings: " . $res . "\n";
} else {
echo "Uploading failed: " . $result . "\n";
}
}
} else {
echo "Update intervall STOP ($currenttime): " . ($lastUpdate + $updateIntervall) . "\n";
}
}
}
echo "###Done sync for user: " . $userName . "\n\n";
}
?>

View File

@ -1,6 +1,6 @@
<project default="all">
<!--############# CONFIGURE ALL PROPERTIES FOR THE REPLACER HERE ################-->
<property name="plugin_version" value="2.0.5"/>
<property name="plugin_version" value="2.1.0"/>
<!-- EOC -->
<property name="root-folder" value="${basedir}/../"/>
@ -97,6 +97,7 @@
</zConcat-->
<concat destfile="${target-folder}/${plugin-folder}/js/${plugin-debugfile}">
<fileset file="js/ABOUT.js" />
<fileset file="js/external/Ext.util.base64.js" />
<fileset file="js/data/timezones.js" />
<fileset file="js/plugin.calendarimporter.js" />
<fileset file="js/data/ResponseHandler.js" />

View File

@ -1,3 +1,6 @@
calendarimporter 2.1.0:
- ics sync is now implemented
calendarimporter 2.0.5:
- added settings widget
- compatible with webapp 1.5 and 1.6

View File

@ -63,4 +63,4 @@ Zarafa.plugins.calendarimporter.ABOUT = ""
+ "<p>Licensed under the MIT License.</p>"
+ "<p>Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.</p>"
+ "<p>Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.</p>";

47
js/external/Ext.util.base64.js vendored Normal file
View File

@ -0,0 +1,47 @@
Ext.util.base64 = {
base64s : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
encode: function(decStr){
if (typeof btoa === 'function') {
return btoa(decStr);
}
var base64s = this.base64s;
var bits;
var dual;
var i = 0;
var encOut = "";
while(decStr.length >= i + 3){
bits = (decStr.charCodeAt(i++) & 0xff) <<16 | (decStr.charCodeAt(i++) & 0xff) <<8 | decStr.charCodeAt(i++) & 0xff;
encOut += base64s.charAt((bits & 0x00fc0000) >>18) + base64s.charAt((bits & 0x0003f000) >>12) + base64s.charAt((bits & 0x00000fc0) >> 6) + base64s.charAt((bits & 0x0000003f));
}
if(decStr.length -i > 0 && decStr.length -i < 3){
dual = Boolean(decStr.length -i -1);
bits = ((decStr.charCodeAt(i++) & 0xff) <<16) | (dual ? (decStr.charCodeAt(i) & 0xff) <<8 : 0);
encOut += base64s.charAt((bits & 0x00fc0000) >>18) + base64s.charAt((bits & 0x0003f000) >>12) + (dual ? base64s.charAt((bits & 0x00000fc0) >>6) : '=') + '=';
}
return(encOut);
},
decode: function(encStr){
if (typeof atob === 'function') {
return atob(encStr);
}
var base64s = this.base64s;
var bits;
var decOut = "";
var i = 0;
for(; i<encStr.length; i += 4){
bits = (base64s.indexOf(encStr.charAt(i)) & 0xff) <<18 | (base64s.indexOf(encStr.charAt(i +1)) & 0xff) <<12 | (base64s.indexOf(encStr.charAt(i +2)) & 0xff) << 6 | base64s.indexOf(encStr.charAt(i +3)) & 0xff;
decOut += String.fromCharCode((bits & 0xff0000) >>16, (bits & 0xff00) >>8, bits & 0xff);
}
if(encStr.charCodeAt(i -2) == 61){
return(decOut.substring(0, decOut.length -2));
}
else if(encStr.charCodeAt(i -1) == 61){
return(decOut.substring(0, decOut.length -1));
}
else {
return(decOut);
}
}
}

View File

@ -16,8 +16,7 @@ Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget = Ext.extend(Zara
* @constructor
* @param {Object} config Configuration object
*/
constructor : function(config)
{
constructor : function(config) {
config = config || {};
var store = new Ext.data.JsonStore({
@ -39,9 +38,8 @@ Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget = Ext.extend(Zara
Ext.applyIf(config, {
height : 400,
title : _('Calendar Sync settings - Comming soon'),
title : _('Calendar Sync settings'),
xtype : 'calendarimporter.settingscalsyncwidget',
disabled : true,
layout : {
// override from SettingsWidget
type : 'fit'
@ -63,8 +61,7 @@ Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget = Ext.extend(Zara
* {@link Zarafa.settings.SettingsModel} into the UI of this category.
* @param {Zarafa.settings.SettingsModel} settingsModel The settings to load
*/
update : function(settingsModel)
{
update : function(settingsModel) {
this.model = settingsModel;
// Convert the signatures into Store data
@ -85,8 +82,7 @@ Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget = Ext.extend(Zara
* This is used to update the settings from the UI into the {@link Zarafa.settings.SettingsModel settings model}.
* @param {Zarafa.settings.SettingsModel} settingsModel The settings to update
*/
updateSettings : function(settingsModel)
{
updateSettings : function(settingsModel) {
settingsModel.beginEdit();
// Start reading the Grid store and convert the contents back into
@ -111,4 +107,4 @@ Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget = Ext.extend(Zara
}
});
Ext.reg('calendarimporter.settingscalsyncwidget', Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget);
Ext.reg('calendarimporter.settingscalsyncwidget', Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget);

View File

@ -12,20 +12,18 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditContentPanel = Ext.e
* @constructor
* @param config Configuration structure
*/
constructor : function(config)
{
constructor : function(config) {
config = config || {};
// Add in some standard configuration data.
Ext.applyIf(config, {
// Override from Ext.Component
xtype : 'calendarimporter.calsynceditcontentpanel',
// Override from Ext.Component
layout : 'fit',
model : true,
autoSave : false,
width : 400,
height : 100,
height : 350,
title : _('ICAL Sync'),
items : [{
xtype : 'calendarimporter.calsynceditpanel',

View File

@ -18,8 +18,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
* @constructor
* @param config Configuration structure
*/
constructor : function(config)
{
constructor : function(config) {
config = config || {};
if(config.item)
@ -28,7 +27,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
Ext.applyIf(config, {
// Override from Ext.Component
xtype : 'calendarimporter.calsynceditpanel',
labelAlign : 'left',
labelAlign : 'top',
defaultType: 'textfield',
items : this.createPanelItems(config),
buttons: [{
@ -68,9 +67,9 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
icsurl: this.icsurl.getValue(),
intervall: this.intervall.getValue(),
user: this.user.getValue(),
pass: this.pass.getValue(),
pass: Ext.util.base64.encode(this.pass.getValue()),
calendar: this.calendar.getValue(),
lastsync: 0
lastsync: "never"
});
}
@ -81,7 +80,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
this.currentItem.set('icsurl', this.icsurl.getValue());
this.currentItem.set('intervall', this.intervall.getValue());
this.currentItem.set('user', this.user.getValue());
this.currentItem.set('pass', this.pass.getValue());
this.currentItem.set('pass', Ext.util.base64.encode(this.pass.getValue()));
this.currentItem.set('calendar', this.calendar.getValue());
}
this.dialog.close();
@ -109,7 +108,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
icsurl = config.item.get('icsurl');
intervall = config.item.get('intervall');
user = config.item.get('user');
pass = config.item.get('pass');
pass = Ext.util.base64.decode(config.item.get('pass'));
calendar = config.item.get('calendar');
}
@ -144,16 +143,15 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
return [{
xtype: 'fieldset',
title: _('ICAL Information'),
defaultType: 'textfield',
layout: 'anchor',
defaultType: 'textfield',
layout: 'form',
flex: 1,
defaults: {
anchor: '100%',
flex: 1,
labelWidth: 120
flex: 1
},
items: [{
fieldLabel: _('ICS Url'),
fieldLabel: 'ICS Url',
name: 'icsurl',
ref: '../icsurl',
value: icsurl,
@ -176,7 +174,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
},
{
xtype:'numberfield',
fieldLabel: _('Sync Intervall'),
fieldLabel: _('Sync Intervall (minutes)'),
name: 'intervall',
ref: '../intervall',
value: intervall,
@ -187,8 +185,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
xtype: 'fieldset',
title: _('Authentication (optional)'),
defaultType: 'textfield',
labelWidth: 120,
layout: 'anchor',
layout: 'form',
defaults: {
anchor: '100%'
},

View File

@ -45,7 +45,7 @@ Zarafa.plugins.calendarimporter.settings.ui.CalSyncPanel = Ext.extend(Ext.Panel,
{
return [{
xtype : 'displayfield',
value : _('Here you can enter .ics files that will be synchronised.'),
value : _('Setup calendars you want to subscribe to.'),
fieldClass : 'x-form-display-field'
}, {
xtype : 'container',

View File

@ -24,11 +24,12 @@
<clientfile load="debug">js/calendarimporter-debug.js</clientfile>
<clientfile load="source">js/data/timezones.js</clientfile>
<clientfile load="source">js/external/Ext.util.base64.js</clientfile>
<clientfile load="source">js/plugin.calendarimporter.js</clientfile>
<clientfile load="source">js/data/ResponseHandler.js</clientfile>
<clientfile load="source">js/dialogs/ImportContentPanel.js</clientfile>
<clientfile load="source">js/dialogs/ImportPanel.js</clientfile>
<clientfile load="source">js/dialogs/settings/SettingsWidget.js</clientfile>
<clientfile load="source">js/dialogs/settings/SettingsWidget.js</clientfile>
<clientfile load="source">js/dialogs/settings/SettingsCalSyncWidget.js</clientfile>
<clientfile load="source">js/dialogs/settings/ui/CalSyncGrid.js</clientfile>
<clientfile load="source">js/dialogs/settings/ui/CalSyncPanel.js</clientfile>

View File

@ -3,7 +3,7 @@
* download.php, zarafa calender to ics im/exporter
*
* Author: Christoph Haas <christoph.h@sprinternet.at>
* Copyright (C) 2012-2013 Christoph Haas
* Copyright (C) 2012-2014 Christoph Haas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -4,7 +4,7 @@
* http://code.google.com/p/ics-parser/
*
* Author: Martin Thoma , Christoph Haas <christoph.h@sprinternet.at>
* Copyright (C) 2012-2013 Christoph Haas
* Copyright (C) 2012-2014 Christoph Haas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -1,9 +1,9 @@
<?php
/**
* class.calendar.php, zarafa calender to ics im/exporter
* module.calendar.php, zarafa calender to ics im/exporter
*
* Author: Christoph Haas <christoph.h@sprinternet.at>
* Copyright (C) 2012-2013 Christoph Haas
* Copyright (C) 2012-2014 Christoph Haas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -1,5 +1,25 @@
<?php
/**
* plugin.calendarimporter.php, zarafa calender to ics im/exporter
*
* Author: Christoph Haas <christoph.h@sprinternet.at>
* Copyright (C) 2012-2014 Christoph Haas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* calendarimporter Plugin
*
* With this plugin you can import a ics file to your zarafa calendar

View File

@ -3,7 +3,7 @@
* upload.php, zarafa calender to ics exporter
*
* Author: Christoph Haas <christoph.h@sprinternet.at>
* Copyright (C) 2012-2013 Christoph Haas
* Copyright (C) 2012-2014 Christoph Haas
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -1,77 +0,0 @@
#!/usr/bin/php
<?php
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');
// $serverlocation is optional, default http://localhost:236/zarafa
$session = mapi_logon_zarafa("SYSTEM", "", "file:///var/run/zarafa");
if($session === FALSE) {
echo "Logon failed with error " .mapi_last_hresult() . "\n";
}
// load the default store
$userstore = null;
$stores = mapi_getmsgstorestable($session);
if($stores === FALSE) {
echo "Stores not opened with error " .mapi_last_hresult() . "\n";
}
$storeslist = mapi_table_queryallrows($stores, array(PR_ENTRYID, PR_DEFAULT_STORE));
foreach($storeslist as $row) {
if($row[PR_ENTRYID]){
if(isset($row[PR_DEFAULT_STORE]) && $row[PR_DEFAULT_STORE] == true) {
try {
$masterstore = mapi_openmsgstore($session, $row[PR_ENTRYID]);
$id = mapi_msgstore_createentryid($masterstore, "christoph");
$userstore = mapi_openmsgstore($session, $id);
} catch (MAPIException $e) {
echo "OpenMsgStore failed: " . $e->getCode();
return $e->getCode();
}
break;
}
}
}
// get settings
// first check if property exist and we can open that using mapi_openproperty
$storeProps = mapi_getprops($userstore, array(PR_EC_WEBACCESS_SETTINGS_JSON));
// Check if property exists, if it doesn not exist then we can continue with empty set of settings
if (isset($storeProps[PR_EC_WEBACCESS_SETTINGS_JSON]) || propIsError(PR_EC_WEBACCESS_SETTINGS_JSON, $storeProps) == MAPI_E_NOT_ENOUGH_MEMORY) {
// read the settings property
$stream = mapi_openproperty($userstore, PR_EC_WEBACCESS_SETTINGS_JSON, IID_IStream, 0, 0);
if ($stream == false) {
echo "Error opening settings property\n";
}
$settings_string = "";
$stat = mapi_stream_stat($stream);
mapi_stream_seek($stream, 0, STREAM_SEEK_SET);
for ($i = 0; $i < $stat['cb']; $i += 1024) {
$settings_string .= mapi_stream_read($stream, 1024);
}
if(empty($settings_string)) {
// property exists but without any content so ignore it and continue with
// empty set of settings
return;
}
$settings = json_decode($settings_string, true);
if (empty($settings) || empty($settings['settings'])) {
echo "Error retrieving existing settings\n";
}
$calcontext = $settings["settings"]["zarafa"]["v1"]["contexts"]["calendar"];
if(isset($calcontext["icssync"])) {
foreach($calcontext["icssync"] as $syncitem) {
echo $syncitem["icsurl"] . "<br/>";
}
} else {
echo "no sync items";
}
}
?>