Skip to content

Commit

Permalink
Merge branch 'master' into nag_4_2
Browse files Browse the repository at this point in the history
  • Loading branch information
mrubinsk committed Nov 5, 2013
2 parents c4623f3 + 7a02ad1 commit fd1efb8
Show file tree
Hide file tree
Showing 66 changed files with 605 additions and 140 deletions.
8 changes: 8 additions & 0 deletions framework/ActiveSync/doc/Horde/ActiveSync/TODO
Expand Up @@ -19,3 +19,11 @@ BC BREAKING (i.e., Horde 6).
============================

- Move all non-specific constants to single class.

- Clean up the various foldertype constant messes. I.e., probably store
the Horde_ActiveSync::FOLDER_TYPE_* and Horde_ActiveSync::CLASS_* values
in the saved state instead of having to switch between them in various
places. (Some client commands are sent using the CLASS, some using the
FOLDER_TYPE).


Expand Up @@ -166,7 +166,8 @@ public function sendNextChange()
$change['id'],
$folder->parentid,
$folder->displayname,
$folder->_serverid);
$folder->_serverid,
$folder->type);
$this->folderChange($folder);
} else {
$this->_logger->err(sprintf(
Expand Down
13 changes: 9 additions & 4 deletions framework/ActiveSync/lib/Horde/ActiveSync/Connector/Importer.php
Expand Up @@ -301,12 +301,13 @@ public function importMessageMove(array $uids, $dst)
* @param string $uid The folder uid
* @param string $displayname The folder display name
* @param string $parent The parent folder id.
* @param integer $type The EAS Folder type. @since 2.9.0
*
* @return string|boolean The new serverid if successful, otherwise false.
* @return string The new serverid if successful.
*
* @todo Horde 6 - This should take and return a Horde_ActiveSync_Message_Folder object.
*/
public function importFolderChange($uid, $displayname, $parent = Horde_ActiveSync::FOLDER_ROOT)
public function importFolderChange($uid, $displayname, $parent = Horde_ActiveSync::FOLDER_ROOT, $type = null)
{
// TODO: BC HACK. For now, we need to convert the uid -> folderid.
$collections = $this->_as->getCollectionsObject();
Expand All @@ -322,9 +323,13 @@ public function importFolderChange($uid, $displayname, $parent = Horde_ActiveSyn
}

try {
$new_uid = $this->_as->driver->changeFolder($folderid, $displayname, $parent_sid, $uid);
$new_uid = $this->_as->driver->changeFolder($folderid, $displayname, $parent_sid, $uid, $type);
} catch (Horde_Exception_PermissionDenied $e) {
$this->_logger->err($e->getMessage());
throw new Horde_ActiveSync_Exception($e->getMessage(), Horde_ActiveSync_Exception::UNSUPPORTED);
} catch (Horde_ActiveSync_Exception $e) {
return false;
$this->_logger->err($e->getMessage());
throw $e;
}

$change = array();
Expand Down
88 changes: 76 additions & 12 deletions framework/ActiveSync/lib/Horde/ActiveSync/Driver/Base.php
Expand Up @@ -85,6 +85,14 @@ abstract class Horde_ActiveSync_Driver_Base
*/
protected $_tempMap = array();

protected $_typeMap = array(
'F' => Horde_ActiveSync::CLASS_EMAIL,
'C' => Horde_ActiveSync::CLASS_CONTACTS,
'A' => Horde_ActiveSync::CLASS_CALENDAR,
'T' => Horde_ActiveSync::CLASS_TASKS,
'N' => Horde_ActiveSync::CLASS_NOTES
);

/**
* Const'r
*
Expand Down Expand Up @@ -350,29 +358,85 @@ static public function buildFbString($fb, Horde_Date $start, Horde_Date $end)
* serverid before, return the previously created uid, otherwise return
* a new one.
*
* @param string $imap The imap server's folder name E.g., INBOX
*
* @return string A UUID to be used by activesync to represent the folder.
* @param string $id The server's folder name E.g., INBOX
* @param string $type The folder type, a Horde_ActiveSync::FOLDER_TYPE_*
* constant. If empty, assumes FOLDER_TYPE_USER_MAIL
*
* @return string A unique identifier for the specified backend folder id.
* The first character indicates the foldertype as such:
* 'F' - Email
* 'C' - Contact
* 'A' - Appointment
* 'T' - Task
* 'N' - Note
* @since 2.4.0
*/
protected function _getFolderUidForBackendId($imap)
protected function _getFolderUidForBackendId($id, $type = null)
{
$map = $this->_state->getFolderUidToBackendIdMap();
if (!empty($map[$imap])) {
return $map[$imap];
} elseif (!empty($this->_tempMap[$imap])) {
return $this->_tempMap[$imap];
if (!empty($map[$id])) {
return $map[$id];
} elseif (!empty($this->_tempMap[$id])) {
return $this->_tempMap[$id];
}

// Convert TYPE to CLASS
$type = $this->_getClassFromType($type);
$rMap = array_flip($this->_typeMap);
$prefix = $rMap[$type];

// None found, generate a new UID.
$this->_tempMap[$imap] = sprintf('F%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$this->_tempMap[$id] = sprintf('%s%04x%04x', $prefix, mt_rand(0, 0xffff), mt_rand(0, 0xffff));
$this->_logger->info(sprintf(
'[%s] Creating new folder uuid for %s: %s',
getmypid(),
$imap,
$this->_tempMap[$imap]));
$id,
$this->_tempMap[$id]));

return $this->_tempMap[$id];
}

/**
* Convert a TYPE constant into it's associated CLASS constant.
*
* @param integer $type The TYPE.
*
* @return string The CLASS
*/
protected function _getClassFromType($type)
{
// @todo This is for BC. Assume we are asking for an email collection
// if we didn't pass a type. Remove in H6.
if (empty($type)) {
return Horde_ActiveSync::CLASS_EMAIL;
}

switch ($type) {
case Horde_ActiveSync::FOLDER_TYPE_APPOINTMENT:
case Horde_ActiveSync::FOLDER_TYPE_USER_APPOINTMENT:
return Horde_ActiveSync::CLASS_CALENDAR;

case Horde_ActiveSync::FOLDER_TYPE_CONTACT:
case Horde_ActiveSync::FOLDER_TYPE_USER_CONTACT:
return Horde_ActiveSync::CLASS_CONTACTS;

return $this->_tempMap[$imap];
case Horde_ActiveSync::FOLDER_TYPE_TASK:
case Horde_ActiveSync::FOLDER_TYPE_USER_TASK:
return Horde_ActiveSync::CLASS_TASKS;

case Horde_ActiveSync::FOLDER_TYPE_NOTE:
case Horde_ActiveSync::FOLDER_TYPE_USER_NOTE:
return Horde_ActiveSync::CLASS_NOTES;

case Horde_ActiveSync::FOLDER_TYPE_INBOX:
case Horde_ActiveSync::FOLDER_TYPE_DRAFTS:
case Horde_ActiveSync::FOLDER_TYPE_WASTEBASKET:
case Horde_ActiveSync::FOLDER_TYPE_SENTMAIL:
case Horde_ActiveSync::FOLDER_TYPE_OUTBOX:
case Horde_ActiveSync::FOLDER_TYPE_USER_MAIL:
return Horde_ActiveSync::CLASS_EMAIL;

}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion framework/ActiveSync/lib/Horde/ActiveSync/Driver/Mock.php
Expand Up @@ -233,7 +233,7 @@ protected function _getMailFolders()
}
}

protected function _getFolderUidForBackendId($sid)
protected function _getFolderUidForBackendId($sid, $type = null)
{
switch ($sid) {
case 'INBOX':
Expand Down
7 changes: 7 additions & 0 deletions framework/ActiveSync/lib/Horde/ActiveSync/Exception.php
Expand Up @@ -29,4 +29,11 @@
*/
class Horde_ActiveSync_Exception extends Horde_Exception_Wrapped
{
/** Error codes **/

// Defauld, unspecified.
const UNSPECIFIED = 0;

// Unsupported action was attempted.
const UNSUPPORTED = 3;
}
2 changes: 1 addition & 1 deletion framework/ActiveSync/lib/Horde/ActiveSync/Folder/Imap.php
Expand Up @@ -377,7 +377,7 @@ public function serialize()
* @throws Horde_ActiveSync_Exception_StaleState
*/
public function unserialize($data)
{ $data = json_decode($data, true, 512, JSON_BIGINT_AS_STRING);
{ $data = json_decode($data, true);
if (!is_array($data) || empty($data['v']) || $data['v'] != self::VERSION) {
throw new Horde_ActiveSync_Exception_StaleState('Cache version change');
}
Expand Down
41 changes: 26 additions & 15 deletions framework/ActiveSync/lib/Horde/ActiveSync/Request/FolderCreate.php
Expand Up @@ -134,8 +134,15 @@ protected function _handle()
$importer = $this->_activeSync->getImporter();
$importer->init($this->_state);
if (!$delete) {
if (!$serverid = $importer->importFolderChange($serverid, $displayname, $parentid)) {
$status = self::STATUS_ERROR;
try {
$serverid = $importer->importFolderChange($serverid, $displayname, $parentid, $type);
} catch (Horde_ActiveSync_Exception $e) {
$this->_logger->err($e->getMessage());
if ($e->getCode() == Horde_ActiveSync_Exception::UNSUPPORTED) {
$status = Horde_ActiveSync_Status::UNEXPECTED_ITEM_CLASS;
} else {
$status = self::STATUS_ERROR;
}
}
} else {
try {
Expand All @@ -151,27 +158,31 @@ protected function _handle()
// @TODO: Horde 6 - pass a H_AS_Message_Folder object to the importFolderChange()
// method so we can delegate the _serverid creation to the backend like
// it should be.
$folder = $this->_activeSync->messageFactory('Folder');
$folder->serverid = $serverid;
$folder->displayname = $displayname;
$folder->type = $type;
$folder->_serverid = $displayname;
$collections->updateFolderInHierarchy($folder);
$collections->save();
if ($status == self::STATUS_SUCCESS) {
$folder = $this->_activeSync->messageFactory('Folder');
$folder->serverid = $serverid;
$folder->displayname = $displayname;
$folder->type = $type;
$folder->_serverid = $displayname;
$collections->updateFolderInHierarchy($folder);
$collections->save();
}

$this->_encoder->startTag(self::FOLDERCREATE);

$this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_STATUS);
$this->_encoder->content($status);
$this->_encoder->endTag();

$this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_SYNCKEY);
$this->_encoder->content($newsynckey);
$this->_encoder->endTag();
if ($status == self::STATUS_SUCCESS) {
$this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_SYNCKEY);
$this->_encoder->content($newsynckey);
$this->_encoder->endTag();

$this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_SERVERENTRYID);
$this->_encoder->content($serverid);
$this->_encoder->endTag();
$this->_encoder->startTag(Horde_ActiveSync::FOLDERHIERARCHY_SERVERENTRYID);
$this->_encoder->content($serverid);
$this->_encoder->endTag();
}

$this->_encoder->endTag();
} elseif ($update) {
Expand Down
2 changes: 1 addition & 1 deletion framework/ActiveSync/lib/Horde/ActiveSync/State/Base.php
Expand Up @@ -416,7 +416,7 @@ public function getChanges(array $options = array())

// Get the current syncStamp from the backend.
$this->_thisSyncStamp = $this->_backend->getSyncStamp(
empty($this->_collection['id']) ? null : $this->_collection['id'],
empty($this->_collection['serverid']) ? null : $this->_collection['serverid'],
$this->_lastSyncStamp);
if ($this->_thisSyncStamp === false) {
throw new Horde_ActiveSync_Exception_StaleState(
Expand Down
5 changes: 3 additions & 2 deletions framework/ActiveSync/lib/Horde/ActiveSync/State/Mongo.php
Expand Up @@ -486,7 +486,8 @@ public function updateState(
$value['id'],
(empty($value['parent']) ? '0' : $value['parent']),
$folder->displayname,
$folder->_serverid);
$folder->_serverid,
$folder->type);
$this->_folder[] = $stat;
$this->_folder = array_values($this->_folder);
}
Expand Down Expand Up @@ -1341,7 +1342,7 @@ protected function _getMailMapChanges(array $changes)
continue 2;
} elseif ($change['type'] == Horde_ActiveSync::CHANGE_TYPE_DELETE) {
$results[$row['message_uid']][$change['type']] =
!is_null($row['sync_deleted']) && $row['sync_deleted'] == $change['flags']['deleted'];
!is_null($row['sync_deleted']) && $row['sync_deleted'] == true;
continue 2;
}
}
Expand Down
7 changes: 4 additions & 3 deletions framework/ActiveSync/lib/Horde/ActiveSync/State/Sql.php
Expand Up @@ -494,7 +494,8 @@ public function updateState(
$value['id'],
(empty($value['parent']) ? '0' : $value['parent']),
$folder->displayname,
$folder->_serverid);
$folder->_serverid,
$folder->type);
$this->_folder[] = $stat;
$this->_folder = array_values($this->_folder);
}
Expand Down Expand Up @@ -1193,7 +1194,7 @@ protected function _havePIMChanges()
/**
* Return all available mailMap changes for the current folder.
*
* @param array $changes The chagnes array
* @param array $changes The changes array
*
* @return array An array of hashes, each in the form of
* {uid} => array(
Expand Down Expand Up @@ -1236,7 +1237,7 @@ protected function _getMailMapChanges(array $changes)
continue 2;
} elseif ($change['type'] == Horde_ActiveSync::CHANGE_TYPE_DELETE) {
$results[$row['message_uid']][$change['type']] =
!is_null($row['sync_deleted']) && $row['sync_deleted'] == $change['flags']['deleted'];
!is_null($row['sync_deleted']) && $row['sync_deleted'] == true;
continue 2;
}
}
Expand Down
8 changes: 6 additions & 2 deletions framework/ActiveSync/lib/Horde/ActiveSync/SyncCache.php
Expand Up @@ -287,8 +287,12 @@ public function setPingableCollection($id)
*/
public function removePingableCollection($id)
{
if (empty($this->_data['collections'][$id])) {
throw new InvalidArgumentException('Collection does not exist');
if (empty($this->_data['collections'][$id])) {
$this->_logger->warn(sprintf(
'[%s] Collection %s was asked to be removed from PINGABLE but does not exist.',
$this->_procid,
$id));
return;
}
$this->_data['collections'][$id]['pingable'] = false;
$this->_markCollectionsDirty($id);
Expand Down
2 changes: 2 additions & 0 deletions framework/ActiveSync/package.xml
Expand Up @@ -21,6 +21,7 @@
</stability>
<license uri="http://www.horde.org/licenses/gpl">GPL-2.0</license>
<notes>
* [mjr] Changes to support multiple non-email collections of the same type.
* [mjr] Improvements to memory and database usage.
* [mjr] Add MongoDB state driver.
</notes>
Expand Down Expand Up @@ -1804,6 +1805,7 @@
<date>2013-10-22</date>
<license uri="http://www.horde.org/licenses/gpl">GPL-2.0</license>
<notes>
* [mjr] Changes to support multiple non-email collections of the same type.
* [mjr] Improvements to memory and database usage.
* [mjr] Add MongoDB state driver.
</notes>
Expand Down
6 changes: 5 additions & 1 deletion framework/Cache/lib/Horde/Cache/Storage/Mongo.php
Expand Up @@ -206,10 +206,14 @@ public function exists($key, $lifetime = 0)
*/
public function expire($key)
{
$okey = $key;
$key = $this->_getCid($key);

try {
$this->_db->remove(array(
self::CID => $this->_getCid($key)
self::CID => $key
));
$this->_logger->log(sprintf('Cache expire: %s (cache ID %s)', $okey, $key), 'DEBUG');
return true;
} catch (MongoException $e) {
return false;
Expand Down
11 changes: 11 additions & 0 deletions framework/Core/lib/Horde/Core/ActiveSync/Driver.php
Expand Up @@ -440,9 +440,20 @@ protected function _getFolderType($id)
* we already have.)
*
* @return string The new folder uid.
* @throws Horde_ActiveSync_Exception, Horde_Exception_PermissionDenied
*/
public function changeFolder($id, $displayname, $parent, $uid = null)
{
// Filter out non-email collections. Empty $parent is always an email
// collection.
if (!empty($parent) && ($parent == self::TASKS_FOLDER_UID ||
$parent == self::CONTACTS_FOLDER_UID ||
$parent == self::NOTES_FOLDER_UID ||
$parent == self::APPOINTMENTS_FOLDER_UID)) {

throw new Horde_Exception_PermissionDenied('Creating sub collection not supported in the ' . $parent . ' collection.');
}

if (!$id) {
try {
$this->_imap->createMailbox($displayname, $parent);
Expand Down
2 changes: 1 addition & 1 deletion framework/Core/lib/Horde/ErrorHandler.php
Expand Up @@ -60,7 +60,7 @@ static public function fatal($error)
* issues on the login page since we would otherwise need
* to do session token checking (which might not be
* available, so logout won't happen, etc...) */
if (array_key_exists($params, 'app')) {
if (array_key_exists('app', $params)) {
$registry->clearAuth();
}

Expand Down

0 comments on commit fd1efb8

Please sign in to comment.