Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117751715
kolab_zpush.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
12 KB
Referenced Files
None
Subscribers
None
kolab_zpush.php
View Options
<?php
/**
* Z-Push configuration utility for Kolab accounts
*
* @version 0.2
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2012, Kolab Systems AG <contact@kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class
kolab_zpush
extends
rcube_plugin
{
public
$task
=
'settings'
;
public
$urlbase
;
private
$rc
;
private
$ui
;
private
$cache
;
private
$devices
;
private
$folders
;
private
$folders_meta
;
private
$root_meta
;
const
ROOT_MAILBOX
=
'INBOX'
;
const
CTYPE_KEY
=
'/shared/vendor/kolab/folder-type'
;
const
ACTIVESYNC_KEY
=
'/private/vendor/kolab/activesync'
;
/**
* Plugin initialization.
*/
public
function
init
()
{
$this
->
rc
=
rcube
::
get_instance
();
$this
->
require_plugin
(
'jqueryui'
);
$this
->
add_texts
(
'localization/'
,
true
);
$this
->
include_script
(
'kolab_zpush.js'
);
$this
->
register_action
(
'plugin.zpushconfig'
,
array
(
$this
,
'config_view'
));
$this
->
register_action
(
'plugin.zpushjson'
,
array
(
$this
,
'json_command'
));
if
(
$this
->
rc
->
action
==
'plugin.zpushconfig'
)
{
$this
->
require_plugin
(
'libkolab'
);
}
}
/**
* Establish IMAP connection
*/
public
function
init_imap
()
{
$storage
=
$this
->
rc
->
get_storage
();
// @TODO: Metadata is already cached by rcube storage, get rid of cache here
$this
->
cache
=
$this
->
rc
->
get_cache
(
'zpush'
,
'db'
,
900
);
$this
->
cache
->
expunge
();
if
(
$meta
=
$storage
->
get_metadata
(
self
::
ROOT_MAILBOX
,
self
::
ACTIVESYNC_KEY
))
{
// clear cache if device config changed
if
((
$oldmeta
=
$this
->
cache
->
read
(
'devicemeta'
))
&&
$oldmeta
!=
$meta
)
$this
->
cache
->
remove
();
$this
->
root_meta
=
$this
->
unserialize_metadata
(
$meta
[
self
::
ROOT_MAILBOX
][
self
::
ACTIVESYNC_KEY
]);
$this
->
cache
->
remove
(
'devicemeta'
);
$this
->
cache
->
write
(
'devicemeta'
,
$meta
);
}
}
/**
* Handle JSON requests
*/
public
function
json_command
()
{
$storage
=
$this
->
rc
->
get_storage
();
$cmd
=
rcube_utils
::
get_input_value
(
'cmd'
,
rcube_utils
::
INPUT_GPC
);
$imei
=
rcube_utils
::
get_input_value
(
'id'
,
rcube_utils
::
INPUT_GPC
);
switch
(
$cmd
)
{
case
'load'
:
$result
=
array
();
$devices
=
$this
->
list_devices
();
if
(
$device
=
$devices
[
$imei
])
{
$result
[
'id'
]
=
$imei
;
$result
[
'devicealias'
]
=
$device
[
'ALIAS'
];
$result
[
'syncmode'
]
=
intval
(
$device
[
'MODE'
]);
$result
[
'laxpic'
]
=
intval
(
$device
[
'LAXPIC'
]);
$result
[
'subscribed'
]
=
array
();
foreach
(
$this
->
folders_meta
()
as
$folder
=>
$meta
)
{
if
(
$meta
[
$imei
][
'S'
])
$result
[
'subscribed'
][
$folder
]
=
intval
(
$meta
[
$imei
][
'S'
]);
}
$this
->
rc
->
output
->
command
(
'plugin.zpush_data_ready'
,
$result
);
}
else
{
$this
->
rc
->
output
->
show_message
(
$this
->
gettext
(
'devicenotfound'
),
'error'
);
}
break
;
case
'save'
:
$syncmode
=
intval
(
rcube_utils
::
get_input_value
(
'syncmode'
,
rcube_utils
::
INPUT_POST
));
$laxpic
=
intval
(
rcube_utils
::
get_input_value
(
'laxpic'
,
rcube_utils
::
INPUT_POST
));
$devicealias
=
rcube_utils
::
get_input_value
(
'devicealias'
,
rcube_utils
::
INPUT_POST
,
true
);
$subsciptions
=
rcube_utils
::
get_input_value
(
'subscribed'
,
rcube_utils
::
INPUT_POST
);
$devices
=
$this
->
list_devices
();
$err
=
false
;
if
(
$device
=
$devices
[
$imei
])
{
// update device config if changed
if
(
$devicealias
!=
$this
->
root_meta
[
'DEVICE'
][
$imei
][
'ALIAS'
]
||
$syncmode
!=
$this
->
root_meta
[
'DEVICE'
][
$imei
][
'MODE'
]
||
$laxpic
!=
$this
->
root_meta
[
'DEVICE'
][
$imei
][
'LAXPIC'
]
||
$subsciptions
[
self
::
ROOT_MAILBOX
]
!=
$this
->
root_meta
[
'FOLDER'
][
$imei
][
'S'
])
{
$this
->
root_meta
[
'DEVICE'
][
$imei
][
'MODE'
]
=
$syncmode
;
$this
->
root_meta
[
'DEVICE'
][
$imei
][
'ALIAS'
]
=
$devicealias
;
$this
->
root_meta
[
'DEVICE'
][
$imei
][
'LAXPIC'
]
=
$laxpic
;
$this
->
root_meta
[
'FOLDER'
][
$imei
][
'S'
]
=
intval
(
$subsciptions
[
self
::
ROOT_MAILBOX
]);
$err
=
!
$storage
->
set_metadata
(
self
::
ROOT_MAILBOX
,
array
(
self
::
ACTIVESYNC_KEY
=>
$this
->
serialize_metadata
(
$this
->
root_meta
)));
// update cached meta data
if
(!
$err
)
{
$this
->
cache
->
remove
(
'devicemeta'
);
$this
->
cache
->
write
(
'devicemeta'
,
$storage
->
get_metadata
(
self
::
ROOT_MAILBOX
,
self
::
ACTIVESYNC_KEY
));
}
}
// iterate over folders list and update metadata if necessary
foreach
(
$this
->
folders_meta
()
as
$folder
=>
$meta
)
{
// skip root folder (already handled above)
if
(
$folder
==
self
::
ROOT_MAILBOX
)
continue
;
if
(
$subsciptions
[
$folder
]
!=
$meta
[
$imei
][
'S'
])
{
$meta
[
$imei
][
'S'
]
=
intval
(
$subsciptions
[
$folder
]);
$this
->
folders_meta
[
$folder
]
=
$meta
;
unset
(
$meta
[
'TYPE'
]);
// read metadata first
$folderdata
=
$storage
->
get_metadata
(
$folder
,
array
(
self
::
ACTIVESYNC_KEY
));
if
(
$asyncdata
=
$folderdata
[
$folder
][
self
::
ACTIVESYNC_KEY
])
$metadata
=
$this
->
unserialize_metadata
(
$asyncdata
);
$metadata
[
'FOLDER'
]
=
$meta
;
$err
|=
!
$storage
->
set_metadata
(
$folder
,
array
(
self
::
ACTIVESYNC_KEY
=>
$this
->
serialize_metadata
(
$metadata
)));
}
}
// update cache
$this
->
cache
->
remove
(
'folders'
);
$this
->
cache
->
write
(
'folders'
,
$this
->
folders_meta
);
$this
->
rc
->
output
->
command
(
'plugin.zpush_save_complete'
,
array
(
'success'
=>
!
$err
,
'id'
=>
$imei
,
'devicealias'
=>
Q
(
$devicealias
)));
}
if
(
$err
)
$this
->
rc
->
output
->
show_message
(
$this
->
gettext
(
'savingerror'
),
'error'
);
else
$this
->
rc
->
output
->
show_message
(
$this
->
gettext
(
'successfullysaved'
),
'confirmation'
);
break
;
case
'delete'
:
$devices
=
$this
->
list_devices
();
if
(
$device
=
$devices
[
$imei
])
{
unset
(
$this
->
root_meta
[
'DEVICE'
][
$imei
],
$this
->
root_meta
[
'FOLDER'
][
$imei
]);
// update annotation and cached meta data
if
(
$success
=
$storage
->
set_metadata
(
self
::
ROOT_MAILBOX
,
array
(
self
::
ACTIVESYNC_KEY
=>
$this
->
serialize_metadata
(
$this
->
root_meta
))))
{
$this
->
cache
->
remove
(
'devicemeta'
);
$this
->
cache
->
write
(
'devicemeta'
,
$storage
->
get_metadata
(
self
::
ROOT_MAILBOX
,
self
::
ACTIVESYNC_KEY
));
// remove device annotation in every folder
foreach
(
$this
->
folders_meta
()
as
$folder
=>
$meta
)
{
// skip root folder (already handled above)
if
(
$folder
==
self
::
ROOT_MAILBOX
)
continue
;
if
(
isset
(
$meta
[
$imei
]))
{
$type
=
$meta
[
'TYPE'
];
// remember folder type
unset
(
$meta
[
$imei
],
$meta
[
'TYPE'
]);
// read metadata first and update FOLDER property
$folderdata
=
$storage
->
get_metadata
(
$folder
,
array
(
self
::
ACTIVESYNC_KEY
));
if
(
$asyncdata
=
$folderdata
[
$folder
][
self
::
ACTIVESYNC_KEY
])
$metadata
=
$this
->
unserialize_metadata
(
$asyncdata
);
$metadata
[
'FOLDER'
]
=
$meta
;
if
(
$storage
->
set_metadata
(
$folder
,
array
(
self
::
ACTIVESYNC_KEY
=>
$this
->
serialize_metadata
(
$metadata
))))
{
$this
->
folders_meta
[
$folder
]
=
$metadata
;
$this
->
folders_meta
[
$folder
][
'TYPE'
]
=
$type
;
}
}
}
// update cache
$this
->
cache
->
remove
(
'folders'
);
$this
->
cache
->
write
(
'folders'
,
$this
->
folders_meta
);
}
}
if
(
$success
)
{
$this
->
rc
->
output
->
show_message
(
$this
->
gettext
(
'successfullydeleted'
),
'confirmation'
);
$this
->
rc
->
output
->
redirect
(
array
(
'action'
=>
'plugin.zpushconfig'
));
// reload UI
}
else
$this
->
rc
->
output
->
show_message
(
$this
->
gettext
(
'savingerror'
),
'error'
);
break
;
}
$this
->
rc
->
output
->
send
();
}
/**
* Render main UI for device configuration
*/
public
function
config_view
()
{
require_once
$this
->
home
.
'/kolab_zpush_ui.php'
;
$storage
=
$this
->
rc
->
get_storage
();
// checks if IMAP server supports any of METADATA, ANNOTATEMORE, ANNOTATEMORE2
if
(!(
$storage
->
get_capability
(
'METADATA'
)
||
$storage
->
get_capability
(
'ANNOTATEMORE'
)
||
$storage
->
get_capability
(
'ANNOTATEMORE2'
)))
{
$this
->
rc
->
output
->
show_message
(
$this
->
gettext
(
'notsupported'
),
'error'
);
}
$this
->
ui
=
new
kolab_zpush_ui
(
$this
);
$this
->
register_handler
(
'plugin.devicelist'
,
array
(
$this
->
ui
,
'device_list'
));
$this
->
register_handler
(
'plugin.deviceconfigform'
,
array
(
$this
->
ui
,
'device_config_form'
));
$this
->
register_handler
(
'plugin.foldersubscriptions'
,
array
(
$this
->
ui
,
'folder_subscriptions'
));
$this
->
rc
->
output
->
set_env
(
'devicecount'
,
count
(
$this
->
list_devices
()));
$this
->
rc
->
output
->
send
(
'kolab_zpush.config'
);
}
/**
* List known devices
*
* @return array Device list as hash array
*/
public
function
list_devices
()
{
if
(!
isset
(
$this
->
devices
))
{
$this
->
init_imap
();
$this
->
devices
=
(
array
)
$this
->
root_meta
[
'DEVICE'
];
}
return
$this
->
devices
;
}
/**
* Get list of all folders available for sync
*
* @return array List of mailbox folders
*/
public
function
list_folders
()
{
if
(!
isset
(
$this
->
folders
))
{
// read cached folder meta data
if
(
$cached_folders
=
$this
->
cache
->
read
(
'folders'
))
{
$this
->
folders_meta
=
$cached_folders
;
$this
->
folders
=
array_keys
(
$this
->
folders_meta
);
}
// fetch folder data from server
else
{
$storage
=
$this
->
rc
->
get_storage
();
$this
->
folders
=
$storage
->
list_folders
();
foreach
(
$this
->
folders
as
$folder
)
{
$folderdata
=
$storage
->
get_metadata
(
$folder
,
array
(
self
::
ACTIVESYNC_KEY
,
self
::
CTYPE_KEY
));
$foldertype
=
explode
(
'.'
,
$folderdata
[
$folder
][
self
::
CTYPE_KEY
]);
if
(
$asyncdata
=
$folderdata
[
$folder
][
self
::
ACTIVESYNC_KEY
])
{
$metadata
=
$this
->
unserialize_metadata
(
$asyncdata
);
$this
->
folders_meta
[
$folder
]
=
$metadata
[
'FOLDER'
];
}
$this
->
folders_meta
[
$folder
][
'TYPE'
]
=
!
empty
(
$foldertype
[
0
])
?
$foldertype
[
0
]
:
'mail'
;
}
// cache it!
$this
->
cache
->
write
(
'folders'
,
$this
->
folders_meta
);
}
}
return
$this
->
folders
;
}
/**
* Getter for folder metadata
*
* @return array Hash array with meta data for each folder
*/
public
function
folders_meta
()
{
if
(!
isset
(
$this
->
folders_meta
))
$this
->
list_folders
();
return
$this
->
folders_meta
;
}
/**
* Helper method to decode saved IMAP metadata
*/
private
function
unserialize_metadata
(
$str
)
{
if
(!
empty
(
$str
))
return
@
json_decode
(
base64_decode
(
$str
),
true
);
return
null
;
}
/**
* Helper method to encode IMAP metadata for saving
*/
private
function
serialize_metadata
(
$data
)
{
if
(
is_array
(
$data
))
return
base64_encode
(
json_encode
(
$data
));
return
''
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, Apr 4, 3:23 AM (1 d, 15 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ae/d8/109961792ac14206ff54e241402c
Default Alt Text
kolab_zpush.php (12 KB)
Attached To
Mode
rRPK roundcubemail-plugins-kolab
Attached
Detach File
Event Timeline