This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/servers/ArticlesServer/ArticlesServer.py

982 lines
44 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
# Romain Chantereau <rchantereau@entrouvert.com>
# Nicolas Clapiès <nclapies@easter-eggs.org>
# Pierre-Antoine Dejace <padejace@entrouvert.be>
# Thierry Dulieu <tdulieu@easter-eggs.com>
# Florent Monnier <monnier@codelutin.com>
# Cédric Musso <cmusso@easter-eggs.org>
# Frédéric Péters <fpeters@entrouvert.be>
# Benjamin Poussin <poussin@codelutin.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
# Sébastien Régnier <regnier@codelutin.com>
# Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
# Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
# Régnier, Emmanuel Saracco, Théridion & Vecam
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
__doc__ = """Glasnost Articles Server"""
__version__ = '$Revision$'[11:-2]
import base64
import fcntl
import os
import sys
import time
import re
glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
sys.path.insert(0, glasnostPythonDir)
import glasnost
from glasnost.common.ArticlesCommon import *
import glasnost.common.tools_new as commonTools
import glasnost.common.faults as faults
import glasnost.common.xhtmlgenerator as X
from glasnost.server.ObjectsServer import register, ObjectServerMixin, \
AdminServerMixin, ObjectsServer
from glasnost.server.tools import *
from glasnost.proxy.CacheProxy import invalidateValue
from glasnost.proxy.DispatcherProxy import MultiCall, \
getApplicationId, getApplicationToken
from glasnost.proxy.GroupsProxy import getSetContainedIds
applicationName = 'ArticlesServer'
applicationRole = 'articles'
dispatcher = None
class AdminArticles(AdminServerMixin, AdminArticlesCommon):
pass
register(AdminArticles)
class Article(ObjectServerMixin, ArticleCommon):
def acquireNonCore(self, objectDirectoryPath = None,
dataDirectoryPath = None, parentSlot = None):
ObjectServerMixin.acquireNonCore(
self, objectDirectoryPath = objectDirectoryPath,
dataDirectoryPath = dataDirectoryPath, parentSlot = parentSlot)
self.loadBody()
def getBodyDiff(self, editionTime):
virtualServerId = self.getServer().computeVirtualServerId(self.id)
virtualServer = self.getServer().getVirtualServer(virtualServerId)
articlesDirectoryPath = os.path.join(
virtualServer.dataDirectoryPath, self.getServer().applicationRole)
serverHostNameAndPort, serverRole, localId = splitId(self.id)
bodyFilePath = os.path.join(articlesDirectoryPath, localId)
if not os.access(bodyFilePath, os.F_OK):
return None
bodyHistoryDirectoryPath = os.path.join(
articlesDirectoryPath, localId + '-history')
if not os.access(bodyHistoryDirectoryPath, os.F_OK):
return None
fileNames = os.listdir(bodyHistoryDirectoryPath)
if not fileNames:
return None
editionTimeString = time.strftime('%Y%m%d%H%M%S',
time.localtime(editionTime))
editionTimeLen = len(editionTimeString)
for fileName in fileNames:
if fileName[:editionTimeLen] == editionTimeString \
and fileName[editionTimeLen] == '-':
editionTimeString, editorIdEncoded, format = \
fileName.split('-')
editorId = base64.decodestring(editorIdEncoded)
bodyVersionFilePath = os.path.join(bodyHistoryDirectoryPath,
fileName)
command = 'diff -u %(backup)s %(current)s' % {
'backup': bodyVersionFilePath,
'current': bodyFilePath,
}
diffFile = os.popen(command, 'r')
diff = diffFile.readlines()
result = diffFile.close()
if not diff:
return None
version = {
'diff': diff[2:],
'editionTime': editionTime,
'format': format,
}
if editorId:
version['editorId'] = editorId
return version
return None
def getBodyHistory(self):
virtualServerId = self.getServer().computeVirtualServerId(self.id)
virtualServer = self.getServer().getVirtualServer(virtualServerId)
articlesDirectoryPath = os.path.join(
virtualServer.dataDirectoryPath, self.getServer().applicationRole)
serverHostNameAndPort, serverRole, localId = splitId(self.id)
bodyHistoryDirectoryPath = os.path.join(
articlesDirectoryPath, localId + '-history')
history = []
if not os.access(bodyHistoryDirectoryPath, os.F_OK):
return history
fileNames = os.listdir(bodyHistoryDirectoryPath)
if fileNames:
fileNames.sort()
for fileName in fileNames:
editionTimeString, editorIdEncoded, format = \
fileName.split('-')
t = time.strptime(editionTimeString, '%Y%m%d%H%M%S')
# Set Daylight Saving Time to -1, so that it is handled
# correctly by mktime.
t = tuple(list(t[0:-1]) + [-1])
editionTime = time.mktime(t)
editorId = base64.decodestring(editorIdEncoded)
version = {
'editionTime': editionTime,
'format': format,
}
if editorId:
version['editorId'] = editorId
history.append(version)
return history
def getBodyVersion(self, editionTime):
virtualServerId = self.getServer().computeVirtualServerId(self.id)
virtualServer = self.getServer().getVirtualServer(virtualServerId)
articlesDirectoryPath = os.path.join(
virtualServer.dataDirectoryPath, self.getServer().applicationRole)
serverHostNameAndPort, serverRole, localId = splitId(self.id)
bodyHistoryDirectoryPath = os.path.join(
articlesDirectoryPath, localId + '-history')
if not os.access(bodyHistoryDirectoryPath, os.F_OK):
return None
fileNames = os.listdir(bodyHistoryDirectoryPath)
if not fileNames:
return None
editionTimeString = time.strftime('%Y%m%d%H%M%S',
time.localtime(editionTime))
editionTimeLen = len(editionTimeString)
for fileName in fileNames:
if fileName[:editionTimeLen] == editionTimeString \
and fileName[editionTimeLen] == '-':
editionTimeString, editorIdEncoded, format = \
fileName.split('-')
editorId = base64.decodestring(editorIdEncoded)
bodyVersionFilePath = os.path.join(bodyHistoryDirectoryPath,
fileName)
bodyVersionFile = open(bodyVersionFilePath, 'rb')
fcntl.lockf(bodyVersionFile, fcntl.LOCK_SH)
body = bodyVersionFile.read()
fcntl.lockf(bodyVersionFile, fcntl.LOCK_UN)
bodyVersionFile.close()
version = {
'body': body,
'editionTime': editionTime,
'format': format,
}
if editorId:
version['editorId'] = editorId
return version
return None
def getDocBookChapter(self):
# FIXME: support conversion from every text format to DocBook
assert self.format == 'spip'
from glasnost.proxy.tools import makeDocBookFromSpip
return makeDocBookFromSpip(self.body, docType = 'chapter',
addHeader = 0, title = self.title)
def getLatexChapter(self):
# FIXME: support conversion from every text format to LaTeX
assert self.format == 'spip'
from glasnost.proxy.tools import makeLatexFromSpip
return makeLatexFromSpip(self.body, docType = 'chapter',
addHeader = 0, title = self.title)
def loadBody(self):
virtualServerId = self.getServer().computeVirtualServerId(self.id)
virtualServer = self.getServer().getVirtualServer(virtualServerId)
articlesDirectoryPath = os.path.join(
virtualServer.dataDirectoryPath, self.getServer().applicationRole)
serverHostNameAndPort, serverRole, localId = splitId(self.id)
bodyFilePath = os.path.join(articlesDirectoryPath, localId)
try:
bodyFile = open(bodyFilePath, 'rb')
except IOError:
if self.__dict__.has_key('body'):
del self.body
else:
fcntl.lockf(bodyFile, fcntl.LOCK_SH)
self.body = bodyFile.read()
fcntl.lockf(bodyFile, fcntl.LOCK_UN)
bodyFile.close()
def modify(self, changes, givenSlotNames = None):
if (not givenSlotNames or 'body' in givenSlotNames) \
and changes.body != self.body:
if changes.body is None:
if self.lastEditorId:
del self.lastEditorId
if self.editionTime:
del self.editionTime
else:
userId = getProxyForServerRole('authentication').getUserId()
if userId:
self.lastEditorId = userId
self.editionTime = time.time()
ObjectServerMixin.modify(
self, changes, givenSlotNames = givenSlotNames)
def releaseNonCore(self, parentSlot = None):
if self.__dict__.has_key('body'):
del self.body
ObjectServerMixin.releaseNonCore(self, parentSlot = parentSlot)
def removeBodyFile(self):
virtualServerId = self.getServer().computeVirtualServerId(self.id)
virtualServer = self.getServer().getVirtualServer(virtualServerId)
articlesDirectoryPath = os.path.join(
virtualServer.dataDirectoryPath, self.getServer().applicationRole)
serverHostNameAndPort, serverRole, localId = splitId(self.id)
bodyFilePath = os.path.join(articlesDirectoryPath, localId)
try:
os.remove(bodyFilePath)
except OSError, error:
# Ignore 'No such file or directory' error.
if error.errno != 2:
raise
def removeBodyHistory(self):
virtualServerId = self.getServer().computeVirtualServerId(self.id)
virtualServer = self.getServer().getVirtualServer(virtualServerId)
articlesDirectoryPath = os.path.join(
virtualServer.dataDirectoryPath, self.getServer().applicationRole)
serverHostNameAndPort, serverRole, localId = splitId(self.id)
bodyHistoryDirectoryPath = os.path.join(
articlesDirectoryPath, localId + '-history')
if not os.access(bodyHistoryDirectoryPath, os.F_OK):
return
fileNames = os.listdir(bodyHistoryDirectoryPath)
if fileNames:
for fileName in fileNames:
filePath = os.path.join(bodyHistoryDirectoryPath, fileName)
os.remove(filePath)
os.rmdir(bodyHistoryDirectoryPath)
def removeNonCore(self, objectDirectoryPath = None,
dataDirectoryPath = None, parentSlot = None):
ObjectServerMixin.removeNonCore(
self, objectDirectoryPath = objectDirectoryPath,
dataDirectoryPath = dataDirectoryPath, parentSlot = parentSlot)
self.removeBodyFile()
self.removeBodyHistory()
def saveBody(self):
if self.body is None:
self.removeBodyFile()
return
virtualServerId = self.getServer().computeVirtualServerId(self.id)
virtualServer = self.getServer().getVirtualServer(virtualServerId)
articlesDirectoryPath = os.path.join(
virtualServer.dataDirectoryPath, self.getServer().applicationRole)
if not os.access(virtualServer.dataDirectoryPath, os.F_OK):
os.mkdir(virtualServer.dataDirectoryPath)
os.chmod(virtualServer.dataDirectoryPath, 0750)
if not os.access(articlesDirectoryPath, os.F_OK):
os.mkdir(articlesDirectoryPath)
os.chmod(articlesDirectoryPath, 0750)
serverHostNameAndPort, serverRole, localId = splitId(self.id)
bodyFilePath = os.path.join(articlesDirectoryPath, localId)
bodyFile = open(bodyFilePath, 'wb')
os.chmod(bodyFilePath, 0640)
fcntl.lockf(bodyFile, fcntl.LOCK_EX)
bodyFile.write(self.body)
fcntl.lockf(bodyFile, fcntl.LOCK_UN)
bodyFile.close()
def saveBodyHistory(self, format, body, editorId, editionTime):
virtualServerId = self.getServer().computeVirtualServerId(self.id)
virtualServer = self.getServer().getVirtualServer(virtualServerId)
articlesDirectoryPath = os.path.join(
virtualServer.dataDirectoryPath, self.getServer().applicationRole)
serverHostNameAndPort, serverRole, localId = splitId(self.id)
bodyHistoryDirectoryPath = os.path.join(
articlesDirectoryPath, localId + '-history')
if not os.access(bodyHistoryDirectoryPath, os.F_OK):
os.mkdir(bodyHistoryDirectoryPath)
os.chmod(bodyHistoryDirectoryPath, 0750)
editionTimeString = time.strftime('%Y%m%d%H%M%S',
time.localtime(editionTime))
if editorId is None:
editorId = ''
bodyHistoryFileName = \
'%(editionTime)s-%(editorIdEncoded)s-%(format)s' % {
'editionTime': editionTimeString,
'editorIdEncoded': base64.encodestring(editorId).strip(),
'format': format,
}
bodyHistoryFilePath = os.path.join(bodyHistoryDirectoryPath,
bodyHistoryFileName)
bodyHistoryFile = open(bodyHistoryFilePath, 'wb')
os.chmod(bodyHistoryFilePath, 0640)
fcntl.lockf(bodyHistoryFile, fcntl.LOCK_EX)
bodyHistoryFile.write(body)
fcntl.lockf(bodyHistoryFile, fcntl.LOCK_UN)
bodyHistoryFile.close()
def saveNonCore(self, objectDirectoryPath = None, dataDirectoryPath = None,
parentSlot = None):
ObjectServerMixin.saveNonCore(
self, objectDirectoryPath = objectDirectoryPath,
dataDirectoryPath = dataDirectoryPath, parentSlot = parentSlot)
self.saveBody()
register(Article)
class ArticlesServer(ArticlesCommonMixin, ObjectsServer):
def addObjectXmlRpc(self, objectImport):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
object = commonTools.importThing(objectImport)
if not self.canAddObject()or (
not self.isAdmin() and not (
getProxyForServerRole('authentication').setContainsUser(
self.getAdminCore().writersSet)
and getProxyForServerRole('authentication').setContainsUser(
object.writersSet))):
if not object.canBeCreatedByClient():
raise faults.UserAccessDenied()
object.checkAddIsPossible()
object.setAutomaticalSlots()
virtualServer.objects[object.id] = object
if object.body is not None:
userId = getProxyForServerRole('authentication').getUserId()
if userId:
object.lastEditorId = userId
object.editionTime = object.modificationTime
object.saveNonCore()
object.releaseNonCore()
virtualServer.markObjectAsDirty(object)
virtualServer.markCoreAsDirty()
return object.id
def canAddObject(self):
virtualServerId = context.getVar('applicationId')
applicationName = extractApplicationHostName(virtualServerId)
nbArticle = int(commonTools.getConfigNoCache(
'%s' % applicationName, 'Limit-%s' % applicationRole, '0'))
if nbArticle:
virtualServer = self.getVirtualServer(virtualServerId)
if len(virtualServer.objects.keys()) >= nbArticle:
return 0
return ObjectsServer.canAddObject(self)
def canGetObjectHistory(self, objectId):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
if not virtualServer.canLoadObjectCore(objectId):
return 0
object = virtualServer.loadObjectCore(objectId)
return self.isAdmin() \
or getProxyForServerRole('authentication').setContainsUser(
object.writersSet)
def convertVirtualServersIds(
self, sourceDispatcherId, destinationDispatcherId):
exitCode = ObjectsServer.convertVirtualServersIds(
self, sourceDispatcherId, destinationDispatcherId)
if exitCode is not None:
return exitCode
destinationVirtualServerId = '%s/%s' % (
destinationDispatcherId, self.applicationRole)
virtualServer = self.virtualServers[destinationVirtualServerId]
sourceHostName = extractApplicationHostName(sourceDispatcherId)
destinationHostName = extractApplicationHostName(
destinationDispatcherId)
sourceVirtualServerDataDirectoryPath = os.path.join(
self.dataDirectoryPath, sourceHostName)
destinationVirtualServerDataDirectoryPath = os.path.join(
self.dataDirectoryPath, destinationHostName)
sourceObjectsDirectoryPath = os.path.join(
sourceVirtualServerDataDirectoryPath, self.applicationRole)
destinationObjectsDirectoryPath = os.path.join(
destinationVirtualServerDataDirectoryPath, self.applicationRole)
for id in virtualServer.objects.keys():
serverHostNameAndPortNotUsed, serverRoleNotUsed, localId = \
splitId(id)
sourceBodyFilePath = os.path.join(
sourceObjectsDirectoryPath, localId)
destinationBodyFilePath = os.path.join(
destinationObjectsDirectoryPath, localId)
if not os.access(sourceBodyFilePath, os.F_OK):
continue
if not os.access(
destinationVirtualServerDataDirectoryPath, os.F_OK):
os.mkdir(destinationVirtualServerDataDirectoryPath)
os.chmod(destinationVirtualServerDataDirectoryPath, 0750)
if not os.access(destinationObjectsDirectoryPath, os.F_OK):
os.mkdir(destinationObjectsDirectoryPath)
os.chmod(destinationObjectsDirectoryPath, 0750)
sourceBodyFile = open(sourceBodyFilePath, 'rb')
destinationBodyFile = open(destinationBodyFilePath, 'wb')
os.chmod(destinationBodyFilePath, 0640)
destinationBodyFile.write(sourceBodyFile.read())
sourceBodyFile.close()
destinationBodyFile.close()
sourceBodyHistoryDirectoryPath = os.path.join(
sourceObjectsDirectoryPath, localId + '-history')
destinationBodyHistoryDirectoryPath = os.path.join(
destinationObjectsDirectoryPath, localId + '-history')
if not os.access(sourceBodyHistoryDirectoryPath, os.F_OK):
continue
if not os.access(destinationBodyHistoryDirectoryPath, os.F_OK):
os.mkdir(destinationBodyHistoryDirectoryPath)
os.chmod(destinationBodyHistoryDirectoryPath, 0750)
sourceBodyHistoryFileNames = os.listdir(
sourceBodyHistoryDirectoryPath)
for sourceBodyHistoryFileName in sourceBodyHistoryFileNames:
editionTimeString, sourceEditorIdEncoded, format = \
sourceBodyHistoryFileName.split('-')
sourceEditorId = base64.decodestring(sourceEditorIdEncoded)
destinationEditorId = sourceEditorId.replace(
sourceDispatcherId, destinationDispatcherId)
destinationBodyHistoryFileName = \
'%(editionTime)s-%(editorIdEncoded)s-%(format)s' % {
'editionTime': editionTimeString,
'editorIdEncoded': base64.encodestring(
destinationEditorId).strip(),
'format': format,
}
sourceBodyHistoryFilePath = os.path.join(
sourceBodyHistoryDirectoryPath, sourceBodyHistoryFileName)
destinationBodyHistoryFilePath = os.path.join(
destinationBodyHistoryDirectoryPath,
destinationBodyHistoryFileName)
sourceBodyHistoryFile = open(sourceBodyHistoryFilePath, 'rb')
destinationBodyHistoryFile = open(
destinationBodyHistoryFilePath, 'wb')
destinationBodyHistoryFile.write(sourceBodyHistoryFile.read())
sourceBodyHistoryFile.close()
destinationBodyHistoryFile.close()
return None
def exportVirtualServer(self, virtualServerId, exportDirectoryPath):
exitCode = ObjectsServer.exportVirtualServer(
self, virtualServerId, exportDirectoryPath)
if exitCode is not None:
return exitCode
virtualServer = self.virtualServers[virtualServerId]
hostName = extractApplicationHostName(virtualServerId)
virtualServerDataDirectoryPath = os.path.join(
self.dataDirectoryPath, hostName)
objectsDirectoryPath = os.path.join(
virtualServerDataDirectoryPath, self.applicationRole)
exportObjectsDirectoryPath = os.path.join(
exportDirectoryPath, self.applicationRole)
for id in virtualServer.objects.keys():
serverHostNameAndPortNotUsed, serverRoleNotUsed, localId = \
splitId(id)
sourceBodyFilePath = os.path.join(
objectsDirectoryPath, localId)
exportBodyFilePath = os.path.join(
exportObjectsDirectoryPath, localId)
if not os.access(sourceBodyFilePath, os.F_OK):
continue
if not os.access(exportDirectoryPath, os.F_OK):
os.mkdir(exportDirectoryPath)
os.chmod(exportDirectoryPath, 0750)
if not os.access(exportObjectsDirectoryPath, os.F_OK):
os.mkdir(exportObjectsDirectoryPath)
os.chmod(exportObjectsDirectoryPath, 0750)
sourceBodyFile = open(sourceBodyFilePath, 'rb')
exportBodyFile = open(exportBodyFilePath, 'wb')
os.chmod(exportBodyFilePath, 0640)
exportBodyFile.write(sourceBodyFile.read())
sourceBodyFile.close()
exportBodyFile.close()
sourceBodyHistoryDirectoryPath = os.path.join(
objectsDirectoryPath, localId + '-history')
exportBodyHistoryDirectoryPath = os.path.join(
exportObjectsDirectoryPath, localId + '-history')
if not os.access(sourceBodyHistoryDirectoryPath, os.F_OK):
continue
if not os.access(exportBodyHistoryDirectoryPath, os.F_OK):
os.mkdir(exportBodyHistoryDirectoryPath)
os.chmod(exportBodyHistoryDirectoryPath, 0750)
bodyHistoryFileNames = os.listdir(
sourceBodyHistoryDirectoryPath)
for bodyHistoryFileName in bodyHistoryFileNames:
sourceBodyHistoryFilePath = os.path.join(
sourceBodyHistoryDirectoryPath, bodyHistoryFileName)
exportBodyHistoryFilePath = os.path.join(
exportBodyHistoryDirectoryPath, bodyHistoryFileName)
sourceBodyHistoryFile = open(sourceBodyHistoryFilePath, 'rb')
exportBodyHistoryFile = open(exportBodyHistoryFilePath, 'wb')
os.chmod(exportBodyHistoryFilePath, 0640)
exportBodyHistoryFile.write(sourceBodyHistoryFile.read())
sourceBodyHistoryFile.close()
exportBodyHistoryFile.close()
return None
def getLastObjectIds(self, objectsCount, possibleAuthorsSet,
possibleReadersSet, possibleWritersSet):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
isAdmin = self.isAdmin()
try:
possibleAuthorIds = getSetContainedIds(
possibleAuthorsSet, ['people'])
except faults.UncountableGroup:
possibleAuthorIds = 'everybody'
try:
possibleReaderIds = getSetContainedIds(
possibleReadersSet, ['people'])
except faults.UncountableGroup:
possibleReaderIds = 'everybody'
try:
possibleWriterIds = getSetContainedIds(
possibleWritersSet, ['people'])
except faults.UncountableGroup:
possibleWriterIds = 'everybody'
objectIds = virtualServer.objects.keys()
def modificationTimeSorter(xId, yId,
virtualServer = virtualServer):
return cmp(virtualServer.loadObjectCore(yId).modificationTime,
virtualServer.loadObjectCore(xId).modificationTime)
objectIds.sort(modificationTimeSorter)
result = []
for objectId in objectIds:
object = virtualServer.loadObjectCore(objectId)
if not isAdmin and not getProxyForServerRole(
'authentication').setContainsUser(object.readersSet):
continue
if not self.getLastObjectIds_filter(
possibleAuthorIds, 1, object.authorsSet):
continue
if not self.getLastObjectIds_filter(
possibleReaderIds, 1, object.readersSet):
continue
if not self.getLastObjectIds_filter(
possibleWriterIds, 1, object.writersSet):
continue
result.append(objectId)
if objectsCount != -1 and len(result) >= objectsCount:
break
return result
def getObjectDiffXmlRpc(self, objectId, editionTime):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
object = virtualServer.loadObjectCore(objectId)
if not self.isAdmin() \
and not getProxyForServerRole('authentication'
).setContainsUser(object.writersSet):
raise faults.UserAccessDenied()
result = object.getBodyDiff(editionTime)
if result is None:
raise faults.MissingItem(objectId)
result['diff'] = [ utf8(line) for line in result['diff']]
return result
def getObjectDocBookChapterXmlRpc(self, objectId):
object = self.getObjectCore(objectId)
object.acquireNonCore()
try:
result = object.getDocBookChapter()
finally:
object.releaseNonCore()
return utf8(result)
def getObjectHistory(self, objectId):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
object = virtualServer.loadObjectCore(objectId)
if not self.isAdmin() \
and not getProxyForServerRole('authentication'
).setContainsUser(object.writersSet):
raise faults.UserAccessDenied()
return object.getBodyHistory()
def getObjectLatexChapterXmlRpc(self, objectId):
object = self.getObjectCore(objectId)
object.acquireNonCore()
try:
result = object.getLatexChapter()
finally:
object.releaseNonCore()
return utf8(result)
def getObjectVersionXmlRpc(self, objectId, editionTime):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
object = virtualServer.loadObjectCore(objectId)
if not self.isAdmin() \
and not getProxyForServerRole('authentication'
).setContainsUser(object.writersSet):
raise faults.UserAccessDenied()
result = object.getBodyVersion(editionTime)
if result is None:
raise faults.MissingItem(objectId)
result['body'] = utf8(result['body'])
return result
def importVirtualServer(self, virtualServerId, importDirectoryPath):
virtualServer = ObjectsServer.importVirtualServer(
self, virtualServerId, importDirectoryPath)
if virtualServer is None:
return None
hostName = extractApplicationHostName(virtualServerId)
virtualServerDataDirectoryPath = os.path.join(
self.dataDirectoryPath, hostName)
importObjectsDirectoryPath = os.path.join(
importDirectoryPath, self.applicationRole)
objectsDirectoryPath = os.path.join(
virtualServerDataDirectoryPath, self.applicationRole)
for id in virtualServer.objects.keys():
serverHostNameAndPortNotUsed, serverRoleNotUsed, localId = \
splitId(id)
importBodyFilePath = os.path.join(
importObjectsDirectoryPath, localId)
destinationBodyFilePath = os.path.join(
objectsDirectoryPath, localId)
if not os.access(importBodyFilePath, os.F_OK):
continue
if not os.access(virtualServerDataDirectoryPath, os.F_OK):
os.mkdir(virtualServerDataDirectoryPath)
os.chmod(virtualServerDataDirectoryPath, 0750)
if not os.access(objectsDirectoryPath, os.F_OK):
os.mkdir(objectsDirectoryPath)
os.chmod(objectsDirectoryPath, 0750)
importBodyFile = open(importBodyFilePath, 'rb')
destinationBodyFile = open(destinationBodyFilePath, 'wb')
os.chmod(destinationBodyFilePath, 0640)
destinationBodyFile.write(importBodyFile.read())
importBodyFile.close()
destinationBodyFile.close()
importBodyHistoryDirectoryPath = os.path.join(
importObjectsDirectoryPath, localId + '-history')
destinationBodyHistoryDirectoryPath = os.path.join(
objectsDirectoryPath, localId + '-history')
if not os.access(importBodyHistoryDirectoryPath, os.F_OK):
continue
if not os.access(destinationBodyHistoryDirectoryPath, os.F_OK):
os.mkdir(destinationBodyHistoryDirectoryPath)
os.chmod(destinationBodyHistoryDirectoryPath, 0750)
bodyHistoryFileNames = os.listdir(
importBodyHistoryDirectoryPath)
for bodyHistoryFileName in bodyHistoryFileNames:
importBodyHistoryFilePath = os.path.join(
importBodyHistoryDirectoryPath, bodyHistoryFileName)
destinationBodyHistoryFilePath = os.path.join(
destinationBodyHistoryDirectoryPath, bodyHistoryFileName)
importBodyHistoryFile = open(importBodyHistoryFilePath, 'rb')
destinationBodyHistoryFile = open(
destinationBodyHistoryFilePath, 'wb')
destinationBodyHistoryFile.write(importBodyHistoryFile.read())
importBodyHistoryFile.close()
destinationBodyHistoryFile.close()
return virtualServer
def modifyObjectXmlRpc(self, objectImport):
objectChanges = commonTools.importThing(objectImport)
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
object = virtualServer.loadObjectCore(objectChanges.id)
object.acquireNonCore()
try:
if not object.canBeModified():
raise faults.ReadOnlyObject()
if not self.canModifyObject(object.id) or not (
self.isAdmin()
or not objectChanges.hasSlotName('writersSet')
or getProxyForServerRole('authentication'
).setContainsUser(
objectChanges.getSlot('writersSet').getValue())):
if not object.canBeModifiedByClient():
raise faults.UserAccessDenied()
object.checkModifyIsPossible(objectChanges)
oldFormat = object.format
oldBody = object.body
oldLastEditorId = object.lastEditorId
oldEditionTime = object.editionTime
object.modify(objectChanges)
if object.body != oldBody:
if oldBody is not None:
object.saveBodyHistory(oldFormat, oldBody, oldLastEditorId,
oldEditionTime)
object.saveNonCore()
finally:
object.releaseNonCore()
virtualServer.markObjectAsDirty(object)
invalidateValue(object.id)
return object.version
def registerPublicMethods(self):
ObjectsServer.registerPublicMethods(self)
self.registerPublicMethod('canGetObjectHistory')
self.registerPublicMethod('getObjectDiff',
self.getObjectDiffXmlRpc)
self.registerPublicMethod('getObjectDocBookChapter',
self.getObjectDocBookChapterXmlRpc)
self.registerPublicMethod('getObjectHistory')
self.registerPublicMethod('getObjectLatexChapter',
self.getObjectLatexChapterXmlRpc)
self.registerPublicMethod('getObjectVersion',
self.getObjectVersionXmlRpc)
self.registerPublicMethod('search')
def removeVirtualServerHistory(self, dispatcherId):
exitCode = ObjectsServer.removeVirtualServerHistory(
self, dispatcherId)
if exitCode is not None:
return exitCode
virtualServerId = '%s/%s' % (dispatcherId, self.applicationRole)
virtualServer = self.getVirtualServer(virtualServerId)
hostName = extractApplicationHostName(dispatcherId)
virtualServerDataDirectoryPath = os.path.join(
self.dataDirectoryPath, hostName)
objectsDirectoryPath = os.path.join(
virtualServerDataDirectoryPath, self.applicationRole)
for id in virtualServer.objects.keys():
serverHostNameAndPortNotUsed, serverRoleNotUsed, localId = \
splitId(id)
bodyHistoryDirectoryPath = os.path.join(
objectsDirectoryPath, localId + '-history')
if not os.access(bodyHistoryDirectoryPath, os.F_OK):
continue
bodyHistoryFileNames = os.listdir(bodyHistoryDirectoryPath)
for bodyHistoryFileName in bodyHistoryFileNames:
bodyHistoryFilePath = os.path.join(
bodyHistoryDirectoryPath, bodyHistoryFileName)
os.remove(bodyHistoryFilePath)
os.rmdir(bodyHistoryDirectoryPath)
return None
def repairVirtualServer(self, virtualServer, version):
changed = 0
if version < 3000:
for object in virtualServer.objects.values():
if object.body is not None:
changed = 1
object.saveBody()
del object.body
object.lastEditorId = 'eePeopleServer/8' # = Manou
object.editionTime = object.modificationTime
elif object.__dict__.has_key('body'):
changed = 1
del object.body
if object.__dict__.has_key('state'):
changed = 1
object.writersSet = object.authorsSet
if object.writersSet is not None:
object.writersSet = object.writersSet[:]
if object.state != 'published':
object.readersSet = [
'eePeopleServer/1', # = Manou
]
del object.state
if version < 4000:
changed = virtualServer.admin.repair(4000) or changed
for id, object in virtualServer.objects.items():
newId = repairId(id)
if newId:
changed = 1
del virtualServer.objects[id]
virtualServer.objects[newId] = object
changed = object.repair(4000) or changed
if not object.__dict__.has_key('language'):
changed = 1
object.language = 'fr'
if version < 5001:
hostName = extractApplicationHostName(
virtualServer.virtualServerId)
virtualServerDataDirectoryPath = os.path.join(
self.dataDirectoryPath, hostName)
objectsDirectoryPath = os.path.join(
virtualServerDataDirectoryPath, self.applicationRole)
for id in virtualServer.objects.keys():
serverHostNameAndPort, serverRole, localId = splitId(id)
bodyFilePath = os.path.join(objectsDirectoryPath, localId)
if not os.access(bodyFilePath, os.F_OK):
continue
bodyHistoryDirectoryPath = os.path.join(
objectsDirectoryPath, localId + '-history')
if not os.access(bodyHistoryDirectoryPath, os.F_OK):
continue
fileNames = os.listdir(bodyHistoryDirectoryPath)
if not fileNames:
continue
for fileName in fileNames:
editionTimeString, editorLocalId, format = \
fileName.split('-')
if len(editorLocalId) > 4:
# The editorId is already encoded into base64.
continue
editorId = 'glasnost://%s/people/%s' % (
hostName, editorLocalId)
newFileName = \
'%(editionTime)s-%(editorIdEncoded)s-%(format)s' % {
'editionTime': editionTimeString,
'editorIdEncoded': base64.encodestring(
editorId).strip(),
'format': format,
}
os.rename(
os.path.join(bodyHistoryDirectoryPath, fileName),
os.path.join(bodyHistoryDirectoryPath, newFileName))
if version < 5004:
changed = virtualServer.admin.repair(5004) or changed
hostName = extractApplicationHostName(
virtualServer.virtualServerId)
virtualServerDataDirectoryPath = os.path.join(
self.dataDirectoryPath, hostName)
objectsDirectoryPath = os.path.join(
virtualServerDataDirectoryPath, self.applicationRole)
for id, object in virtualServer.objects.items():
changed = object.repair(5004) or changed
serverHostNameAndPort, serverRole, localId = splitId(id)
bodyFilePath = os.path.join(objectsDirectoryPath, localId)
if not os.access(bodyFilePath, os.F_OK):
continue
file = open(bodyFilePath, 'rb')
body = file.read()
file.close()
repairedBody = body.replace('\r\n', '\n')
repairedBody = repairedBody.replace('\r', '\n')
if repairedBody != body:
file = open(bodyFilePath, 'wb')
os.chmod(bodyFilePath, 0640)
file.write(repairedBody)
file.close()
bodyHistoryDirectoryPath = os.path.join(
objectsDirectoryPath, localId + '-history')
if not os.access(bodyHistoryDirectoryPath, os.F_OK):
continue
fileNames = os.listdir(bodyHistoryDirectoryPath)
if not fileNames:
continue
for fileName in fileNames:
filePath = os.path.join(bodyHistoryDirectoryPath, fileName)
file = open(filePath, 'rb')
body = file.read()
file.close()
repairedBody = body.replace('\r\n', '\n')
repairedBody = repairedBody.replace('\r', '\n')
if repairedBody != body:
file = open(filePath, 'wb')
os.chmod(filePath, 0640)
file.write(repairedBody)
file.close()
if version <= 1021000:
admin = virtualServer.admin
if admin.id is None:
changed = 1
admin.id = '%s/__admin__' % virtualServer.virtualServerId
if changed:
virtualServer.markAllAsDirtyFIXME()
def search(self, searchTerms, scope, language):
searchTerms = iso8859_15(searchTerms)
serverId = getProxyForServerRole('translations').getServerId()
applicationToken = getApplicationToken()
params = []
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
isAdmin = self.isAdmin()
objectsLookedIn = []
# FIXME: Do not translate here. Should be done by the client.
multiCall = MultiCall()
for objectId, object in virtualServer.objects.items():
if not isAdmin \
and not getProxyForServerRole('authentication'
).setContainsUser(object.readersSet):
continue
if 'body' in scope:
object.loadBody()
for s in scope:
text = getattr(object, s)
if not text:
continue
sourcePath = 'self.%s' % s
getProxyForServerRole('translations').getTranslationInfos(
text, object.id, sourcePath, object.language,
[language], ignoreNew = 1, multiCall = multiCall)
objectsLookedIn.append(objectId)
if object.__dict__.has_key('body'):
del object.body
lazyResults = multiCall.call()
nbTerms = len(searchTerms.split(' '))
regexpOne = re.compile(
r'\b(%s)\b' % '|'.join(searchTerms.split(' ')),
re.LOCALE | re.IGNORECASE)
regexpAll = re.compile(searchTerms.replace(' ', '\s*'),
re.LOCALE | re.IGNORECASE)
result = []
scores = {}
for i in range(len(objectsLookedIn)):
objectId = objectsLookedIn[i]
translationInfos = lazyResults[i]()
text = translationInfos[0]
score = 0.0
if not text:
continue
rOne = regexpOne.findall(text)
if not rOne:
continue
rAll = regexpAll.findall(text)
if not rAll or nbTerms == 1:
score += 1.0*len(rOne)/nbTerms
else:
score += 1.3*len(rAll)+0.7*len(rOne)/nbTerms
score /= len(text)/200.0
scores[objectId] = scores.setdefault(objectId, 0) + score
return scores.items()
articlesServer = ArticlesServer()
if __name__ == "__main__":
articlesServer.launch(applicationName, applicationRole)