Viewing file: Repository.py (15.52 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/Xslt/Repository.py,v 1.45 2005/04/06 23:05:46 jkloth Exp $ """ XSLT and XPath extensions supporting the 4SS repository API
Copyright 2005 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
import sha, cStringIO
from Ft.Lib import boolean from Ft.Xml import Domlette from Ft.Xml.XPath import Conversions from Ft.Xml.Xslt import XsltElement, ContentInfo, AttributeInfo from Ft.Server import FTSERVER_NAMESPACE, RESERVED_NAMESPACE from Ft.Server.Server import FtServerServerException,Error
import FtssXsltBase from Ns import SCORE_NS
#def RepoUserName(context): # repo = context.processor._repository # return repo.getUserName() or ''
class TextSearchRepositoryElement(XsltElement): """ Invoke the full-text search to find text in the repository (Requires SWISH-E as supporting software) """
content = ContentInfo.Empty
legalAttrs = { 'query' : AttributeInfo.StringAvt( required=1, description='The string to search for'), }
def instantiate(self, context, processor): context.setProcessState(self)
queryString = Conversions.StringValue(self._query.evaluate(context))
repo = context.processor._repository results = repo.searchDocuments(queryString)
processor.writers[-1].startElement('Results') for result in results: processor.writers[-1].startElement('Match') processor.writers[-1].text(result) processor.writers[-1].endElement('Match')
processor.writers[-1].endElement('Results') return
class TextReindexRepositoryElement(XsltElement): """ Trigger a re-indexing for full-text in the repository (Requires SWISH-E as supporting software) """
content = ContentInfo.Empty legalAttrs = {}
def instantiate(self, context, processor): repo = context.processor._repository repo.reindex() return
class LoginElement(XsltElement): """ Log in a user and create a new repository session accordingly, establishing a session for the logged in user with implicit log in on all subsequent requests from that agent until timeout. Sessions also support the management of persistent state data. When the repo session eventually times out, the user is redirected to timeout-redirect on the next request. """ content = ContentInfo.Empty legalAttrs = { 'user' : AttributeInfo.StringAvt( required=1, description='The 4Suite user name'), 'password' : AttributeInfo.StringAvt( required=1, description='The 4Suite user password'), 'ttl' : AttributeInfo.NumberAvt( default=0, description=('The time to live (in seconds) for the session.' ' If omitted, the driver default is used (usually' ' 15 minutes)')), 'success-redirect' : AttributeInfo.StringAvt( description=('A URI to redirect to if the login succeeds.' ' Defaults to the current page.')), 'failure-redirect' : AttributeInfo.StringAvt( description=('A URI to redirect to if the login fails.' ' Defaults to the current page.')), 'timeout-redirect' : AttributeInfo.StringAvt( description=('A URI to redirect to for requests after the' ' session eventually times out. Defaults to the' ' current page.')), }
def instantiate(self, context, processor): from Ft.Server.Server.Http import Session from Ft.Server import RESERVED_NAMESPACE repo = context.processor._repository user = self._user.evaluate(context) password = sha.new(self._password.evaluate(context)).hexdigest() #print "Session-based login requested via fcore:login for user %s" % user processor.extensionParams[(RESERVED_NAMESPACE, 'login')] = ( user, password, self._ttl.evaluate(context), self._success_redirect.evaluate(context), self._failure_redirect.evaluate(context), self._timeout_redirect.evaluate(context), ) #SessionInvalidate(context) return
class CreateSessionElement(XsltElement): """ Create a new repository session. This allows implicit log in on all requests, and the management of persistent state data. """ content = ContentInfo.Empty legalAttrs = { 'key' : AttributeInfo.StringAvt( description=('The session key to use. If omitted, a session' ' key is generated for you.')), 'ttl' : AttributeInfo.NumberAvt( default=0, description=('The time to live for the session. If omitted,' ' the driver default is used (usually 15 minutes)')), #'id' : AttributeInfo.StringAvt(description='The session ID to attach'), }
def instantiate(self, context, processor): from Ft.Server.Server.Http import Session from Ft.Server import RESERVED_NAMESPACE repo = context.processor._repository id = repo.createSession(self._key.evaluate(context), self._ttl.evaluate(context)) handler = processor.extensionParams[(RESERVED_NAMESPACE, 'handler')] processor.extensionParams[(RESERVED_NAMESPACE, 'sessionId')] = id handler.session = Session.Create(id, handler.session_method) processor.writers[-1].text(unicode(id)) print "Session set to", id return
class _XsltSessionData: def __init__(self, type, value, baseURI=None): self.type = type self.value = value self.baseURI = baseURI return
class SessionDataElement(XsltElement): """ Sets a key/value pair in the data for the current session data, for persistence in the user agent If the "value" attribute is used, the resulting string is the session entry value. If this attribute is omitted, a node set is the resulting value, whose sole entry is the root node of the result tree fragment from instantiating the template that makes up the content of this element. """ content = ContentInfo.Template legalAttrs = { 'key' : AttributeInfo.StringAvt( required=1, description='The session key to use'), 'value' : AttributeInfo.StringAvt( description='A string value for the session datum') }
def instantiate(self, context, processor): key = self._key.evaluate(context) value = self._value.evaluate(context) repo = processor._repository if repo.hasSession(): if value: value = _XsltSessionData('string', value) else: processor.pushResultTree(self.baseUri) # Add a wrapper element to allow the tree to be parsed later processor.writers[-1].startElement("session-data-wrapper") try: self.processChildren(context, processor) finally: processor.writers[-1].endElement("session-data-wrapper") result = processor.popResult()
buf = cStringIO.StringIO() Domlette.Print(result, stream=buf) value = _XsltSessionData('nodeset', buf.getvalue(), self.baseUri)
repo.setSessionData(key, value) return
def HasSession(context): """ See if this connection is in a session """ repo = context.processor._repository if repo.hasSession(): return boolean.true return boolean.false
def SessionInvalidate(context): """ Destroy the current session """ print "Invalidating session at user request" try: repo = context.processor._repository if repo.hasSession(): repo.invalidateSession() return boolean.true else: return boolean.false except: return boolean.false
def SessionData(context, key): """ Session data is stored under a session ID (a UUID string) and takes the form of zero or more key-value pairs. Each key is a unique string, and each value is either a string or a node-set.
This XSLT extension function coerces the given key to its string-value and returns from the current session the node-set that is associated with that key. If the key does not exist in the current session, or if there is no current session, then an empty node-set is returned. There is no way to distinguish between an empty node-set as an indication of such an error and an empty node-set as the legitimate value for the given key. """
key = Conversions.StringValue(key) repo = context.processor._repository rv = [] if repo.hasSession(): try: data = repo.getSessionData(key) if data is not None: print "Session data found for key '%s'" % key if isinstance(data, _XsltSessionData): # Restore wrapped data if data.type == 'string': rv = data.value elif data.type == 'nodeset': doc = context.processor._docReader.parseString( data.value, data.baseURI, driver=repo._driver) # Remove the wrapper element wrapper = doc.documentElement while wrapper.firstChild: doc.appendChild(wrapper.firstChild) doc.removeChild(wrapper) # Return as a nodeset rv = [doc] else: print "Malformed session data instance: %r" % data else: print "Non-XSLT created session data!" rv = data else: print "There is a current Session, but it has no data for key '%s'." % key except: print "There was an error getting the Session data." else: print "There is no current Session." return rv
def DeleteSessionData(context, key): """ Delete one of the key/value pairs stored in the session data """ key = Conversions.StringValue(key) try: repo = context.processor._repository if not repo.hasSession(): return '' print "Remove Session Data for %s" % (key) repo.deleteSessionData(key) return '' except: return ''
def GetAllDocumentDefinitionPaths(context, path=None): """ Get the resource (path) given a user or group name """ path = Conversions.StringValue(path) base = FtssXsltBase.FetchBaseObject(context.processor,path) root = base.getRoot()
doc = context.node.rootNode return map(doc.createTextNode, root.getAllDocumentDefinitionPaths())
def GetUserOrGroupByName(context, name): """ Given a user name, return the user resource path """ repo = context.processor._repository name = Conversions.StringValue(name) try: user_or_group = repo.fetchUserOrGroupByName(name) except FtServerServerException, e: if e.errorCode == Error.PERMISSION_DENIED: return ""; raise if user_or_group is None: return '' else: return user_or_group.getAbsolutePath()
def HashString(context, rawString): """ Return a hash for a string DEPRECATED - use f:sha-hash() """ print 'Notice: please use extension function "f:sha-hash()"' \ ' rather than the deprecated "fcore:hash-string()"' rstring = Conversions.StringValue(rawString) return sha.new(rstring).hexdigest()
class RollbackElement(XsltElement): """ Abort the current transaction (governing the current XSLT operation) which will undo all repository operations """
content = ContentInfo.Empty
legalAttrs = {}
def instantiate(self, context, processor): context.setProcessState(self) processor.extensionParams[(RESERVED_NAMESPACE, 'rollback')] = 1 return
def GetCurrentUser(context): """ Get the resource (path) for the current user """ repo = context.processor._repository user = repo.getCurrentUser() if user is None: return '' else: return user.getAbsolutePath()
def _GetUserName(context): print 'Notice: please use extension function "fcore:get-current-username()"' \ ' rather than the deprecated "fcore:get-user-name()"' return GetCurrentUserName(context)
def GetCurrentUserName(context): """ Get the name (not the resource) of the current user """ repo = context.processor._repository user = repo.getCurrentUser() if user is None: #return "Anonymous" # should be 'world'? from Ft.Server.Common.AclConstants import ANONYMOUS_USER_NAME return ANONYMOUS_USER_NAME else: return user.getUsername()
def RepoPathToUriFunc(context, path): """ Convert a full repository URI e.g. ("ftss:///spam/eggs") to a repository path (e.g. "/spam/eggs") """ path = Conversions.StringValue(path) from Ft.Server.Server.Drivers.PathImp import RepoPathToUri return RepoPathToUri(path)
def UriToRepoPath(context, uri): """ Convert a repository path (e.g. "/spam/eggs") to a proper repository URI e.g. ("ftss:///spam/eggs") """ uri = Conversions.StringValue(uri) if uri.startswith('ftss://'): return uri[7:] else: return uri
def NormalizeUri(context, uri, base=None): """ Resolve a relative URI against a given base, in effect just turning it into a proper repository URI (ftss://...) if no base is given for a relative path """ from Ft.Lib.Uri import IsAbsolute from Ft.Server.Server.Drivers.PathImp import RepoPathToUri from Ft.Server.Server.Drivers import FtssInputSource uri = Conversions.StringValue(uri) if IsAbsolute(uri): return uri if base: if not IsAbsolute(base): base = RepoPathToUri(base) normalized = FtssInputSource.FTSS_RESOLVER.normalize(rel, base) return normalized return RepoPathToUri(uri)
ExtFunctions = { #(SCORE_NS, 'repo-user-name'): RepoUserName, (SCORE_NS, 'has-session'): HasSession, (SCORE_NS, 'get-current-user'): GetCurrentUser, (SCORE_NS, 'get-current-username'): GetCurrentUserName, (SCORE_NS, 'get-user-name'): _GetUserName, # deprecated! (SCORE_NS, 'get-user-or-group'): GetUserOrGroupByName, #(NS, 'create'): SessionCreate, (SCORE_NS, 'session-invalidate'): SessionInvalidate, #(NS, 'reattach'): SessionReattach, (SCORE_NS, 'session-data'): SessionData, (SCORE_NS, 'delete-session-data'): DeleteSessionData, (SCORE_NS, 'hash-string'): HashString, (SCORE_NS, "get-all-document-definition-paths"): GetAllDocumentDefinitionPaths, (SCORE_NS, 'repo-path-to-uri'): RepoPathToUriFunc, (SCORE_NS, 'uri-to-repo-path'): UriToRepoPath, (SCORE_NS, 'normalize-uri'): NormalizeUri, }
ExtElements = { (SCORE_NS, 'rollback'): RollbackElement, (SCORE_NS, 'login'): LoginElement, (SCORE_NS, 'create-session'): CreateSessionElement, (SCORE_NS, 'session-data'): SessionDataElement, (SCORE_NS, 'repo-text-search'): TextSearchRepositoryElement, (SCORE_NS, 'repo-text-reindex'): TextReindexRepositoryElement, }
|