diff -Naur Zope-4.5.3/OFS/XMLExportImport.py Zope-4.5.3-Nexedi/OFS/XMLExportImport.py --- Zope-4.5.3/OFS/XMLExportImport.py 1970-01-01 01:00:00.000000000 +0100 +++ Zope-4.5.3-Nexedi/OFS/XMLExportImport.py 2021-03-09 16:11:55.000000000 +0100 @@ -0,0 +1,124 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Foundation and Contributors. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +from base64 import encodestring +from cStringIO import StringIO +from ZODB.serialize import referencesf +from ZODB.ExportImport import TemporaryFile, export_end_marker +from ZODB.utils import p64 +from ZODB.utils import u64 +from Shared.DC.xml import ppml + + +magic='<?xm' # importXML(jar, file, clue)} + +def XMLrecord(oid, len, p): + q=ppml.ToXMLUnpickler + f=StringIO(p) + u=q(f) + id=u64(oid) + aka=encodestring(oid)[:-1] + u.idprefix=str(id)+'.' + p=u.load().__str__(4) + if f.tell() < len: + p=p+u.load().__str__(4) + String=' <record id="%s" aka="%s">\n%s </record>\n' % (id, aka, p) + return String + +def exportXML(jar, oid, file=None): + + if file is None: file=TemporaryFile() + elif type(file) is str: file=open(file,'w+b') + write=file.write + write('<?xml version="1.0"?>\012<ZopeData>\012') + ref=referencesf + oids=[oid] + done_oids={} + done=done_oids.has_key + load=jar._storage.load + while oids: + oid=oids[0] + del oids[0] + if done(oid): continue + done_oids[oid]=1 + try: + try: + p, serial = load(oid) + except TypeError: + # Some places inside the ZODB 3.9 still want a version + # argument, for example TmpStore from Connection.py + p, serial = load(oid, None) + except: + pass # Ick, a broken reference + else: + ref(p, oids) + write(XMLrecord(oid,len(p),p)) + write('</ZopeData>\n') + return file + +class zopedata: + def __init__(self, parser, tag, attrs): + self.file=parser.file + write=self.file.write + write('ZEXP') + + def append(self, data): + file=self.file + write=file.write + pos=file.tell() + file.seek(pos) + write(data) + +def start_zopedata(parser, tag, data): + return zopedata(parser, tag, data) + +def save_zopedata(parser, tag, data): + file=parser.file + write=file.write + pos=file.tell() + file.seek(pos) + write(export_end_marker) + +def save_record(parser, tag, data): + file=parser.file + write=file.write + pos=file.tell() + file.seek(pos) + a=data[1] + if a.has_key('id'): oid=a['id'] + oid=p64(int(oid)) + v='' + for x in data[2:]: + v=v+x + l=p64(len(v)) + v=oid+l+v + return v + +def importXML(jar, file, clue=''): + import xml.parsers.expat + if type(file) is str: + file=open(file, 'rb') + outfile=TemporaryFile() + data=file.read() + F=ppml.xmlPickler() + F.end_handlers['record'] = save_record + F.end_handlers['ZopeData'] = save_zopedata + F.start_handlers['ZopeData'] = start_zopedata + F.binary=1 + F.file=outfile + p=xml.parsers.expat.ParserCreate() + p.CharacterDataHandler=F.handle_data + p.StartElementHandler=F.unknown_starttag + p.EndElementHandler=F.unknown_endtag + r=p.Parse(data) + outfile.seek(0) + return jar.importFile(outfile,clue) diff -Naur Zope-4.5.3/Shared/DC/xml/__init__.py Zope-4.5.3-Nexedi/Shared/DC/xml/__init__.py --- Zope-4.5.3/Shared/DC/xml/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ Zope-4.5.3-Nexedi/Shared/DC/xml/__init__.py 2021-03-09 16:13:49.000000000 +0100 @@ -0,0 +1,12 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Foundation and Contributors. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## diff -Naur Zope-4.5.3/Shared/DC/xml/ppml.py Zope-4.5.3-Nexedi/Shared/DC/xml/ppml.py --- Zope-4.5.3/Shared/DC/xml/ppml.py 1970-01-01 01:00:00.000000000 +0100 +++ Zope-4.5.3-Nexedi/Shared/DC/xml/ppml.py 2021-03-09 16:13:49.000000000 +0100 @@ -0,0 +1,597 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Foundation and Contributors. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE +# +############################################################################## +"""Provide conversion between Python pickles and XML +""" + +from pickle import * +import struct +import base64 +import re +from marshal import loads as mloads +from xyap import NoBlanks +from xyap import xyap + +binary = re.compile('[^\x1f-\x7f]').search + + +def escape(s, encoding='repr'): + if binary(s) and isinstance(s, str): + s = base64.encodestring(s)[:-1] + encoding = 'base64' + elif '>' in s or '<' in s or '&' in s: + if not ']]>' in s: + s = '<![CDATA[' + s + ']]>' + encoding = 'cdata' + else: + s = s.replace('&', '&') + s = s.replace('>', '>') + s = s.replace('<', '<') + return encoding, s + +def unescape(s, encoding): + if encoding == 'base64': + return base64.decodestring(s) + else: + s = s.replace('<', '<') + s = s.replace('>', '>') + return s.replace('&', '&') + +class Global: + def __init__(self, module, name): + self.module = module + self.name = name + + def __str__(self, indent=0): + if hasattr(self, 'id'): + id = ' id="%s"' % self.id + else: + id = '' + name = self.__class__.__name__.lower() + return '%s<%s%s name="%s" module="%s"/>\n' % ( + ' ' * indent, name, id, self.name, self.module) + +class Scalar: + def __init__(self, v): + self._v = v + + def value(self): + return self._v + + def __str__(self, indent=0): + if hasattr(self, 'id'): + id = ' id="%s"' % self.id + else: + id = '' + name = self.__class__.__name__.lower() + return '%s<%s%s>%s</%s>\n' % ( + ' ' * indent, name, id, self.value(), name) + +class Long(Scalar): + def value(self): + result = str(self._v) + if result[-1:] == 'L': + return result[:-1] + return result + +class String(Scalar): + def __init__(self, v, encoding=''): + encoding, v = escape(v, encoding) + self.encoding = encoding + self._v = v + + def __str__(self, indent=0): + if hasattr(self,'id'): + id = ' id="%s"' % self.id + else: + id = '' + if hasattr(self, 'encoding'): + encoding = ' encoding="%s"' % self.encoding + else: + encoding = '' + name = self.__class__.__name__.lower() + return '%s<%s%s%s>%s</%s>\n' % ( + ' ' * indent, name, id, encoding, self.value(), name) + +class Unicode(String): + def __init__(self, v, encoding): + v = unicode(v, encoding) + String.__init__(self, v) + + def value(self): + return self._v.encode('utf-8') + +class Wrapper: + def __init__(self, v): + self._v = v + + def value(self): + return self._v + + def __str__(self, indent=0): + if hasattr(self, 'id'): + id = ' id="%s"' % self.id + else: + id = '' + name = self.__class__.__name__.lower() + v = self._v + i = ' ' * indent + if isinstance(v, Scalar): + return '%s<%s%s>%s</%s>\n' % (i, name, id, str(v)[:-1], name) + else: + try: + v = v.__str__(indent + 2) + except TypeError: + v = v.__str__() + return '%s<%s%s>\n%s%s</%s>\n' % (i, name, id, v, i, name) + +class Collection: + def __str__(self, indent=0): + if hasattr(self, 'id'): + id = ' id="%s"' % self.id + else: + id = '' + name = self.__class__.__name__.lower() + i = ' ' * indent + if self: + return '%s<%s%s>\n%s%s</%s>\n' % ( + i, name, id, self.value(indent + 2), i, name) + else: + return '%s<%s%s/>\n' % (i, name, id) + +class Dictionary(Collection): + def __init__(self): + self._d = [] + + def __len__(self): + return len(self._d) + + def __setitem__(self, k, v): + self._d.append((k, v)) + + def value(self, indent): + return ''.join( + map(lambda i, ind=' ' * indent, indent=indent + 4: + '%s<item>\n' + '%s' + '%s' + '%s</item>\n' + % + (ind, + Key(i[0]).__str__(indent), + Value(i[1]).__str__(indent), + ind), + self._d + )) + +class Sequence(Collection): + def __init__(self, v=None): + if not v: + v = [] + self._subs = v + + def __len__(self): + return len(self._subs) + + def append(self, v): + self._subs.append(v) + + def extend(self, v): + self._subs.extend(v) + + def _stringify(self, v, indent): + try: + return v.__str__(indent + 2) + except TypeError: + return v.__str__() + + def value(self, indent): + return ''.join(map( + lambda v, indent=indent: self._stringify(v, indent), + self._subs)) + +class none: + def __str__(self, indent=0): + return ' ' * indent + '<none/>\n' +none = none() + +class Reference(Scalar): + def __init__(self, v): + self._v = v + + def __str__(self, indent=0): + v = self._v + name = self.__class__.__name__.lower() + return '%s<%s id="%s"/>\n' % (' ' * indent, name, v) + +Get = Reference + +class Object(Sequence): + def __init__(self, klass, args): + self._subs = [Klass(klass), args] + + def __setstate__(self, v): + self.append(State(v)) + +class Int(Scalar): pass +class Float(Scalar): pass +class List(Sequence): pass +class Tuple(Sequence): pass +class Key(Wrapper): pass +class Value(Wrapper): pass +class Klass(Wrapper): pass +class State(Wrapper): pass +class Pickle(Wrapper): pass +class Persistent(Wrapper): pass + + +class ToXMLUnpickler(Unpickler): + def load(self): + return Pickle(Unpickler.load(self)) + + dispatch = {} + dispatch.update(Unpickler.dispatch) + + def persistent_load(self, v): + return Persistent(v) + + def load_persid(self): + pid = self.readline()[:-1] + self.append(self.persistent_load(String(pid))) + dispatch[PERSID] = load_persid + + def load_none(self): + self.append(none) + dispatch[NONE] = load_none + + def load_int(self): + self.append(Int(int(self.readline()[:-1]))) + dispatch[INT] = load_int + + def load_binint(self): + self.append(Int(mloads('i' + self.read(4)))) + dispatch[BININT] = load_binint + + def load_binint1(self): + self.append(Int(ord(self.read(1)))) + dispatch[BININT1] = load_binint1 + + def load_binint2(self): + self.append(Int(mloads('i' + self.read(2) + '\000\000'))) + dispatch[BININT2] = load_binint2 + + def load_long(self): + self.append(Long(long(self.readline()[:-1], 0))) + dispatch[LONG] = load_long + + def load_float(self): + self.append(Float(float(self.readline()[:-1]))) + dispatch[FLOAT] = load_float + + def load_binfloat(self, unpack=struct.unpack): + self.append(Float(unpack('>d', self.read(8))[0])) + dispatch[BINFLOAT] = load_binfloat + + def load_string(self): + rep = self.readline()[:-1] + for q in "\"'": + if rep.startswith(q): + if not rep.endswith(q): + raise ValueError, 'insecure string pickle' + rep = rep[len(q):-len(q)] + break + else: + raise ValueError, 'insecure string pickle' + self.append(String(rep.decode('string-escape'))) + dispatch[STRING] = load_string + + def load_binstring(self): + len = mloads('i' + self.read(4)) + self.append(String(self.read(len))) + dispatch[BINSTRING] = load_binstring + + def load_unicode(self): + self.append(Unicode(self.readline()[:-1],'raw-unicode-escape')) + dispatch[UNICODE] = load_unicode + + def load_binunicode(self): + len = mloads('i' + self.read(4)) + self.append(Unicode(self.read(len),'utf-8')) + dispatch[BINUNICODE] = load_binunicode + + def load_short_binstring(self): + len = ord(self.read(1)) + self.append(String(self.read(len))) + dispatch[SHORT_BINSTRING] = load_short_binstring + + def load_tuple(self): + k = self.marker() + self.stack[k:] = [Tuple(self.stack[k + 1:])] + dispatch[TUPLE] = load_tuple + + def load_empty_tuple(self): + self.stack.append(Tuple()) + dispatch[EMPTY_TUPLE] = load_empty_tuple + + def load_empty_list(self): + self.stack.append(List()) + dispatch[EMPTY_LIST] = load_empty_list + + def load_empty_dictionary(self): + self.stack.append(Dictionary()) + dispatch[EMPTY_DICT] = load_empty_dictionary + + def load_list(self): + k = self.marker() + self.stack[k:] = [List(self.stack[k + 1:])] + dispatch[LIST] = load_list + + def load_dict(self): + k = self.marker() + d = Dictionary() + items = self.stack[k + 1:] + for i in range(0, len(items), 2): + key = items[i] + value = items[i + 1] + d[key] = value + self.stack[k:] = [d] + dispatch[DICT] = load_dict + + def load_inst(self): + k = self.marker() + args = Tuple(self.stack[k + 1:]) + del self.stack[k:] + module = self.readline()[:-1] + name = self.readline()[:-1] + value = Object(Global(module, name), args) + self.append(value) + dispatch[INST] = load_inst + + def load_obj(self): + stack = self.stack + k = self.marker() + klass = stack[k + 1] + del stack[k + 1] + args = Tuple(stack[k + 1:]) + del stack[k:] + value = Object(klass, args) + self.append(value) + dispatch[OBJ] = load_obj + + def load_global(self): + module = self.readline()[:-1] + name = self.readline()[:-1] + self.append(Global(module, name)) + dispatch[GLOBAL] = load_global + + def load_reduce(self): + stack = self.stack + + callable = stack[-2] + arg_tup = stack[-1] + del stack[-2:] + + value = Object(callable, arg_tup) + self.append(value) + dispatch[REDUCE] = load_reduce + + idprefix='' + + def load_get(self): + self.append(Get(self.idprefix + self.readline()[:-1])) + dispatch[GET] = load_get + + def load_binget(self): + i = ord(self.read(1)) + self.append(Get(self.idprefix + repr(i))) + dispatch[BINGET] = load_binget + + def load_long_binget(self): + i = mloads('i' + self.read(4)) + self.append(Get(self.idprefix + repr(i))) + dispatch[LONG_BINGET] = load_long_binget + + def load_put(self): + self.stack[-1].id = self.idprefix + self.readline()[:-1] + dispatch[PUT] = load_put + + def load_binput(self): + i = ord(self.read(1)) + last = self.stack[-1] + if getattr(last, 'id', last) is last: + last.id = self.idprefix + repr(i) + dispatch[BINPUT] = load_binput + + def load_long_binput(self): + i = mloads('i' + self.read(4)) + last = self.stack[-1] + if getattr(last, 'id', last) is last: + last.id = self.idprefix + repr(i) + dispatch[LONG_BINPUT] = load_long_binput + + +def ToXMLload(file): + return ToXMLUnpickler(file).load() + +def ToXMLloads(str): + from StringIO import StringIO + file = StringIO(str) + return ToXMLUnpickler(file).load() + +def name(self, tag, data): + return ''.join(data[2:]).strip() + +def start_pickle(self, tag, attrs): + self._pickleids = {} + return [tag, attrs] + +def save_int(self, tag, data): + if self.binary: + v = int(name(self, tag, data)) + if v >= 0: + if v <= 0xff: + return BININT1 + chr(v) + if v <= 0xffff: + return '%c%c%c' % (BININT2, v & 0xff, v >> 8) + hb = v >> 31 + if hb == 0 or hb == -1: + return BININT + struct.pack('<i', v) + return INT + name(self, tag, data) + '\n' + +def save_float(self, tag, data): + if self.binary: + return BINFLOAT + struct.pack('>d', float(name(self, tag, data))) + else: + return FLOAT + name(self, tag, data) + '\n' + +def save_put(self, v, attrs): + id = attrs.get('id', '') + if id: + prefix = id.rfind('.') + if prefix >= 0: + id = id[prefix + 1:] + elif id[0] == 'i': + id = id[1:] + if self.binary: + id = int(id) + if id < 256: + id = BINPUT + chr(id) + else: + id = LONG_BINPUT + struct.pack('<i', id) + else: + id = PUT + repr(id) + '\n' + return v + id + return v + +def save_string(self, tag, data): + a = data[1] + v = ''.join(data[2:]) + encoding = a['encoding'] + if encoding is not '': + v = unescape(v, encoding) + if self.binary: + l = len(v) + if l < 256: + v = SHORT_BINSTRING + chr(l) + v + else: + v = BINSTRING + struct.pack('<i', l) + v + else: + v = STRING + repr(v) + '\n' + return save_put(self, v, a) + +def save_unicode(self, tag, data): + a = data[1] + v = ''.join(data[2:]) + encoding = a['encoding'] + if encoding is not '': + v = unescape(v, encoding) + if self.binary: + v = v.encode('utf-8') + v = BINUNICODE + struct.pack("<i", len(v)) + v + else: + v = v.replace("\\", "\\u005c") + v = v.replace("\n", "\\u000a") + v.encode('raw-unicode-escape') + v = UNICODE + v + '\n' + return save_put(self, v, a) + +def save_tuple(self, tag, data): + T = data[2:] + if not T: + return EMPTY_TUPLE + return save_put(self, MARK + ''.join(T) + TUPLE, data[1]) + +def save_list(self, tag, data): + L = data[2:] + if self.binary: + v = save_put(self, EMPTY_LIST, data[1]) + if L: + v = v + MARK + ''.join(L) + APPENDS + else: + v = save_put(self, MARK + LIST, data[1]) + if L: + v = APPEND.join(L) + APPEND + return v + +def save_dict(self, tag, data): + D = data[2:] + if self.binary: + v = save_put(self, EMPTY_DICT, data[1]) + if D: + v = v + MARK + ''.join(D) + SETITEMS + else: + v = save_put(self, MARK + DICT, data[1]) + if D: + v = v + SETITEM.join(D) + SETITEM + return v + +def save_reference(self, tag, data): + a = data[1] + id = a['id'] + prefix = id.rfind('.') + if prefix >= 0: + id = id[prefix + 1:] + if self.binary: + id = int(id) + if id < 256: + return BINGET + chr(id) + else: + return LONG_BINGET + struct.pack('<i', i) + else: + return GET + repr(id) + '\n' + +def save_object(self, tag, data): + v = MARK + data[2] + x = data[3][1:] + stop = x.rfind('t') # This seems + if stop >= 0: # wrong! + x = x[:stop] + v = save_put(self, v + x + OBJ, data[1]) + v = v + data[4] + BUILD # state + return v + +def save_global(self, tag, data): + a = data[1] + return save_put(self, GLOBAL + a['module'] + '\n' + a['name'] + '\n', a) + +def save_persis(self, tag, data): + v = data[2] + if self.binary: + return v + BINPERSID + else: + return PERSID + v + +class xmlPickler(NoBlanks, xyap): + start_handlers = { + 'pickle': lambda self, tag, attrs: [tag, attrs], + } + end_handlers = { + 'pickle': lambda self, tag, data: str(data[2]) + STOP, + 'none': lambda self, tag, data: NONE, + 'int': save_int, + 'long': lambda self, tag, data: LONG + str(data[2]) + LONG + '\n', + 'float': save_float, + 'string': save_string, + 'reference': save_reference, + 'tuple': save_tuple, + 'list': save_list, + 'dictionary': save_dict, + 'item': lambda self, tag, data: ''.join(map(str, data[2:])), + 'value': lambda self, tag, data: data[2], + 'key' : lambda self, tag, data: data[2], + 'object': save_object, + 'klass': lambda self, tag, data: data[2], + 'state': lambda self, tag, data: data[2], + 'global': save_global, + 'persistent': save_persis, + 'unicode': save_unicode, + } diff -Naur Zope-4.5.3/Shared/DC/xml/xyap.py Zope-4.5.3-Nexedi/Shared/DC/xml/xyap.py --- Zope-4.5.3/Shared/DC/xml/xyap.py 1970-01-01 01:00:00.000000000 +0100 +++ Zope-4.5.3-Nexedi/Shared/DC/xml/xyap.py 2021-03-09 16:13:49.000000000 +0100 @@ -0,0 +1,117 @@ +"""Yet another XML parser + +This is meant to be very simple: + + - stack based + + - The parser has a table of start handlers and end handlers. + + - start tag handlers are called with the parser instance, tag names + and attributes. The result is placed on the stack. The default + handler places a special object on the stack (uh, a list, with the + tag name and attributes as the first two elements. ;) + + - end tag handlers are called with the object on the parser, the tag + name, and top of the stack right after it has been removed. The + result is appended to the object on the top of the stack. + +Note that namespace attributes should recieve some special handling. +Oh well. +""" + +import string +import xml.parsers.expat + + +class xyap: + start_handlers = {} + end_handlers = {} + + def __init__(self): + top = [] + self._stack = _stack = [top] + self.push = _stack.append + self.append = top.append + + def handle_data(self, data): + self.append(data) + + def unknown_starttag(self, tag, attrs): + if isinstance(attrs, list): + attrs = dict(attrs) + start = self.start_handlers + if tag in start: + tag = start[tag](self, tag, attrs) + else: + tag = [tag, attrs] + self.push(tag) + self.append = tag.append + + def unknown_endtag(self, tag): + _stack = self._stack + top = _stack.pop() + append = self.append = _stack[-1].append + end = self.end_handlers + if tag in end: + top = end[tag](self, tag, top) + append(top) + +class NoBlanks: + + def handle_data(self, data): + if data.strip(): + self.append(data) + + +def struct(self, tag, data): + r = {} + for k, v in data[2:]: + r[k] = v + return r + +_nulljoin = "".join + +def name(self, tag, data): + return _nulljoin(data[2:]).strip() + +def tuplef(self, tag, data): + return tuple(data[2:]) + +class XYap(xyap): + def __init__(self): + self._parser = xml.parsers.expat.ParserCreate() + self._parser.StartElementHandler = self.unknown_starttag + self._parser.EndElementHandler = self.unknown_endtag + self._parser.CharacterDataHandler = self.handle_data + xyap.__init__(self) + +class xmlrpc(NoBlanks, XYap): + end_handlers = { + 'methodCall': tuplef, + 'methodName': name, + 'params': tuplef, + 'param': lambda self, tag, data: data[2], + 'value': lambda self, tag, data: data[2], + 'i4': + lambda self, tag, data, atoi=string.atoi, name=name: + atoi(name(self, tag, data)), + 'int': + lambda self, tag, data, atoi=string.atoi, name=name: + atoi(name(self, tag, data)), + 'boolean': + lambda self, tag, data, atoi=string.atoi, name=name: + atoi(name(self, tag, data)), + 'string': lambda self, tag, data, join=string.join: + join(data[2:], ''), + 'double': + lambda self, tag, data, atof=string.atof, name=name: + atof(name(self, tag, data)), + 'float': + lambda self, tag, data, atof=string.atof, name=name: + atof(name(self, tag, data)), + 'struct': struct, + 'member': tuplef, + 'name': name, + 'array': lambda self, tag, data: data[2], + 'data': lambda self, tag, data: data[2:], + }