File:  [Repository] / VSyncer / BaseSyncer.py
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Fri Jan 4 15:34:43 2008 UTC (16 years, 6 months ago) by casties
Branches: MAIN
CVS tags: HEAD
more unicode fixes

    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: 
   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: 
   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
  210:         return base64.encodestring(utf8ify(s))
  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>