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
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(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), '<font color=red>Unknown error occured</font>')))
elif m[:6] == 'Object': ms.append('<li><font color=blue size=3>%s</font>' % 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, '<br>'))
)
)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>