[bin] backup.py: remove Data.fs.old before packing the ZODB to avoid disk space problems; [checkldap] added a param to define the scope of the LDAP query (base, onelevel or subtree); [shared] xml_parser: convert nbsp entity to the equivalent utf-8 char.

This commit is contained in:
Gaetan Delannay 2013-09-05 10:42:19 +02:00
parent 528cca9aa0
commit 1be7d9f0ab
8 changed files with 83 additions and 22 deletions

View file

@ -61,6 +61,21 @@ class ZodbBackuper:
fileName = self.storageLocation + fileSuffix
os.system('chown %s %s' % (self.zopeUser, fileName))
def removeDataFsOld(self):
'''Removes the file Data.fs.old if it exists.
In the process of packing the ZODB, an additional file Data.fs.pack
is created, and renamed to Data.fs once finished. It means that, when
we pack the ZODB, 3 copies of the DB can be present at the same time:
Data.fs, Data.fs.old and Data.fs.pack. We prefer to remove the
Data.fs.old copy to avoid missing disk space if the DB is big.
'''
old = self.storageLocation + '.old'
if os.path.exists(old):
self.log('Removing %s...' % old)
os.remove(old)
self.log('Done.')
folderCreateError = 'Could not create backup folder. Backup of log ' \
'files will not take place. %s'
def backupLogs(self):
@ -190,6 +205,8 @@ class ZodbBackuper:
self.executeCommand('%s stop' % self.zopectl)
# If we are on the "full backup day", let's pack the ZODB first
if time.asctime().startswith(self.options.dayFullBackup):
# As a preamble to packing the ZODB, remove Data.fs.old if present.
self.removeDataFsOld()
w('> Day is "%s", packing the ZODB...' % self.options.dayFullBackup)
self.packZodb()
w('> Make a backup of log files...')

View file

@ -12,18 +12,22 @@ class LdapTester:
attrs is a comma-separated list of attrs we will retrieve in the LDAP,
ie "uid,login"
filter is the query filter, ie "(&(attr1=Geez*)(status=OK))"
scope is the scope of the search, and can be:
BASE To search the object itself on base
ONELEVEL To search base's immediate children
SUBTREE To search base and all its descendants
'''
def __init__(self):
# Get params from shell args.
if len(sys.argv) != 7:
if len(sys.argv) != 8:
print(LdapTester.__doc__)
sys.exit(0)
s = self
s.uri, s.login, s.password, s.base, s.attrs, s.filter = sys.argv[1:]
s.uri,s.login,s.password,s.base,s.attrs,s.filter,s.scope = sys.argv[1:]
self.attrs = self.attrs.split(',')
self.tentatives = 5
self.timeout = 5
self.attrList = ['cfwbV2cn', 'logindisabled']
self.attrList = ['cn']
self.ssl = False
def test(self):
@ -38,8 +42,9 @@ class LdapTester:
for i in range(self.tentatives):
try:
print('Done. Performing a simple query on %s...'% self.base)
res = server.search_st(
self.base, ldap.SCOPE_ONELEVEL, filterstr=self.filter,
res = server.search_st(self.base,
getattr(ldap, 'SCOPE_%s' % self.scope),
filterstr=self.filter,
attrlist=self.attrs, timeout=5)
print('Got %d entries' % len(res))
break

View file

@ -369,15 +369,22 @@ class User(Model):
# ------------------------------------------------------------------------------
class LdapConfig:
'''Parameters for authenticating users to an external LDAP.'''
server = '' # Name of the LDAP server
port = None # Port for this server.
# Login and password of the technical power user that the Appy application
# will use to connect to the LDAP.
adminLogin = ''
adminPassword = ''
# LDAP attribute to use as login for authenticating users.
loginAttribute = 'dn' # Can also be "mail", "sAMAccountName", "cn"
baseDn = '' # Base distinguished name where to find users in the LDAP.
def __init__(self):
self.server = '' # Name of the LDAP server
self.port = None # Port for this server.
# Login and password of the technical power user that the Appy
# application will use to connect to the LDAP.
self.adminLogin = ''
self.adminPassword = ''
# LDAP attribute to use as login for authenticating users.
self.loginAttribute = 'dn' # Can also be "mail", "sAMAccountName", "cn"
self.baseDn = '' # Base distinguished name where to find users.
def getServerUri(self):
'''Returns the complete URI for accessing the LDAP, ie
"ldap://some.ldap.server:389".'''
port = self.port or 389
return 'ldap://%s:%d' % (self.server, port)
# ------------------------------------------------------------------------------
class Config:

View file

@ -25,12 +25,11 @@ def traverseWrapper(self, path, response=None, validated_hook=None):
'''This function is called every time a users gets a URL, this is used for
tracking user activity. self is a BaseRequest'''
res = originalTraverse(self, path, response, validated_hook)
t = time.time()
if os.path.splitext(path)[-1].lower() not in doNotTrack:
# Do nothing when the user gets non-pages
# Do nothing when the user gets non-pages.
userId, dummy = gutils.readCookie(self)
if userId:
loggedUsers[userId] = t
loggedUsers[userId] = time.time()
# "Touch" the SESSION object. Else, expiration won't occur.
session = self.SESSION
return res

View file

@ -1,5 +1,34 @@
# ------------------------------------------------------------------------------
try:
import ldap
except ImportError:
# For people that do not care about ldap.
ldap = None
# ------------------------------------------------------------------------------
def connect(serverUri, login, password):
'''Tries to connect to some LDAP server whose UIR is p_serverUri, using
p_login and p_password as credentials.'''
try:
server = ldap.initialize(serverUri)
server.simple_bind(login, password)
return True, server, None
except ldap.LDAPError, le:
return False, None, str(le)
# ------------------------------------------------------------------------------
def authenticate(login, password, ldapConfig, tool):
'''Tries to authenticate user p_login in the LDAP.'''
return
'''Tries to authenticate user p_login in the LDAP.'''
# Connect to the ldap server.
serverUri = cfg.getServerUri()
success, server, msg = connect(serverUri, cfg.adminLogin, cfg.adminPassword)
# Manage a connection error.
if not success:
tool.log('%s: connect error (%s).' % (serverUri, msg))
return
# Do p_login and p_password correspond to a user in the LDAP?
try:
pass
except:
pass
# ------------------------------------------------------------------------------

View file

@ -1051,6 +1051,7 @@ class ToolMixin(BaseMixin):
# a is the object the object was accessed through
# c is the physical container of the object
a, c, n, v = self._getobcontext(v, request)
print c
# Try to get user name and password from basic authentication
login, password = self.identify(auth)
if not login:

View file

@ -330,7 +330,7 @@ class XhtmlEnvironment(XmlEnvironment):
'''Dumps content that was temporarily stored in self.currentContent
into the result.'''
contentSize = 0
if self.currentContent.strip():
if self.currentContent.strip(' \n\r\t'): # NBSP must not be in this list
# Manage missing elements
currentElem = self.getCurrentElement()
if self.anElementIsMissing(currentElem, None):

View file

@ -61,7 +61,7 @@ HTML_ENTITIES = {
'ntilde':'ñ', 'ograve':'ò', 'oacute':'ó', 'ocirc':'ô', 'otilde':'õ',
'ouml':'ö', 'divide':'÷', 'oslash':'ø', 'ugrave':'ù', 'uacute':'ú',
'ucirc':'û', 'uuml':'ü', 'yacute':'ý', 'thorn':'þ', 'yuml':'ÿ',
'euro':'', 'nbsp':' ', "rsquo":"'", "lsquo":"'", "ldquo":"'",
'euro':'', 'nbsp':' ', "rsquo":"'", "lsquo":"'", "ldquo":"'",
"rdquo":"'", 'ndash': '', 'mdash': '', 'oelig':'oe', 'quot': "'",
'mu': 'µ'}
import htmlentitydefs
@ -1135,7 +1135,10 @@ class XhtmlCleaner(XmlParser):
# between tags.
if not self.env.currentContent or \
self.env.currentContent[-1] in ('\n', ' '):
toAdd = content.lstrip()
# I give here to lstrip an explicit list of what is to be considered
# as blank chars, because I do not want unicode NBSP chars to be in
# this list.
toAdd = content.lstrip(u' \n\r\t')
else:
toAdd = content
# Re-transform XML special chars to entities.