Commit f94d33b0 authored by Sriram Karra's avatar Sriram Karra

Implement --op=create-folder command for all PIMDBs

parent 9eb9ac80
##
## Created : Tue Apr 10 15:55:20 IST 2012
## Last Modified : Wed Apr 11 19:14:56 IST 2012
## Last Modified : Fri Apr 13 14:59:20 IST 2012
##
## Copyright (C) 2012 Sriram Karra <karra.etc@gmail.com>
##
......@@ -29,6 +29,7 @@ except ImportError, e:
from sync import Sync
from state import Config
from gdata.client import BadAuthentication
from folder import Folder
from pimdb_gc import GCPIMDB
from pimdb_bb import BBPIMDB
......@@ -60,6 +61,7 @@ def setup_parser ():
p.add_argument('--op', action='store',
choices = ('list-folders',
'create-folder',
'del-folder',
'list-items',
'print-item',
......@@ -80,6 +82,9 @@ def setup_parser ():
p.add_argument('--remote-db', action='store', choices=('bb', 'gc', 'ol'),
help=('Specifies which remote db''s sync data to be ' +
'cleared with clear-sync-artifacts'))
p.add_argument('--store-id', action='store',
help=('Specifies ID of Outlook Message store. Useful with '
'certain operations like --create-folder'))
p.add_argument('--folder-name', action='store',
help='For folder operations specify the name of the '
'folder to operate on.')
......@@ -158,7 +163,8 @@ class Asynk:
def validate_and_snarf_uinps (self, uinps):
# Most of the validation is already done by argparse. This is where we
# will do some additional sanity checking and consistency enforcement,
# mutual exclusion and so forth.
# mutual exclusion and so forth. In addition to this, every command
# will do some parsing and validation itself.
# Let's start with the db flags
if uinps.db:
......@@ -184,6 +190,7 @@ class Asynk:
raise AsynkParserError('Only one of --folder-name or --folder-id '
'can be specified.')
self.set_store_id(uinps.store_id)
self.set_folder_name(uinps.folder_name)
self.set_folder_id(uinps.folder_id)
self.set_item_id(uinps.item_id)
......@@ -213,6 +220,30 @@ class Asynk:
self.get_db(db).list_folders()
logging.info('Listing all folders in PIMDB %s...done', db)
def create_folder (self):
## Let's start with some sanity checking of arguments
# We need to have a --folder-name flag specified
fname = self.get_folder_name()
if not fname:
raise AsynkParserError('--create-folder needs a folder name '
'through --folder-name')
# There should only be one DB specified
if self.get_db2():
raise AsynkParserError('Please specify only 1 db with --db '
'where new folder is to be created')
if not self.get_db1():
raise AsynkParserError('Please specify the PIMDB where new folder '
'is to be created, with --db option')
storeid = self.get_store_id()
db = self.get_db(self.get_db1())
db.new_folder(fname, Folder.CONTACT_t, storeid)
def del_folder (self):
logging.debug('%s; Not Implemented', 'del_folder')
......@@ -309,6 +340,12 @@ class Asynk:
def set_remote_db (self, val):
return self._set_att('remote_db', val)
def get_store_id (self):
return self._get_att('store_id')
def set_store_id (self, val):
return self._set_att('store_id', val)
def get_gcuser (self):
return self._get_att('gcuser')
......
##
## Created : Tue Mar 13 14:26:01 IST 2012
## Last Modified : Thu Apr 12 16:35:14 IST 2012
## Last Modified : Fri Apr 13 14:57:13 IST 2012
##
## Copyright (C) 2012 Sriram Karra <karra.etc@gmail.com>
##
......@@ -25,14 +25,14 @@ class Folder:
NOTE_t = PR_IPM_NOTE_ENTRYID = 0x36D30102
TASK_t = PR_IPM_TASK_ENTRYID = 0x36D40102
APPT_t = PR_IPM_APPOINTMENT_ENTRYID = 0x36D00102
UKNOWN_t = 0x0
UNKNOWN_t = 0x0
valid_types = [CONTACT_t, NOTE_t, TASK_t, APPT_t]
type_names = { CONTACT_t : 'contacts',
NOTE_t : 'notes',
TASK_t : 'tasks',
APPT_t : 'appts',
UKNOWN_t : 'other',
UNKNOWN_t : 'other',
}
def __init__ (self, db):
......
##
## Created : Wed May 18 13:16:17 IST 2011
## Last Modified : Thu Apr 12 16:41:38 IST 2012
## Last Modified : Fri Apr 13 14:56:36 IST 2012
##
## Copyright (C) 2011, 2012 Sriram Karra <karra.etc@gmail.com>
##
......@@ -34,6 +34,16 @@ class OLFolder(Folder):
__metaclass__ = ABCMeta
cclass_ftype_d = {'IPF.Contact' : Folder.CONTACT_t,
'IPF.Task' : Folder.TASK_t,
'IPF.StickyNote' : Folder.NOTE_t,
'IPF.Appointment' : Folder.APPT_t,
'IPF.Note' : Folder.UNKNOWN_t,
}
ftype_cclass_d = {}
for key, val in cclass_ftype_d.iteritems():
ftype_cclass_d.update({val : key})
def __init__ (self, db, entryid, name, fobj, msgstore):
Folder.__init__(self, db)
......@@ -321,17 +331,20 @@ class OLFolder(Folder):
(ttag, tval), (ntag, nval) = props
try:
d = {'IPF.Contact' : Folder.CONTACT_t,
'IPF.Task' : Folder.TASK_t,
'IPF.StickyNote' : Folder.NOTE_t,
'IPF.Appointment' : Folder.APPT_t,
}
tval = d[tval]
tval = self.get_ftype_from_cclass(tval)
except KeyError, e:
tval = Folder.UKNOWN_t
tval = Folder.UNKNOWN_t
return tval, f
@classmethod
def get_cclass_from_ftype (self, ftype):
return self.ftype_cclass_d[ftype]
@classmethod
def get_ftype_from_cclass (self, cclass):
return self.cclass_ftype_d[cclass]
class OLContactsFolder(OLFolder):
def __init__ (self, db, entryid, name, fobj, msgstore):
......
##
## Created : Sat Apr 07 18:52:19 IST 2012
## Last Modified : Wed Apr 11 19:07:28 IST 2012
## Last Modified : Fri Apr 13 15:46:20 IST 2012
##
## Copyright (C) 2012 by Sriram Karra <karra.etc@gmail.com>
##
......@@ -39,10 +39,19 @@ class BBPIMDB(PIMDB):
logging.info(' %2d; Name: %-32s ID: %s', 1, self.get_def_fn(),
None)
def new_folder (self, fname, type):
"""See the documentation in class PIMDB"""
def new_folder (self, fname, ftype=None, storeid=None):
"""See the documentation in class PIMDB.
raise NotImplementedError
fname should be a filename in this case.
"""
with open(fname, 'w') as bbf:
bbf.write(';; -*-coding: utf-8-emacs;-*-\n')
bbf.write(';;; file-format: 8\n')
bbf.write(';;; user-fields: \n')
bbf.close()
logging.info('Successfully Created BBDB file: %s', fname)
def del_folder (self, gid):
"""See the documentation in class PIMDB"""
......
##
## Created : Thu Jul 07 14:47:54 IST 2011
## Last Modified : Wed Apr 11 19:09:54 IST 2012
## Last Modified : Fri Apr 13 15:41:55 IST 2012
##
## Copyright (C) 2011, 2012 by Sriram Karra <karra.etc@gmail.com>
##
......@@ -56,7 +56,7 @@ class GCPIMDB(PIMDB):
return ret
def new_folder (self, fname, ftype=None):
def new_folder (self, fname, ftype=None, storeid=None):
if not ftype:
ftype = Folder.CONTACT_t
......
##
## Created : Wed May 18 13:16:17 IST 2011
## Last Modified : Fri Apr 13 14:06:46 IST 2012
## Last Modified : Fri Apr 13 15:38:48 IST 2012
##
## Copyright (C) 2011, 2012 Sriram Karra <karra.etc@gmail.com>
##
......@@ -171,6 +171,11 @@ class MessageStore:
self.name = name
return name
def get_root_folder_obj (self):
"""Return the root folder object of the current messages store."""
msgstore = self.get_obj()
return(msgstore.OpenEntry(None, None, MOD_FLAG))
def get_folders (self, ftype=None):
"""Return all the folders of specified type. ftype should be one of
the valid folder types. If none is specifiedfor ftype, then the entire
......@@ -395,11 +400,60 @@ class OLPIMDB(PIMDB):
i += 1
def new_folder (self, fname, type):
def new_folder (self, fname, ftype, storeid=None):
"""Create a new folder of specified type and return an id. The folder
will not contain any items"""
will not contain any items. If storeid is None the folder is
created in the default message store.
raise NotImplementedError
type has to be one of the Folder.valid_types
"""
if not ftype in Folder.valid_types:
logging.error('Cannot create folder of type: %s', ftype)
return None
if not storeid:
store = self.get_default_msgstore()
else:
store = self.get_msgstore(storeid)
root = store.get_root_folder_obj()
if not root:
logging.error('Unable to open Root Folder for store : %s',
storeid)
return None
cclass = OLFolder.get_cclass_from_ftype(ftype)
try:
nf = root.CreateFolder(mapi.FOLDER_GENERIC, fname, 'Comment',
None, 0)
except Exception, e:
logging.error('Failed to create new folder %s. CreateFolder '
'returned error code: %s', fname,
str(e))
return None
hr, ps = nf.SetProps([(mapitags.PR_CONTAINER_CLASS, cclass)])
if winerror.FAILED(hr):
logging.error('Failed to Set Container class for newly created '
'folder %s. Hm. tough luck... Delete the sucker '
'manually from Outlook. Sorry for the bother. '
'Error Code retruned by SetProps: 0x%x',fname,
winerror.HRESULT_CODE(hr))
return None
hr, ps = nf.GetProps((mapitags.PR_ENTRYID))
if winerror.FAILED(hr):
logging.error('Failed to get Entry_ID for newly created '
'folder %s. Hm. tough luck... Delete the sucker '
'manually from Outlook. Sorry for the bother. '
'Error Code retruned by SetProps: 0x%x',fname,
winerror.HRESULT_CODE(hr))
return None
tag, val = ps[0]
return val
def get_olsession (self):
"""Return a reference to the Outlook MAPI session."""
......@@ -445,6 +499,13 @@ class OLPIMDB(PIMDB):
self.sync_folders['contacts'].append(self.folders['contacts'][0])
def get_default_msgstore (self):
stores = self.get_msgstores()
return stores.get_default_store()
def get_msgstore (self, eid):
return self.get_msgstore().get(eid=eid)
def prep_for_sync (self, dbid):
pass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment