diff --git a/src/oaipmh/common.py b/src/oaipmh/common.py index c602ada..387d086 100644 --- a/src/oaipmh/common.py +++ b/src/oaipmh/common.py @@ -46,6 +46,46 @@ def getField(self, name): __getitem__ = getField +class About(object): + def __init__(self, element, baseURL, identifier, datestamp, metadataNamespace, harvestDate, repositoryID=None, repositoryName=None): + self._element = element + # force identifier to be a string, it might be + # an lxml.etree._ElementStringResult... + try: + self._identifier = str(identifier) + except UnicodeEncodeError: + self._identifier = unicode(identifier) + self._datestamp = datestamp + self._baseURL = baseURL + self._metadataNamespace = metadataNamespace + self._harvestDate = harvestDate + self._repositoryID = repositoryID + self._repositoryName = repositoryName + + def element(self): + return self._element + + def identifier(self): + return self._identifier + + def datestamp(self): + return self._datestamp + + def baseURL(self): + return self._baseURL + + def metadataNamespace(self): + return self._metadataNamespace + + def harvestDate(self): + return self._harvestDate + + def repositoryID(self): + return self._repositoryID + + def repositoryName(self): + return self._repositoryName + class Identify(object): def __init__(self, repositoryName, baseURL, protocolVersion, adminEmails, earliestDatestamp, deletedRecord, granularity, compression, diff --git a/src/oaipmh/server.py b/src/oaipmh/server.py index ae843e8..07804e4 100644 --- a/src/oaipmh/server.py +++ b/src/oaipmh/server.py @@ -1,6 +1,8 @@ from lxml.etree import ElementTree, Element, SubElement from lxml import etree from datetime import datetime +import base64 + try: from urllib.parse import urlencode, quote, unquote except ImportError: @@ -48,6 +50,8 @@ def getRecord(self, **kw): self._outputHeader(e_record, header) if not header.isDeleted(): self._outputMetadata(e_record, kw['metadataPrefix'], metadata) + if about: + self._outputAbout(e_record, about) return envelope def getMetadata(self, **kw): @@ -131,7 +135,8 @@ def outputFunc(element, records, token_kw): self._outputHeader(e_record, header) if not header.isDeleted(): self._outputMetadata(e_record, metadataPrefix, metadata) - # XXX about + if about: + self._outputAbout(e_record, about) self._outputResuming( e_listRecords, self._server.listRecords, @@ -243,6 +248,29 @@ def _outputMetadata(self, element, metadata_prefix, metadata): self._metadata_registry.writeMetadata( metadata_prefix, e_metadata, metadata) + def _outputAbout(self, element, about): + if about.baseURL(): + e_about = SubElement(element, nsoai('about')) + e_provenance = SubElement(e_about, nsoai('provenance')) + e_provenance.set ('xmlns', 'http://www.openarchives.org/OAI/2.0/provenance') + e_provenance.set ('{%s}schemaLocation' % NS_XSI, 'http://www.openarchives.org/OAI/2.0/provenance http://www.openarchives.org/OAI/2.0/provenance.xsd') + e_originDescription = SubElement(e_provenance, nsoai('originDescription')) + e_originDescription.set ('harvestDate', datetime_to_datestamp(about.harvestDate())) + e_originDescription.set ('altered', "true") + e_baseURL = SubElement(e_originDescription, nsoai('baseURL')) + e_baseURL.text = about.baseURL() + e_identifier = SubElement(e_originDescription, nsoai('identifier')) + e_identifier.text = about.identifier() + e_datestamp = SubElement(e_originDescription, nsoai('datestamp')) +# e_datestamp.text = datetime_to_datestamp(about.datestamp()) + e_datestamp.text = about.datestamp() + e_metadataNamespace = SubElement(e_originDescription, nsoai('metadataNamespace')) + e_metadataNamespace.text = about.metadataNamespace() + e_repositoryID = SubElement(e_originDescription, nsoai('repositoryID')) + e_repositoryID.text = about.repositoryID() + e_repositoryName = SubElement(e_originDescription, nsoai('repositoryName')) + e_repositoryName.text = about.repositoryName() + class ServerBase(common.ResumptionOAIPMH): """A server that responds to messages by returning OAI-PMH compliant XML. @@ -452,11 +480,13 @@ def encodeResumptionToken(kw, cursor): until = kw.get('until') if until is not None: kw['until'] = datetime_to_datestamp(until) - return quote(urlencode(kw)) +# return quote(urlencode(kw)) + return base64.b64encode(bytes(urlencode(kw), encoding="utf-8")) def decodeResumptionToken(token): - token = str(unquote(token)) - +# token = str(unquote(token)) + token = base64.b64decode(token).decode('utf-8') + try: kw = parse_qs(token, True, True) except ValueError: @@ -468,6 +498,7 @@ def decodeResumptionToken(token): if key == 'from_' or key == 'until': value = datestamp_to_datetime(value) result[key] = value + try: cursor = int(result.pop('cursor')) except (KeyError, ValueError):