from OFS import SimpleItem from Globals import Persistent, data_dir, MessageDialog from AccessControl import getSecurityManager, Role import Acquisition, base64, time from Config import * from SysConfig import * from DocumentTemplate.DT_Var import url_quote_plus from StringIO import StringIO import string, os from os.path import exists from Products.PageTemplates.PageTemplateFile import PageTemplateFile # do xml import xmlrpclibBasicAuth def unicodify(s): """decode str (utf-8 or latin-1 representation) into unicode object""" if not s: return u"" if isinstance(s, str): try: return s.decode('utf-8') except: return s.decode('latin-1') else: return s def utf8ify(s): """encode unicode object or string into byte string in utf-8 representation. assumes string objects to be utf-8""" if not s: return "" if isinstance(s, str): return s else: return s.encode('utf-8') class BaseSyncer(SimpleItem.Item, Persistent, Acquisition.Implicit, Role.RoleManager): """This class contains Basic methods, even These methods will be common if we implements Module Syncer""" manage_options = ( {'label': 'Sync', 'action': 'manage_vsync' }, {'label': 'Edit Server', 'action': 'manage_edit' }, {'label': 'View Log', 'action': 'manage_viewlog' }, ) __ac_permissions__= ( ('View management screens', ( 'manage_tabs','manage_main','manage_edit','is_diffable', 'manage_approvedAction', 'manage_addXMLRPC', 'manage_listObjects', 'manage_exportXMLRPC', 'manage_deleteXMLRPC', 'manage_diffObject', 'manage_compare', 'manage_srcXMLRPC', 'status_colour', 'manage_folders', 'manage_vsync') ), ('Change permissions', ('manage_access',) ), ) targetServer=dest_syncer allowed_objs_sync = allowed_objs_sync manage_viewlog = PageTemplateFile('zpt/VViewLog', globals()) def __init__(self, id, title=''): """initialize a new instance of Server""" self.id = id self.title = title self.source_server = [ None, ] # source is this Syncer self.dest_server = '' self.log = 0 self.approval = 1 self.syncable = syncable self.filtered_objects = [] self.logfile = os.path.join(data_dir, 'VSourceSyncer.log') def manage_editServer(self, title='', dest=None, log=0, approval=0, logfile='', REQUEST=None, syncable=syncable, filterObjects=0, allowed_objs=[] ): "edit server" auth_user = getSecurityManager().getUser().getId() if auth_user not in managers_list: return MessageDialog(title='Addess Denied', message='You are not allowed to edit SourceSyncer', action='manage_vsync') self.title = title self.log = log self.logfile = logfile self.approval = approval self.syncable = syncable self.dest_server = string.strip(dest) self.filterObjects = filterObjects self.filtered_objects = allowed_objs if REQUEST is not None: return MessageDialog(title = 'Edited', message = "Properties changed.", action = 'manage_edit') #################### for displaying the log info ########################## def manage_getLog(self, filter=None): """Return the log file details as a list """ log_list=[] if not exists(self.logfile): return 'file not found. Please enable log option from edit server tab' # Cool. File found. Open. if we have permission. try: fp = open(self.logfile, 'r') data_list = fp.readlines() fp.close() except : return "problem with opening/reading file" dummy_list = [] for line in data_list: if string.find(line, 'Syncing finished') > -1: dummy_list.reverse() log_list = log_list + dummy_list dummy_list = [] continue elif string.find(line, 'Syncing started') > -1: dummy_list.append({'head':1,'text':line[:25]}) elif (string.find(line, 'Syncer:') > -1 or string.find(line, 'Approver:') > -1): dummy_list.append({'spec':1,'text':line[25:]}) else: dummy_list.append({'normal':1,'text':line[25:]}) log_list.reverse() return log_list ############################################################ def manage_approvedAction(self, REQUEST=None, action='', object=None, syncer=None, approver=None, comments=None): """ If this action is to be approved, throw that data in into the message list """ if not syncer : syncer = getSecurityManager().getUser().getId() msgs = ['Syncer: %s' % syncer,] msgs.append('Approver: %s' % approver) # string out any newlines in comments msgs.append('Comments: %s' % string.replace(comments, '\n', '')) # call the relevant thing if action == 'manage_updateXMLRPC': return self.manage_updateXMLRPC(object, msgs=msgs, REQUEST=REQUEST) else: return self._error(msg='Unknown action') def manage_addXMLRPC(self, data, obj_path, add_in=1): """ Adds an object into the server """ # make sure we always get a string or a list if type(obj_path) == type('string'): obj_path = string.split(obj_path, '/') # object lets try finding the parent try: parent = self.restrictedTraverse(obj_path[:-1]) except KeyError: return 404 # lets check they are allowed to do this c = getSecurityManager().checkPermission allowed = 1 for perm in ['Delete objects', 'Import/Export objects']: if not c(perm, parent): allowed = 0 if not allowed: return 403 # if there is one there already, delete it if obj_path[-1] in parent.objectIds(): parent.manage_delObjects([obj_path[-1],]) else: if not add_in: # ok so if we are deleting return 404 # lets do it if add_in: # fake a file using StringIO file = StringIO() file.write(self._decode(data)) file.seek(0) # now import new = parent._p_jar.importFile(file) parent._setObject(new.getId(), new) # wow!.. return 200 def manage_takeBackup(self, obj=None): #take a back of the syncable file in the backup_sync folder if not exists just create one. if obj is None : return None obj_id = obj.getId() parent = obj.aq_parent parent_contents = parent.objectIds() bak_id = 'backup_sync' # backup folder name. if bak_id not in parent_contents:parent.manage_addFolder(id=bak_id) bak_folder = getattr(parent,bak_id) if obj_id in bak_folder.objectIds(): bak_folder.manage_delObjects([obj_id]) bak_folder.manage_pasteObjects(parent.manage_copyObjects([obj_id])) ############################################################################# #Private Methods ############################################################################# def _log(self, msgs): # log to ZSyncer # this will become more configurable file = open(self.logfile, 'a') # write out the log file.write('%s\tSyncing started\n' % self._get_time()) for m in msgs: file.write('%s\t%s\n' % (self._get_time(), m)) file.write('%s\tSyncing finished\n' % self._get_time()) file.close() def _get_time(self): # get time for logging # could be done using DateTime, but i think I want to fiddle this return time.asctime(time.localtime(time.time())) def _encode(self, s): # do any other encoding here # eg twofish, zlib etc # this will do me for now return base64.encodestring(utf8ify(s)) def _decode(self, s): # do any other encoding here return base64.decodestring(s) def _serverUser(self, url): # extract user from server url, returns server, user, pw if url.find('@'): # user:password in URL (us,ur) = url.split('@') (prot,upw) = us.split('//') (user,pw) = upw.split(':') url = prot + '//' + ur else: u = getSecurityManager().getUser() user = u.getId() pw = u._getPassword() return (url,user,pw) def _serverConn(self, url): # connect using xmlrpc lib (server,user,pw) = self._serverUser(url) return xmlrpclibBasicAuth.Server(server, user, pw) def _check_http(self, v): # so people can get away with leaving http:// off :) if v[:7] != 'http://' and v[:8] != 'https://': v = 'http://%s' % v if v[:5] != 'http:' and v[:6] != 'https:': v = 'http:%s' % v return v def _msg(self, msgs, REQUEST=None): # what to do with these messages ms = [] for m in msgs: # hack-o-rama, if i have a number, its a status code, so lets look it up and get a nicer message if type(m) == type(1): ms.append(' - %s' % (error_messages.get(str(m), 'Unknown error occured'))) elif m[:6] == 'Object': ms.append('
  • %s' % m) else: ms.append(m) if self.log or self.approval: self._log(ms) if REQUEST is not None: return REQUEST.RESPONSE.redirect( 'manage_vsync?folder=%s&msg=%s' % ( self.REQUEST.get('folder', '/'), url_quote_plus(string.join(ms, '
    ')) ) )