Annotation of VSyncer/BaseSyncer.py, revision 1.2

1.1       casties     1: from OFS import SimpleItem
                      2: from Globals import Persistent, data_dir, MessageDialog
                      3: from AccessControl import getSecurityManager, Role
                      4: import Acquisition, base64, time
                      5: from Config import *
                      6: from SysConfig import *
                      7: from DocumentTemplate.DT_Var import url_quote_plus
                      8: from StringIO import StringIO
                      9: import string, os
                     10: from os.path import exists
                     11: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
                     12: 
                     13: # do xml
                     14: import xmlrpclibBasicAuth
                     15: 
1.2     ! casties    16: def unicodify(s):
        !            17:     """decode str (utf-8 or latin-1 representation) into unicode object"""
        !            18:     if not s:
        !            19:         return u""
        !            20:     if isinstance(s, str):
        !            21:         try:
        !            22:             return s.decode('utf-8')
        !            23:         except:
        !            24:             return s.decode('latin-1')
        !            25:     else:
        !            26:         return s
        !            27: 
        !            28: def utf8ify(s):
        !            29:     """encode unicode object or string into byte string in utf-8 representation.
        !            30:        assumes string objects to be utf-8"""
        !            31:     if not s:
        !            32:         return ""
        !            33:     if isinstance(s, str):
        !            34:         return s
        !            35:     else:
        !            36:         return s.encode('utf-8')
        !            37: 
1.1       casties    38: 
                     39: class BaseSyncer(SimpleItem.Item, Persistent, Acquisition.Implicit, Role.RoleManager):
                     40:     """This class contains Basic methods, even These methods will be common if we implements Module Syncer"""
                     41:     manage_options = (
                     42:         {'label': 'Sync', 'action': 'manage_vsync' },
                     43:         {'label': 'Edit Server', 'action': 'manage_edit' },
                     44:         {'label': 'View Log', 'action': 'manage_viewlog' },
                     45:     )
                     46:     
                     47:     __ac_permissions__= (
                     48:         ('View management screens', (
                     49:         'manage_tabs','manage_main','manage_edit','is_diffable', 'manage_approvedAction', 'manage_addXMLRPC',
                     50:         'manage_listObjects', 'manage_exportXMLRPC', 'manage_deleteXMLRPC', 'manage_diffObject',
                     51:         'manage_compare', 'manage_srcXMLRPC', 'status_colour', 'manage_folders', 'manage_vsync') ),
                     52:         ('Change permissions', ('manage_access',) ),
                     53:     )
                     54: 
                     55:     targetServer=dest_syncer
                     56:     allowed_objs_sync = allowed_objs_sync
                     57:     manage_viewlog = PageTemplateFile('zpt/VViewLog', globals())
                     58:     
                     59: 
                     60:     def __init__(self, id, title=''):
                     61:         """initialize a new instance of Server"""
                     62:         self.id = id
                     63:         self.title = title
                     64:         self.source_server = [ None, ] # source is this Syncer
                     65:         self.dest_server = ''
                     66:         self.log = 0
                     67:         self.approval = 1
                     68:         self.syncable = syncable
                     69:         self.filtered_objects = []
                     70:         self.logfile = os.path.join(data_dir, 'VSourceSyncer.log')
                     71: 
                     72:     def manage_editServer(self, title='', dest=None, log=0, approval=0, logfile='', REQUEST=None, syncable=syncable, filterObjects=0, allowed_objs=[] ):
                     73:         "edit server"
                     74:         auth_user = getSecurityManager().getUser().getId()
                     75:         if auth_user not in managers_list:
                     76:             return MessageDialog(title='Addess Denied', message='You are not allowed to edit SourceSyncer', action='manage_vsync')
                     77:         
                     78:         self.title = title
                     79:         self.log = log
                     80:         self.logfile = logfile
                     81:         self.approval = approval
                     82:         self.syncable = syncable
                     83:         self.dest_server = string.strip(dest)
                     84:         self.filterObjects = filterObjects
                     85:         self.filtered_objects = allowed_objs
                     86:         if REQUEST is not None:
                     87:             return MessageDialog(title = 'Edited', message = "Properties changed.", action = 'manage_edit')
                     88:             
                     89:     #################### for displaying the log info ##########################
                     90:     def manage_getLog(self, filter=None):
                     91:         """Return the log file details as a list """
                     92:         log_list=[]
                     93:         if not exists(self.logfile):
                     94:                 return 'file not found. Please enable log option from edit server tab'
                     95: 
                     96:         # Cool. File found. Open. if we have permission.
                     97:         try:
                     98:             fp = open(self.logfile, 'r')
                     99:             data_list = fp.readlines()
                    100:             fp.close()
                    101:         except :
                    102:             return "problem with opening/reading file" 
                    103:         dummy_list = []    
                    104:         for line in data_list:
                    105:             if string.find(line, 'Syncing finished') > -1:
                    106:                 dummy_list.reverse()
                    107:                 log_list = log_list + dummy_list
                    108:                 dummy_list = []
                    109:                 continue
                    110:             elif string.find(line, 'Syncing started') > -1:
                    111:                 dummy_list.append({'head':1,'text':line[:25]})
                    112:             elif (string.find(line, 'Syncer:') > -1 or
                    113:                     string.find(line, 'Approver:') > -1):
                    114:                 dummy_list.append({'spec':1,'text':line[25:]})
                    115:             else:
                    116:                 dummy_list.append({'normal':1,'text':line[25:]})
                    117: 
                    118:         log_list.reverse()
                    119:         return log_list
                    120:     ############################################################    
                    121:     def manage_approvedAction(self, REQUEST=None, action='', object=None, syncer=None, approver=None, comments=None):
                    122:         """ If this action is to be approved, throw that data in into the message list """
                    123:         if not syncer : syncer = getSecurityManager().getUser().getId()
                    124:         msgs = ['Syncer: %s' % syncer,]
                    125:         msgs.append('Approver: %s' % approver)
                    126:         
                    127:         # string out any newlines in comments
                    128:         msgs.append('Comments: %s' % string.replace(comments, '\n', ''))
                    129:         # call the relevant thing
                    130:         if action == 'manage_updateXMLRPC':
                    131:             return self.manage_updateXMLRPC(object, msgs=msgs, REQUEST=REQUEST)
                    132:         else:
                    133:             return self._error(msg='Unknown action')
                    134: 
                    135: 
                    136:     def manage_addXMLRPC(self, data, obj_path, add_in=1):
                    137:         """ Adds an object into the server """
                    138:         # make sure we always get a string or a list
                    139:         if type(obj_path) == type('string'): obj_path = string.split(obj_path, '/')
                    140: 
                    141:         # object lets try finding the parent
                    142:         try: parent = self.restrictedTraverse(obj_path[:-1])
                    143:         except KeyError: return 404
                    144: 
                    145:         # lets check they are allowed to do this
                    146:         c = getSecurityManager().checkPermission
                    147:         allowed = 1
                    148:         for perm in ['Delete objects', 'Import/Export objects']:
                    149:             if not c(perm, parent): allowed = 0
                    150:         if not allowed: return 403
                    151: 
                    152:         # if there is one there already, delete it
                    153:         if obj_path[-1] in parent.objectIds():
                    154:             parent.manage_delObjects([obj_path[-1],])
                    155:         else:
                    156:             if not add_in: # ok so if we are deleting
                    157:                 return 404
                    158: 
                    159:         # lets do it
                    160:         if add_in:
                    161:             # fake a file using StringIO
                    162:             file = StringIO()
                    163:             file.write(self._decode(data))
                    164:             file.seek(0)
                    165: 
                    166:             # now import
                    167:             new = parent._p_jar.importFile(file)
                    168:             parent._setObject(new.getId(), new)
                    169: 
                    170:         # wow!..
                    171:         return 200
                    172: 
                    173:     def manage_takeBackup(self, obj=None):
                    174:         #take a back of the syncable file in the backup_sync folder if not exists just create one.
                    175:         if obj is None : return None
                    176:         obj_id = obj.getId()
                    177:         parent = obj.aq_parent
                    178:         parent_contents = parent.objectIds()
                    179:         bak_id = 'backup_sync' #  backup folder name.
                    180:         if bak_id not in parent_contents:parent.manage_addFolder(id=bak_id)
                    181:         bak_folder = getattr(parent,bak_id)
                    182:         if obj_id in bak_folder.objectIds(): bak_folder.manage_delObjects([obj_id])
                    183:         bak_folder.manage_pasteObjects(parent.manage_copyObjects([obj_id]))
                    184: 
                    185:     #############################################################################
                    186:     #Private Methods
                    187:     #############################################################################
                    188:     
                    189:     def _log(self, msgs):
                    190:         # log to ZSyncer
                    191:         # this will become more configurable
                    192:         file = open(self.logfile, 'a')
                    193: 
                    194:         # write out the log
                    195:         file.write('%s\tSyncing started\n' % self._get_time())
                    196:         for m in msgs: file.write('%s\t%s\n' % (self._get_time(), m))
                    197:         file.write('%s\tSyncing finished\n' % self._get_time())
                    198: 
                    199:         file.close()
                    200: 
                    201:     def _get_time(self):
                    202:         # get time for logging
                    203:         # could be done using DateTime, but i think I want to fiddle this
                    204:         return time.asctime(time.localtime(time.time()))    
                    205: 
                    206:     def _encode(self, s):
                    207:         # do any other encoding here
                    208:         # eg twofish, zlib etc
                    209:         # this will do me for now
1.2     ! casties   210:         return base64.encodestring(utf8ify(s))
1.1       casties   211:     
                    212:     def _decode(self, s):
                    213:         # do any other encoding here
                    214:         return base64.decodestring(s)
                    215: 
                    216:     def _serverUser(self, url):
                    217:         # extract user from server url, returns server, user, pw
                    218:         if url.find('@'):
                    219:             # user:password in URL
                    220:             (us,ur) = url.split('@')
                    221:             (prot,upw) = us.split('//')
                    222:             (user,pw) = upw.split(':')
                    223:             url = prot + '//' + ur
                    224:         else: 
                    225:             u = getSecurityManager().getUser()
                    226:             user = u.getId()
                    227:             pw = u._getPassword()
                    228:         return (url,user,pw)
                    229: 
                    230:     def _serverConn(self, url):
                    231:         # connect using xmlrpc lib
                    232:         (server,user,pw) = self._serverUser(url)
                    233:         return xmlrpclibBasicAuth.Server(server, user, pw)
                    234: 
                    235:     def _check_http(self, v):
                    236:         # so people can get away with leaving http:// off :)
                    237:         if v[:7] != 'http://' and v[:8] != 'https://': v = 'http://%s' % v
                    238:         if v[:5] != 'http:' and v[:6] != 'https:': v = 'http:%s' % v
                    239:         return v
                    240: 
                    241:     def _msg(self, msgs, REQUEST=None):
                    242:         # what to do with these messages
                    243:         ms = []
                    244:         for m in msgs:
                    245:             # hack-o-rama, if i have a number, its a status code, so lets look it up and get a nicer message
                    246:             if type(m) == type(1): ms.append(' - %s' % (error_messages.get(str(m), '<font color=red>Unknown error occured</font>')))
                    247:             elif m[:6] == 'Object': ms.append('<li><font color=blue size=3>%s</font>' % m)
                    248:             else: ms.append(m)
                    249: 
                    250:         if self.log or self.approval: self._log(ms)
                    251:         if REQUEST is not None:
                    252:             return REQUEST.RESPONSE.redirect(
                    253:                     'manage_vsync?folder=%s&msg=%s' %
                    254:                     (
                    255:                         self.REQUEST.get('folder', '/'),
                    256:                         url_quote_plus(string.join(ms, '<br>'))
                    257:                     )    
                    258:                 )

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>