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>