calendarimporter 2.1.0:
- ics sync is now implemented
This commit is contained in:
parent
38855391f0
commit
c387565a45
14
backend/README.txt
Normal file
14
backend/README.txt
Normal 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
1
backend/config.php
Normal 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
165
backend/functions.php
Normal 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
150
backend/sync.php
Normal 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";
|
||||||
|
}
|
||||||
|
?>
|
@ -1,6 +1,6 @@
|
|||||||
<project default="all">
|
<project default="all">
|
||||||
<!--############# CONFIGURE ALL PROPERTIES FOR THE REPLACER HERE ################-->
|
<!--############# CONFIGURE ALL PROPERTIES FOR THE REPLACER HERE ################-->
|
||||||
<property name="plugin_version" value="2.0.5"/>
|
<property name="plugin_version" value="2.1.0"/>
|
||||||
<!-- EOC -->
|
<!-- EOC -->
|
||||||
|
|
||||||
<property name="root-folder" value="${basedir}/../"/>
|
<property name="root-folder" value="${basedir}/../"/>
|
||||||
@ -97,6 +97,7 @@
|
|||||||
</zConcat-->
|
</zConcat-->
|
||||||
<concat destfile="${target-folder}/${plugin-folder}/js/${plugin-debugfile}">
|
<concat destfile="${target-folder}/${plugin-folder}/js/${plugin-debugfile}">
|
||||||
<fileset file="js/ABOUT.js" />
|
<fileset file="js/ABOUT.js" />
|
||||||
|
<fileset file="js/external/Ext.util.base64.js" />
|
||||||
<fileset file="js/data/timezones.js" />
|
<fileset file="js/data/timezones.js" />
|
||||||
<fileset file="js/plugin.calendarimporter.js" />
|
<fileset file="js/plugin.calendarimporter.js" />
|
||||||
<fileset file="js/data/ResponseHandler.js" />
|
<fileset file="js/data/ResponseHandler.js" />
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
calendarimporter 2.1.0:
|
||||||
|
- ics sync is now implemented
|
||||||
|
|
||||||
calendarimporter 2.0.5:
|
calendarimporter 2.0.5:
|
||||||
- added settings widget
|
- added settings widget
|
||||||
- compatible with webapp 1.5 and 1.6
|
- compatible with webapp 1.5 and 1.6
|
||||||
|
@ -63,4 +63,4 @@ Zarafa.plugins.calendarimporter.ABOUT = ""
|
|||||||
|
|
||||||
+ "<p>Licensed under the MIT License.</p>"
|
+ "<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
47
js/external/Ext.util.base64.js
vendored
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,8 +16,7 @@ Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget = Ext.extend(Zara
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @param {Object} config Configuration object
|
* @param {Object} config Configuration object
|
||||||
*/
|
*/
|
||||||
constructor : function(config)
|
constructor : function(config) {
|
||||||
{
|
|
||||||
config = config || {};
|
config = config || {};
|
||||||
|
|
||||||
var store = new Ext.data.JsonStore({
|
var store = new Ext.data.JsonStore({
|
||||||
@ -39,9 +38,8 @@ Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget = Ext.extend(Zara
|
|||||||
|
|
||||||
Ext.applyIf(config, {
|
Ext.applyIf(config, {
|
||||||
height : 400,
|
height : 400,
|
||||||
title : _('Calendar Sync settings - Comming soon'),
|
title : _('Calendar Sync settings'),
|
||||||
xtype : 'calendarimporter.settingscalsyncwidget',
|
xtype : 'calendarimporter.settingscalsyncwidget',
|
||||||
disabled : true,
|
|
||||||
layout : {
|
layout : {
|
||||||
// override from SettingsWidget
|
// override from SettingsWidget
|
||||||
type : 'fit'
|
type : 'fit'
|
||||||
@ -63,8 +61,7 @@ Zarafa.plugins.calendarimporter.settings.SettingsCalSyncWidget = Ext.extend(Zara
|
|||||||
* {@link Zarafa.settings.SettingsModel} into the UI of this category.
|
* {@link Zarafa.settings.SettingsModel} into the UI of this category.
|
||||||
* @param {Zarafa.settings.SettingsModel} settingsModel The settings to load
|
* @param {Zarafa.settings.SettingsModel} settingsModel The settings to load
|
||||||
*/
|
*/
|
||||||
update : function(settingsModel)
|
update : function(settingsModel) {
|
||||||
{
|
|
||||||
this.model = settingsModel;
|
this.model = settingsModel;
|
||||||
|
|
||||||
// Convert the signatures into Store data
|
// 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}.
|
* 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
|
* @param {Zarafa.settings.SettingsModel} settingsModel The settings to update
|
||||||
*/
|
*/
|
||||||
updateSettings : function(settingsModel)
|
updateSettings : function(settingsModel) {
|
||||||
{
|
|
||||||
settingsModel.beginEdit();
|
settingsModel.beginEdit();
|
||||||
|
|
||||||
// Start reading the Grid store and convert the contents back into
|
// Start reading the Grid store and convert the contents back into
|
||||||
|
@ -12,20 +12,18 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditContentPanel = Ext.e
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @param config Configuration structure
|
* @param config Configuration structure
|
||||||
*/
|
*/
|
||||||
constructor : function(config)
|
constructor : function(config) {
|
||||||
{
|
|
||||||
config = config || {};
|
config = config || {};
|
||||||
|
|
||||||
// Add in some standard configuration data.
|
// Add in some standard configuration data.
|
||||||
Ext.applyIf(config, {
|
Ext.applyIf(config, {
|
||||||
// Override from Ext.Component
|
// Override from Ext.Component
|
||||||
xtype : 'calendarimporter.calsynceditcontentpanel',
|
xtype : 'calendarimporter.calsynceditcontentpanel',
|
||||||
// Override from Ext.Component
|
|
||||||
layout : 'fit',
|
layout : 'fit',
|
||||||
model : true,
|
model : true,
|
||||||
autoSave : false,
|
autoSave : false,
|
||||||
width : 400,
|
width : 400,
|
||||||
height : 100,
|
height : 350,
|
||||||
title : _('ICAL Sync'),
|
title : _('ICAL Sync'),
|
||||||
items : [{
|
items : [{
|
||||||
xtype : 'calendarimporter.calsynceditpanel',
|
xtype : 'calendarimporter.calsynceditpanel',
|
||||||
|
@ -18,8 +18,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @param config Configuration structure
|
* @param config Configuration structure
|
||||||
*/
|
*/
|
||||||
constructor : function(config)
|
constructor : function(config) {
|
||||||
{
|
|
||||||
config = config || {};
|
config = config || {};
|
||||||
|
|
||||||
if(config.item)
|
if(config.item)
|
||||||
@ -28,7 +27,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
|
|||||||
Ext.applyIf(config, {
|
Ext.applyIf(config, {
|
||||||
// Override from Ext.Component
|
// Override from Ext.Component
|
||||||
xtype : 'calendarimporter.calsynceditpanel',
|
xtype : 'calendarimporter.calsynceditpanel',
|
||||||
labelAlign : 'left',
|
labelAlign : 'top',
|
||||||
defaultType: 'textfield',
|
defaultType: 'textfield',
|
||||||
items : this.createPanelItems(config),
|
items : this.createPanelItems(config),
|
||||||
buttons: [{
|
buttons: [{
|
||||||
@ -68,9 +67,9 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
|
|||||||
icsurl: this.icsurl.getValue(),
|
icsurl: this.icsurl.getValue(),
|
||||||
intervall: this.intervall.getValue(),
|
intervall: this.intervall.getValue(),
|
||||||
user: this.user.getValue(),
|
user: this.user.getValue(),
|
||||||
pass: this.pass.getValue(),
|
pass: Ext.util.base64.encode(this.pass.getValue()),
|
||||||
calendar: this.calendar.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('icsurl', this.icsurl.getValue());
|
||||||
this.currentItem.set('intervall', this.intervall.getValue());
|
this.currentItem.set('intervall', this.intervall.getValue());
|
||||||
this.currentItem.set('user', this.user.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.currentItem.set('calendar', this.calendar.getValue());
|
||||||
}
|
}
|
||||||
this.dialog.close();
|
this.dialog.close();
|
||||||
@ -109,7 +108,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
|
|||||||
icsurl = config.item.get('icsurl');
|
icsurl = config.item.get('icsurl');
|
||||||
intervall = config.item.get('intervall');
|
intervall = config.item.get('intervall');
|
||||||
user = config.item.get('user');
|
user = config.item.get('user');
|
||||||
pass = config.item.get('pass');
|
pass = Ext.util.base64.decode(config.item.get('pass'));
|
||||||
calendar = config.item.get('calendar');
|
calendar = config.item.get('calendar');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,15 +144,14 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
|
|||||||
xtype: 'fieldset',
|
xtype: 'fieldset',
|
||||||
title: _('ICAL Information'),
|
title: _('ICAL Information'),
|
||||||
defaultType: 'textfield',
|
defaultType: 'textfield',
|
||||||
layout: 'anchor',
|
layout: 'form',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
defaults: {
|
defaults: {
|
||||||
anchor: '100%',
|
anchor: '100%',
|
||||||
flex: 1,
|
flex: 1
|
||||||
labelWidth: 120
|
|
||||||
},
|
},
|
||||||
items: [{
|
items: [{
|
||||||
fieldLabel: _('ICS Url'),
|
fieldLabel: 'ICS Url',
|
||||||
name: 'icsurl',
|
name: 'icsurl',
|
||||||
ref: '../icsurl',
|
ref: '../icsurl',
|
||||||
value: icsurl,
|
value: icsurl,
|
||||||
@ -176,7 +174,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
xtype:'numberfield',
|
xtype:'numberfield',
|
||||||
fieldLabel: _('Sync Intervall'),
|
fieldLabel: _('Sync Intervall (minutes)'),
|
||||||
name: 'intervall',
|
name: 'intervall',
|
||||||
ref: '../intervall',
|
ref: '../intervall',
|
||||||
value: intervall,
|
value: intervall,
|
||||||
@ -187,8 +185,7 @@ Zarafa.plugins.calendarimporter.settings.dialogs.CalSyncEditPanel = Ext.extend(E
|
|||||||
xtype: 'fieldset',
|
xtype: 'fieldset',
|
||||||
title: _('Authentication (optional)'),
|
title: _('Authentication (optional)'),
|
||||||
defaultType: 'textfield',
|
defaultType: 'textfield',
|
||||||
labelWidth: 120,
|
layout: 'form',
|
||||||
layout: 'anchor',
|
|
||||||
defaults: {
|
defaults: {
|
||||||
anchor: '100%'
|
anchor: '100%'
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,7 @@ Zarafa.plugins.calendarimporter.settings.ui.CalSyncPanel = Ext.extend(Ext.Panel,
|
|||||||
{
|
{
|
||||||
return [{
|
return [{
|
||||||
xtype : 'displayfield',
|
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'
|
fieldClass : 'x-form-display-field'
|
||||||
}, {
|
}, {
|
||||||
xtype : 'container',
|
xtype : 'container',
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
<clientfile load="debug">js/calendarimporter-debug.js</clientfile>
|
<clientfile load="debug">js/calendarimporter-debug.js</clientfile>
|
||||||
|
|
||||||
<clientfile load="source">js/data/timezones.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/plugin.calendarimporter.js</clientfile>
|
||||||
<clientfile load="source">js/data/ResponseHandler.js</clientfile>
|
<clientfile load="source">js/data/ResponseHandler.js</clientfile>
|
||||||
<clientfile load="source">js/dialogs/ImportContentPanel.js</clientfile>
|
<clientfile load="source">js/dialogs/ImportContentPanel.js</clientfile>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* download.php, zarafa calender to ics im/exporter
|
* download.php, zarafa calender to ics im/exporter
|
||||||
*
|
*
|
||||||
* Author: Christoph Haas <christoph.h@sprinternet.at>
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* http://code.google.com/p/ics-parser/
|
* http://code.google.com/p/ics-parser/
|
||||||
*
|
*
|
||||||
* Author: Martin Thoma , Christoph Haas <christoph.h@sprinternet.at>
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?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>
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -1,5 +1,25 @@
|
|||||||
<?php
|
<?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
|
* calendarimporter Plugin
|
||||||
*
|
*
|
||||||
* With this plugin you can import a ics file to your zarafa calendar
|
* With this plugin you can import a ics file to your zarafa calendar
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* upload.php, zarafa calender to ics exporter
|
* upload.php, zarafa calender to ics exporter
|
||||||
*
|
*
|
||||||
* Author: Christoph Haas <christoph.h@sprinternet.at>
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
77
test.php
77
test.php
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
Loading…
Reference in New Issue
Block a user