You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
roundcubemail/plugins/push/lib/parser_notify.php

284 lines
7.3 KiB
PHP

<?php
/**
* Push aka Instant Updates
*
* @author Aleksander Machniak <alec@alec.pl>
*
* Copyright (C) 2010-2019 The Roundcube Dev Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
/**
* Parser of push notifications as of RFC5423
* This format is used e.g. by Cyrus IMAP
*/
class push_parser_notify
{
public function __construct()
{
// $this->service = push_service::get_instance();
}
public function parse($data)
{
if (!is_array($data) || empty($data) || !isset($data['event'])) {
return;
}
// Get event name (remove non-standard prefixes)
$event = str_replace('vnd.cmu.', '', $data['event']);
$data['event'] = $event;
// Parse data
$common = $this->commonProps($data);
$result = $this->{"event$event"}($data);
if (is_array($result)) {
return array_merge($common, $result);
}
}
public function __call($name, $arguments)
{
// Here we end up with unknown/undefined events
}
protected function commonProps($data)
{
$uri = $this->parseURI($data['uri']);
$result = array(
'event' => $data['event'],
'service' => $data['service'],
'uidset' => $data['uidset'],
'exists' => isset($data['messages']) ? intval($data['messages']) : null,
'folder_user' => $uri['user'] ?: $data['user'],
'folder_name' => $uri['folder'],
);
if (isset($data['oldMailboxID'])) {
$uri = $this->parseURI($data['oldMailboxID']);
$result['old_folder_user'] = $uri['user'] ?: $data['user'];
$result['old_folder_name'] = $uri['folder'];
}
if (isset($data['vnd.cmu.unseenMessages'])) {
$result['unseen'] = intval($data['vnd.cmu.unseenMessages']);
}
return $result;
}
protected function eventAclChange($data)
{
// Not implemented
}
protected function eventFlagsClear($data)
{
return array(
'flags' => explode(' ', $data['flagNames']),
);
}
protected function eventFlagsSet($data)
{
return array(
'flags' => explode(' ', $data['flagNames']),
);
}
protected function eventLogin($data)
{
// Not implemented
}
protected function eventLogout($data)
{
// Not implemented
}
protected function eventMailboxCreate($data)
{
return array();
}
protected function eventMailboxDelete($data)
{
return array();
}
protected function eventMailboxRename($data)
{
return array();
}
protected function eventMailboxSubscribe($data)
{
return array();
}
protected function eventMailboxUnSubscribe($data)
{
return array();
}
protected function eventMessageAppend($data)
{
return array();
}
protected function eventMessageCopy($data)
{
return array(
'old_uidset' => $data['vnd.cmu.oldUidset'],
);
}
protected function eventMessageExpire($data)
{
// Not implemented
}
protected function eventMessageExpunge($data)
{
return array();
}
protected function eventMessageMove($data)
{
// this is non-standard event used in Cyrus IMAP
return $this->eventMessageCopy($data);
}
protected function eventMessageNew($data)
{
// Add some props that might be useful if we want to display
// new message notification with message subject, etc.
// Maybe we should talk with newmail_notifier plugin
$headers = array();
// Note: messageHeaders is not defined in RFC5423, but used by Cyrus.
// Other properties does not include Subject header
foreach ((array) $data['messageHeaders'] as $uid => $h) {
$headers[$uid] = array(
'subject' => $h['Subject'],
'from' => $h['From'],
);
}
return array(
'headers' => $headers,
);
}
protected function eventMessageRead($data)
{
// This is equivalent of FlagsSet with \Seen flag
// so let's imitate it for simplicity
return array(
'event' => 'FlagsSet',
'flags' => array('\\Seen'),
);
}
protected function eventMessageTrash($data)
{
// This is equivalent of FlagsSet with \Deleted flag
// so let's imitate it for simplicity
return array(
'event' => 'FlagsSet',
'flags' => array('\\Deleted'),
);
}
protected function eventQuotaChange($data)
{
return array(
'quota' => $data['diskQuota'],
'used' => $data['diskUsed'],
'messages' => $data['maxMessages'],
);
}
protected function eventQuotaExceed($data)
{
// Not implemented
}
protected function eventQuotaWithin($data)
{
return $this->eventQuotaChange($data);
}
/**
* Parse imap folder URI to extract user and folder name
*/
protected function parseURI($uri)
{
$_uri = parse_url($uri);
list($path, $args) = explode(';', $_uri['path'], 2);
$path = ltrim($path, '/');
$params = array();
// Standard: "imap://test%40example.org@imap.example.org/INBOX";
if (!empty($_uri['user'])) {
$user = urldecode($_uri['user']);
$path = strlen($path) ? urldecode($path) : 'INBOX';
}
// (Old?) Cyrus IMAP: imap://imap.example.org/user/test.test/Sent%40example.org
else if (strpos($path, 'user/') === 0) {
$path = array_map('urldecode', explode('/', $path));
if (count($path) > 1) {
$last = count($path) - 1;
$user = $path[1];
if ($last > 1 && ($pos = strrpos($path[$last], '@'))) {
$user .= substr($path[$last], $pos);
$path[$last] = substr($path[$last], 0, $pos);
}
$path = implode('/', array_slice($path, 2));
if (!strlen($path)) {
$path = 'INBOX';
}
}
}
// E.g. for MailboxSubscribe the uri can be also just imap://imap.example.org/Folder
if (empty($user) && empty($path)) {
// invalid uri?
}
if (!empty($args)) {
foreach (explode(';', $args) as $arg) {
list($key, $val) = explode('=', $arg);
$params[urldecode($key)] = urldecode($val);
}
}
return array(
'user' => $user,
'folder' => $path,
'params' => $params,
);
}
}