ActiveSync: added getDatabases support for fetching folder list

A new method, findCollections, fetches the folder list from the server and
creates two maps:

m_collections - store all the information about each collection (folder),
indexed by server collection ID

m_folderPaths - map full folder paths to collection IDs

getDatabases uses this data to returns the folder path, collection ID and a
flag indicating if the folder is the default for that type.

Note 1: getDatabases always asks activesyncd to update the folder list from the
server in order to return up to date information.

Note 2: this depends on a new libeasclient routine:
eas_sync_handler_get_folder_list
This commit is contained in:
Graham R. Cobb 2013-02-04 22:24:58 +00:00 committed by Patrick Ohly
parent d8ca8b64cf
commit 5920bf59b3
2 changed files with 148 additions and 2 deletions

View File

@ -32,6 +32,7 @@
#include <errno.h>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptors.hpp>
/* #include <eas-connection-errors.h> */
#include <syncevo/declarations.h>
@ -39,6 +40,7 @@ SE_BEGIN_CXX
void EASItemUnref(EasItemInfo *info) { g_object_unref(&info->parent_instance); }
void GStringUnref(char *str) { g_free(str); }
void EASFolderUnref(EasFolder *f) { g_object_unref(&f->parent_instance); }
void ActiveSyncSource::enableServerMode()
{
@ -50,11 +52,125 @@ bool ActiveSyncSource::serverModeEnabled() const
return m_operations.m_loadAdminData;
}
/* Recursively work out full path name */
std::string ActiveSyncSource::Collection::fullPath() {
if (!pathFound) {
if (parentId == "0") {
pathName = name;
} else {
pathName = source->m_collections[parentId].fullPath() + "/" + name;
}
pathFound = true;
}
return pathName;
}
void ActiveSyncSource::findCollections(const std::string account, const bool force_update)
{
GErrorCXX gerror;
EasSyncHandler *handler;
EASFoldersCXX folders;
if (!m_collections.empty()) {
if (!force_update) return;
m_collections.clear();
m_folderPaths.clear();
}
/* Fetch the folders */
handler = eas_sync_handler_new(account.c_str());
if (!handler) throwError("findCollections cannot allocate sync handler");
if (!eas_sync_handler_get_folder_list (handler,
force_update,
folders,
NULL,
gerror)) {
g_object_unref(handler);
gerror.throwError("fetching folder list");
}
g_object_unref(handler);
/* Save the Collections */
BOOST_FOREACH(EasFolder *folder, folders) {
m_collections[folder->folder_id].collectionId = folder->folder_id;
m_collections[folder->folder_id].name = folder->display_name;
m_collections[folder->folder_id].parentId = folder->parent_id;
m_collections[folder->folder_id].type = folder->type;
m_collections[folder->folder_id].source = this;
}
/* Save the full paths */
BOOST_FOREACH(std::string id, m_collections | boost::adaptors::map_keys) {
m_folderPaths[m_collections[id].fullPath()] = id;
}
}
int ActiveSyncSource::Collection::getFolderType () {
switch (type) {
case EAS_FOLDER_TYPE_DEFAULT_INBOX:
case EAS_FOLDER_TYPE_DEFAULT_DRAFTS:
case EAS_FOLDER_TYPE_DEFAULT_DELETED_ITEMS:
case EAS_FOLDER_TYPE_DEFAULT_SENT_ITEMS:
case EAS_FOLDER_TYPE_DEFAULT_OUTBOX:
case EAS_FOLDER_TYPE_USER_CREATED_MAIL:
return EAS_ITEM_MAIL;
case EAS_FOLDER_TYPE_DEFAULT_TASKS:
case EAS_FOLDER_TYPE_USER_CREATED_TASKS:
return EAS_ITEM_TODO;
case EAS_FOLDER_TYPE_DEFAULT_CALENDAR:
case EAS_FOLDER_TYPE_USER_CREATED_CALENDAR:
return EAS_ITEM_CALENDAR;
case EAS_FOLDER_TYPE_DEFAULT_CONTACTS:
case EAS_FOLDER_TYPE_USER_CREATED_CONTACTS:
return EAS_ITEM_CONTACT;
case EAS_FOLDER_TYPE_DEFAULT_NOTES:
case EAS_FOLDER_TYPE_USER_CREATED_NOTES:
//TODO: implement memos
case EAS_FOLDER_TYPE_DEFAULT_JOURNAL:
case EAS_FOLDER_TYPE_USER_CREATED_JOURNAL:
case EAS_FOLDER_TYPE_UNKNOWN:
case EAS_FOLDER_TYPE_RECIPIENT_CACHE:
default:
return -1;
}
}
bool ActiveSyncSource::Collection::collectionIsDefault () {
return type == EAS_FOLDER_TYPE_DEFAULT_INBOX ||
type == EAS_FOLDER_TYPE_DEFAULT_DRAFTS ||
type == EAS_FOLDER_TYPE_DEFAULT_DELETED_ITEMS ||
type == EAS_FOLDER_TYPE_DEFAULT_SENT_ITEMS ||
type == EAS_FOLDER_TYPE_DEFAULT_OUTBOX ||
type == EAS_FOLDER_TYPE_DEFAULT_TASKS ||
type == EAS_FOLDER_TYPE_DEFAULT_CALENDAR ||
type == EAS_FOLDER_TYPE_DEFAULT_CONTACTS ||
type == EAS_FOLDER_TYPE_DEFAULT_NOTES ||
type == EAS_FOLDER_TYPE_DEFAULT_JOURNAL;
}
ActiveSyncSource::Databases ActiveSyncSource::getDatabases()
{
Databases result;
// empty string always selects the default database
result.push_back(Database("", "", true));
// do a scan if username is set
std::string account = m_context->getSyncUsername();
if (!account.empty()) {
findCollections(account, true);
BOOST_FOREACH(Collection coll, m_collections | boost::adaptors::map_values) {
if (coll.getFolderType() == getEasType()) {
result.push_back(Database(coll.pathName, coll.collectionId, coll.collectionIsDefault()));
}
}
} else {
result.push_back(Database("to scan, specify --print-databases username=<account> backend=\""+getSourceType().m_backend+"\"",
""));
}
return result;
}

View File

@ -38,6 +38,7 @@
#include "libeassync.h"
#include <eas-item-info.h>
#include <eas-folder.h>
#include <syncevo/declarations.h>
SE_BEGIN_CXX
@ -179,6 +180,8 @@ class ActiveSyncSource :
void setStartSyncKey(const std::string &startSyncKey) { m_startSyncKey = startSyncKey; }
std::string getCurrentSyncKey() { return m_currentSyncKey; }
void setCurrentSyncKey(const std::string &currentSyncKey) { m_currentSyncKey = currentSyncKey; }
void findCollections(const std::string account, bool force_update);
std::string getCollectionPath(const std::string parentId, const std::string name);
boost::shared_ptr<ConfigNode> m_itemNode;
@ -212,6 +215,28 @@ class ActiveSyncSource :
* changes are made (if doing change tracking)
*/
std::map<std::string, std::string> m_items;
/**
* list of folders
*/
typedef struct Collection {
std::string collectionId;
std::string name;
std::string parentId;
std::string pathName;
unsigned type;
bool pathFound;
ActiveSyncSource *source;
Collection() {pathFound = false;}
int getFolderType();
bool collectionIsDefault();
std::string fullPath();
} collection;
std::map<std::string, Collection> m_collections; // Indexed by collectionID
std::map<std::string, std::string> m_folderPaths; // Maps pathName to collectionId
};
class ActiveSyncContactSource : public ActiveSyncSource
@ -263,6 +288,11 @@ typedef GListCXX<char, GSList, GStringUnref> EASIdsCXX;
/** non-copyable smart pointer to an EasItemInfo, unrefs when going out of scope */
typedef eptr<EasItemInfo, GObject> EASItemPtr;
void EASFolderUnref(EasFolder *f);
/** non-copyable list of EasFolder pointers, owned by list */
typedef GListCXX<EasFolder, GSList, EASFolderUnref> EASFoldersCXX;
SE_END_CXX
#endif // ENABLE_ACTIVESYNC