Commit acf21da9 authored by Tres Seaver's avatar Tres Seaver

LP #195761: fixed ZMI XML export / import and restored it to the UI.

parent df3cc16a
......@@ -133,6 +133,8 @@ Features Added
Bugs Fixed
++++++++++
- LP #195761: fixed ZMI XML export / import and restored it to the UI.
- LP #491224: proper escaping of rendered error message
- LP #246983: Enabled unicode conflict resolution on variables inside "string:"
......
......@@ -14,6 +14,8 @@ 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
......@@ -23,7 +25,7 @@ def XMLrecord(oid, len, p):
q=ppml.ToXMLUnpickler
f=StringIO(p)
u=q(f)
id=ppml.u64(oid)
id=u64(oid)
aka=encodestring(oid)[:-1]
u.idprefix=str(id)+'.'
p=u.load().__str__(4)
......@@ -93,11 +95,11 @@ def save_record(parser, tag, data):
file.seek(pos)
a=data[1]
if a.has_key('id'): oid=a['id']
oid=ppml.p64(int(oid))
oid=p64(int(oid))
v=''
for x in data[2:]:
v=v+x
l=ppml.p64(len(v))
l=p64(len(v))
v=oid+l+v
return v
......
......@@ -10,16 +10,12 @@ them to a different Zope installation. You can either choose
to download the export file to your local machine, or save it
in the "var" directory of your Zope installation
on the server.
<!--
<br/>
<br/>
<b>Note:</b>
Zope can export/import objects in two dfferent formats: a binary format (called
Zope can export/import objects in two different formats: a binary format (called
ZEXP) and as XML. The ZEXP format is the officially supported export/import
format for moving data between <u>identical</u> Zope installations (it is not a migration tool).
The XML export/import is unsupported (and possibly broken under certain circumstances) - use it
at your own risk.
-->
</p>
<form action="manage_exportObject" method="post">
......@@ -54,7 +50,6 @@ at your own risk.
</div>
</td>
</tr>
<!--
<tr>
<td align="left" valign="top">
&nbsp;
......@@ -69,7 +64,6 @@ at your own risk.
</div>
</td>
</tr>
-->
<tr>
<td></td>
<td align="left" valign="top">
......
<?xml version="1.0"?>
<ZopeData>
<record id="482504664188191745" aka="BrIzb4doBAE=">
<pickle>
<tuple id="482504664188191745.2">
<global id="482504664188191745.1" name="Folder" module="OFS.Folder"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary id="482504664188191745.3">
<item>
<key><string id="482504664188191745.4" encoding="">_objects</string></key>
<value>
<tuple id="482504664188191745.10">
<dictionary id="482504664188191745.5">
<item>
<key><string id="482504664188191745.6" encoding="">meta_type</string></key>
<value><string id="482504664188191745.7" encoding="">Image</string></value>
</item>
<item>
<key><string id="482504664188191745.8" encoding="">id</string></key>
<value><string id="482504664188191745.9" encoding="">image</string></value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key><reference id="482504664188191745.9"/></key>
<value>
<persistent><string id="482504664188191745.11" encoding="base64">BrIzb4doBAI=</string></persistent>
</value>
</item>
<item>
<key><reference id="482504664188191745.8"/></key>
<value><string id="482504664188191745.12" encoding="">sub</string></value>
</item>
</dictionary>
</pickle>
</record>
<record id="482504664188191746" aka="BrIzb4doBAI=">
<pickle>
<tuple id="482504664188191746.2">
<global id="482504664188191746.1" name="Image" module="OFS.Image"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary id="482504664188191746.3">
<item>
<key><string id="482504664188191746.4" encoding="">precondition</string></key>
<value><string encoding=""></string></value>
</item>
<item>
<key><string id="482504664188191746.5" encoding="">height</string></key>
<value><int>16</int></value>
</item>
<item>
<key><string id="482504664188191746.6" encoding="">size</string></key>
<value><int>894</int></value>
</item>
<item>
<key><string id="482504664188191746.7" encoding="">title</string></key>
<value><string encoding=""></string></value>
</item>
<item>
<key><string id="482504664188191746.8" encoding="">width</string></key>
<value><int>16</int></value>
</item>
<item>
<key><string id="482504664188191746.9" encoding="">_EtagSupport__etag</string></key>
<value><string id="482504664188191746.10" encoding="">ts65767150.22</string></value>
</item>
<item>
<key><string id="482504664188191746.11" encoding="">prop3</string></key>
<value><long>2147483647</long></value>
</item>
<item>
<key><string id="482504664188191746.12" encoding="">content_type</string></key>
<value><string id="482504664188191746.13" encoding="">image/gif</string></value>
</item>
<item>
<key><string id="482504664188191746.14" encoding="">__name__</string></key>
<value><string id="482504664188191746.15" encoding="">image</string></value>
</item>
<item>
<key><string id="482504664188191746.16" encoding="">data</string></key>
<value><string id="482504664188191746.17" encoding="base64">R0lGODlhEAAQAPcAAP8A/wAAAFBQUICAgMDAwP8AAIAAQAAAoABAgIAAgEAAQP//AP//gACAgECA
gP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAA
AAhbAAMIHEhwIICDAQ4qXIhQYUKFCCIufAiAYsSLDjMWiFjgoMSODkECAMmRIcWDBTYiYMjS40qT
DFWKRHmyY8mRKStmXJhzp04AEllSfBgUZsOWPk+2HFqwaYCAAAA7</string></value>
</item>
<item>
<key><string id="482504664188191746.18" encoding="">prop12</string></key>
<value><unicode encoding="">£</unicode></value>
</item>
<item>
<key><string id="482504664188191746.19" encoding="">prop10</string></key>
<value><string id="482504664188191746.20" encoding="">&lt;]]&gt;</string></value>
</item>
<item>
<key><string id="482504664188191746.21" encoding="">prop11</string></key>
<value><unicode id="482504664188191746.22" encoding="">&lt;]]&gt;</unicode></value>
</item>
<item>
<key><string id="482504664188191746.23" encoding="">prop4</string></key>
<value><string id="482504664188191746.24" encoding="">xxx</string></value>
</item>
<item>
<key><string id="482504664188191746.25" encoding="">prop5</string></key>
<value>
<tuple id="482504664188191746.27">
<reference id="482504664188191746.24"/>
<string id="482504664188191746.26" encoding="">zzz</string>
</tuple>
</value>
</item>
<item>
<key><string id="482504664188191746.28" encoding="">prop6</string></key>
<value><unicode id="482504664188191746.29" encoding="">xxx</unicode></value>
</item>
<item>
<key><string id="482504664188191746.30" encoding="">prop7</string></key>
<value>
<tuple id="482504664188191746.32">
<reference id="482504664188191746.29"/>
<unicode id="482504664188191746.31" encoding="">zzz</unicode>
</tuple>
</value>
</item>
<item>
<key><string id="482504664188191746.33" encoding="">prop1</string></key>
<value><float>3.14159265359</float></value>
</item>
<item>
<key><string id="482504664188191746.34" encoding="">prop2</string></key>
<value><int>1</int></value>
</item>
<item>
<key><string id="482504664188191746.35" encoding="">_properties</string></key>
<value>
<tuple id="482504664188191746.66">
<dictionary id="482504664188191746.36">
<item>
<key><string id="482504664188191746.37" encoding="">type</string></key>
<value><string id="482504664188191746.38" encoding="">string</string></value>
</item>
<item>
<key><string id="482504664188191746.39" encoding="">id</string></key>
<value><reference id="482504664188191746.7"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.40">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.38"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><string id="482504664188191746.41" encoding="">alt</string></value>
</item>
</dictionary>
<dictionary id="482504664188191746.42">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.38"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.12"/></value>
</item>
<item>
<key><string id="482504664188191746.43" encoding="">mode</string></key>
<value><string encoding="">w</string></value>
</item>
</dictionary>
<dictionary id="482504664188191746.44">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.38"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.5"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.45">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.38"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.8"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.46">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><string id="482504664188191746.47" encoding="">float</string></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.33"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.48">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><string id="482504664188191746.49" encoding="">int</string></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.34"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.50">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><string id="482504664188191746.51" encoding="">long</string></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.11"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.52">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.38"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.23"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.53">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><string id="482504664188191746.54" encoding="">lines</string></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.25"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.55">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><string id="482504664188191746.56" encoding="">unicode</string></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.28"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.57">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><string id="482504664188191746.58" encoding="">ulines</string></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.30"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.59">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.38"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><string id="482504664188191746.60" encoding="">prop8</string></value>
</item>
</dictionary>
<dictionary id="482504664188191746.61">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.56"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><string id="482504664188191746.62" encoding="">prop9</string></value>
</item>
</dictionary>
<dictionary id="482504664188191746.63">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.38"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.19"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.64">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.56"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.21"/></value>
</item>
</dictionary>
<dictionary id="482504664188191746.65">
<item>
<key><reference id="482504664188191746.37"/></key>
<value><reference id="482504664188191746.56"/></value>
</item>
<item>
<key><reference id="482504664188191746.39"/></key>
<value><reference id="482504664188191746.18"/></value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key><reference id="482504664188191746.60"/></key>
<value><string id="482504664188191746.67" encoding="cdata"><![CDATA[<&>]]></string></value>
</item>
<item>
<key><reference id="482504664188191746.62"/></key>
<value><unicode id="482504664188191746.68" encoding="cdata"><![CDATA[<&>]]></unicode></value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# -*- coding: iso8859-1 -*-
##############################################################################
#
# Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
......@@ -16,7 +17,15 @@ import tempfile
import transaction
from StringIO import StringIO
_LONG_DTML = '\n'.join([('<dtml-var foo%d' % x) for x in xrange(1000)])
try:
here = os.path.dirname(os.path.abspath(__file__))
except:
here = os.path.dirname(os.path.abspath(sys.argv[0]))
imagedata = os.path.join(here, 'test.gif')
xmldata = os.path.join(here, 'export.xml')
_LONG_DTML = ''.join([('<dtml-var foo%d' % x) for x in xrange(1000)])
class XMLExportImportTests(unittest.TestCase):
......@@ -112,6 +121,75 @@ class XMLExportImportTests(unittest.TestCase):
# the block above.
os.remove(path)
def test_exportXML(self):
from OFS.Folder import Folder
from OFS.Image import Image
from OFS.XMLExportImport import exportXML
connection, app = self._makeJarAndRoot()
data = open(imagedata, 'rb')
sub = Folder('sub')
app._setObject('sub', sub)
img = Image('image', '', data, 'image/gif')
sub._setObject('image', img)
img._setProperty('prop1', 3.14159265359, 'float')
img._setProperty('prop2', 1, 'int')
img._setProperty('prop3', 2L**31-1, 'long')
img._setProperty('prop4', 'xxx', 'string')
img._setProperty('prop5', ['xxx', 'zzz'], 'lines')
img._setProperty('prop6', u'xxx', 'unicode')
img._setProperty('prop7', [u'xxx', u'zzz'], 'ulines')
img._setProperty('prop8', '<&>', 'string')
img._setProperty('prop9', u'<&>', 'unicode')
img._setProperty('prop10', '<]]>', 'string')
img._setProperty('prop11', u'<]]>', 'unicode')
img._setProperty('prop12', u'', 'unicode')
transaction.savepoint(optimistic=True)
oid = sub._p_oid
handle, path = tempfile.mkstemp(suffix='.xml')
try:
ostream = os.fdopen(handle,'wb')
data = exportXML(connection, oid, ostream)
ostream.close()
finally:
os.remove(path)
def test_importXML(self):
from OFS.XMLExportImport import importXML
connection, app = self._makeJarAndRoot()
newobj = importXML(connection, xmldata)
img = newobj._getOb('image')
data = open(imagedata, 'rb').read()
self.assertEqual(img.data, data)
self.assertEqual(repr(img.getProperty('prop1')),
repr(3.14159265359))
self.assertEqual(repr(img.getProperty('prop2')),
repr(1))
self.assertEqual(repr(img.getProperty('prop3')),
repr(2L**31-1))
self.assertEqual(repr(img.getProperty('prop4')),
repr('xxx'))
self.assertEqual(repr(img.getProperty('prop5')),
repr(('xxx', 'zzz')))
self.assertEqual(repr(img.getProperty('prop6')),
repr(u'xxx'))
self.assertEqual(repr(img.getProperty('prop7')),
repr((u'xxx', u'zzz')))
self.assertEqual(repr(img.getProperty('prop8')),
repr('<&>'))
self.assertEqual(repr(img.getProperty('prop9')),
repr(u'<&>'))
self.assertEqual(repr(img.getProperty('prop10')),
repr('<]]>'))
self.assertEqual(repr(img.getProperty('prop11')),
repr(u'<]]>'))
self.assertEqual(repr(img.getProperty('prop12')),
repr(u''))
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(XMLExportImportTests),
......
......@@ -17,119 +17,68 @@
__version__ = "1.9" # Code version
from pickle import *
from string import replace
import struct
import base64
import string
import pickle
import tempfile
import marshal
import xyap
mdumps = marshal.dumps
mloads = marshal.loads
xyap=xyap.xyap
ListType=type([])
# Create repr mappong
reprs = {}
for c in map(chr,range(256)): reprs[c] = repr(c)[1:-1]
reprs['\n'] = "\\n\n"
reprs['\t'] = "\\t"
reprs['\\'] = "\\\\"
reprs['\r'] = "\\r"
reprs["'"] = "\\'"
reprs2={}
reprs2['<'] = "\\074"
reprs2['>'] = "\\076"
reprs2['&'] = "\\046"
# Function convert takes a string and converts it to either
# repr or base64 format
def convert(S, find=string.find):
new = ''
encoding = 'repr'
new = string.join(map(reprs.get, S), '')
if len(new) > (1.4*len(S)):
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'
new = base64.encodestring(S)[:-1]
elif find(new,'>') >= 0 or find(new,'<') >= 0 or find(new,'&') >= 0:
if find(new, ']]>') <0 :
new='<![CDATA[\n\n'+new+'\n\n]]>'
encoding='cdata'
elif '>' in s or '<' in s or '&' in s:
if not ']]>' in s:
s = '<![CDATA[' + s + ']]>'
encoding = 'cdata'
else:
new=string.join(map(lambda s: reprs2.get(s,s), new), '')
return encoding, new
# Function unconvert takes a encoding and a string and
# returns the original string
s = s.replace('&', '&amp;')
s = s.replace('>', '&gt;')
s = s.replace('<', '&lt;')
return encoding, s
def unconvert(encoding,S):
original = ''
def unescape(s, encoding):
if encoding == 'base64':
original = base64.decodestring(S)
return base64.decodestring(s)
else:
x = string.replace(S, '\n', '')
original = eval("'"+x+"'")
return original
t32 = 1L << 32
def p64(v, pack=struct.pack):
if v < t32: h=0
else:
h=v/t32
v=v%t32
return pack(">II", h, v)
def u64(v, unpack=struct.unpack):
h, v = unpack(">ii", v)
if v < 0: v=t32+v
if h:
if h < 0: h=t32+h
v=h*t32+v
return v
s = s.replace('&lt;', '<')
s = s.replace('&gt;', '>')
return s.replace('&amp;', '&')
class Global:
def __init__(self, module, name):
self.module=module
self.name=name
self.module = module
self.name = name
def __str__(self, indent=0):
if hasattr(self, 'id'): id=' id="%s"' % self.id
else: id=''
name=string.lower(self.__class__.__name__)
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)
' ' * indent, name, id, self.name, self.module)
class Scalar:
def __init__(self, v):
self._v=v
self._v = v
def value(self): return self._v
def value(self):
return self._v
def __str__(self, indent=0):
if hasattr(self, 'id'): id=' id="%s"' % self.id
else: id=''
name=string.lower(self.__class__.__name__)
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)
' ' * indent, name, id, self.value(), name)
def xmlstr(v):
v=`v`
if v[:1]=='\'':
v=string.replace(v,'"','\\"')
v=replace(v,'%','\\045')
v=replace(v,'&','\\046')
return v[1:-1]
class Int(Scalar): pass
class Long(Scalar):
def value(self):
result = str(self._v)
......@@ -137,65 +86,84 @@ class Long(Scalar):
return result[:-1]
return result
class Float(Scalar): pass
class String(Scalar):
def __init__(self, v, encoding=''):
encoding, v = convert(v)
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=string.lower(self.__class__.__name__)
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)
' ' * indent, name, id, encoding, self.value(), name)
class Wrapper:
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')
def __init__(self, v): self._v=v
class Wrapper:
def __init__(self, v):
self._v = v
def value(self): return self._v
def value(self):
return self._v
def __str__(self, indent=0):
if hasattr(self, 'id'): id=' id="%s"' % self.id
else: id=''
name=string.lower(self.__class__.__name__)
v=self._v
i=' '*indent
if isinstance(v,Scalar):
return '%s<%s%s> %s </%s>\n' % (i, name, id, str(v)[:-1], name)
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)
v = v.__str__(indent + 2)
except TypeError:
v=v.__str__()
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=string.lower(self.__class__.__name__)
i=' '*indent
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)
i, name, id, self.value(indent + 2), i, name)
else:
return '%s<%s%s/>\n' % (i, name, id)
class Key(Wrapper): pass
class Value(Wrapper): pass
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 __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 string.join(
map(lambda i, ind=' '*indent, indent=indent+4:
return ''.join(
map(lambda i, ind=' ' * indent, indent=indent + 4:
'%s<item>\n'
'%s'
'%s'
......@@ -206,61 +174,72 @@ class Dictionary(Collection):
Value(i[1]).__str__(indent),
ind),
self._d
),
'')
))
class Sequence(Collection):
def __init__(self, v=None):
if not v: v=[]
self._subs=v
if not v:
v = []
self._subs = v
def __len__(self): return len(self._subs)
def __len__(self):
return len(self._subs)
def append(self, v): self._subs.append(v)
def extend(self, v): self._subs.extend(v)
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)
return v.__str__(indent + 2)
except TypeError:
return v.__str__()
def value(self, indent):
return string.join(map(
return ''.join(map(
lambda v, indent=indent: self._stringify(v, indent),
self._subs),'')
class List(Sequence): pass
class Tuple(Sequence): pass
class Klass(Wrapper): pass
class State(Wrapper): pass
class Pickle(Wrapper): pass
class Persistent(Wrapper): pass
self._subs))
class none:
def __str__(self, indent=0): return ' '*indent+'<none/>\n'
none=none()
def __str__(self, indent=0):
return ' ' * indent + '<none/>\n'
none = none()
class Reference(Scalar):
def __init__(self, v): self._v=v
def __init__(self, v):
self._v = v
def __str__(self, indent=0):
v=self._v
name=string.lower(self.__class__.__name__)
return '%s<%s id="%s"/>\n' % (' '*indent,name,v)
v = self._v
name = self.__class__.__name__.lower()
return '%s<%s id="%s"/>\n' % (' ' * indent, name, v)
Get=Reference
Get = Reference
class Object(Sequence):
def __init__(self, klass, args):
self._subs=[Klass(klass), args]
self._subs = [Klass(klass), args]
def __setstate__(self, v): self.append(State(v))
def __setstate__(self, v):
self.append(State(v))
class ToXMLUnpickler(Unpickler):
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
def load(self): return Pickle(Unpickler.load(self))
class ToXMLUnpickler(Unpickler):
def load(self):
return Pickle(Unpickler.load(self))
dispatch = {}
dispatch.update(Unpickler.dispatch)
......@@ -278,7 +257,7 @@ class ToXMLUnpickler(Unpickler):
dispatch[NONE] = load_none
def load_int(self):
self.append(Int(string.atoi(self.readline()[:-1])))
self.append(Int(int(self.readline()[:-1])))
dispatch[INT] = load_int
def load_binint(self):
......@@ -286,7 +265,7 @@ class ToXMLUnpickler(Unpickler):
dispatch[BININT] = load_binint
def load_binint1(self):
self.append(Int(mloads('i' + self.read(1) + '\000\000\000')))
self.append(Int(ord(self.read(1))))
dispatch[BININT1] = load_binint1
def load_binint2(self):
......@@ -294,11 +273,11 @@ class ToXMLUnpickler(Unpickler):
dispatch[BININT2] = load_binint2
def load_long(self):
self.append(Long(string.atol(self.readline()[:-1], 0)))
self.append(Long(long(self.readline()[:-1], 0)))
dispatch[LONG] = load_long
def load_float(self):
self.append(Float(string.atof(self.readline()[:-1])))
self.append(Float(float(self.readline()[:-1])))
dispatch[FLOAT] = load_float
def load_binfloat(self, unpack=struct.unpack):
......@@ -306,8 +285,16 @@ class ToXMLUnpickler(Unpickler):
dispatch[BINFLOAT] = load_binfloat
def load_string(self):
self.append(String(eval(self.readline()[:-1],
{'__builtins__': {}}))) # Let's be careful
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):
......@@ -315,14 +302,23 @@ class ToXMLUnpickler(Unpickler):
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 = mloads('i' + self.read(1) + '\000\000\000')
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:])]
self.stack[k:] = [Tuple(self.stack[k + 1:])]
dispatch[TUPLE] = load_tuple
def load_empty_tuple(self):
......@@ -339,27 +335,27 @@ class ToXMLUnpickler(Unpickler):
def load_list(self):
k = self.marker()
self.stack[k:] = [List(self.stack[k+1:])]
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:]
items = self.stack[k + 1:]
for i in range(0, len(items), 2):
key = items[i]
value = items[i+1]
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:])
args = Tuple(self.stack[k + 1:])
del self.stack[k:]
module = self.readline()[:-1]
name = self.readline()[:-1]
value=Object(Global(module, name), args)
value = Object(Global(module, name), args)
self.append(value)
dispatch[INST] = load_inst
......@@ -370,7 +366,7 @@ class ToXMLUnpickler(Unpickler):
del stack[k + 1]
args = Tuple(stack[k + 1:])
del stack[k:]
value=Object(klass,args)
value = Object(klass, args)
self.append(value)
dispatch[OBJ] = load_obj
......@@ -384,45 +380,45 @@ class ToXMLUnpickler(Unpickler):
stack = self.stack
callable = stack[-2]
arg_tup = stack[-1]
arg_tup = stack[-1]
del stack[-2:]
value=Object(callable, arg_tup)
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]))
self.append(Get(self.idprefix + self.readline()[:-1]))
dispatch[GET] = load_get
def load_binget(self):
i = mloads('i' + self.read(1) + '\000\000\000')
self.append(Get(self.idprefix+`i`))
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+`i`))
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]
self.stack[-1].id = self.idprefix + self.readline()[:-1]
dispatch[PUT] = load_put
def load_binput(self):
i = mloads('i' + self.read(1) + '\000\000\000')
i = ord(self.read(1))
last = self.stack[-1]
if getattr(last, 'id', last) is last:
last.id = self.idprefix + `i`
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 + `i`
last.id = self.idprefix + repr(i)
dispatch[LONG_BINPUT] = load_long_binput
......@@ -430,230 +426,169 @@ def ToXMLload(file):
return ToXMLUnpickler(file).load()
def ToXMLloads(str):
from StringIO import StringIO
file = StringIO(str)
return ToXMLUnpickler(file).load()
class NoBlanks:
def handle_data(self, data):
if string.strip(data): self.append(data)
def name(self, tag, data, join=string.join, strip=string.strip):
return strip(join(data[2:],''))
def name(self, tag, data):
return ''.join(data[2:]).strip()
def start_pickle(self, tag, attrs):
self._pickleids={}
return [tag,attrs]
def end_string(self, tag, data):
v=data[2]
a=data[1]
if a['encoding'] is not '':
v=unconvert(a['encoding'],v)
if a.has_key('id'): self._pickleids[a['id']]=v
return v
def end_list(self, tag, data):
v=data[2:]
a=data[1]
if a.has_key('id'): self._pickleids[data[1]['id']]=v
return v
def end_tuple(self, tag, data):
v=tuple(data[2:])
a=data[1]
if a.has_key('id'): self._pickleids[data[1]['id']]=v
return v
def end_dictionary(self, tag, data):
D={}
a=data[1]
for k, v in data[2:]: D[k]=v
if a.has_key('id'): self._pickleids[a['id']]=D
return D
class xmlUnpickler(NoBlanks, xyap):
start_handlers={'pickle': start_pickle}
end_handlers={
'int':
lambda self,tag,data,atoi=string.atoi,name=name:
atoi(name(self, tag, data)),
'long':
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': end_string ,
'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)),
'none': lambda self, tag, data: None,
'list': end_list,
'tuple': end_tuple,
'dictionary': end_dictionary,
'key': lambda self, tag, data: data[2],
'value': lambda self, tag, data: data[2],
'item': lambda self, tag, data: data[2:],
'reference': lambda self, tag, data: self._pickleids[data[1]['id']],
'state': lambda self, tag, data: data[2],
'klass': lambda self, tag, data: data[2],
}
self._pickleids = {}
return [tag, attrs]
def save_int(self, tag, data):
binary=self.binary
if binary:
v=string.atoi(name(self, tag, data))
i=mdumps(v)[1:]
if (i[-2:] == '\000\000'):
if (i[-3] == '\000'):
v='K'+i[:-3]
return v
v='M'+i[:-2]
return v
v='J'+i
return v
v='I'+name(self, tag, data)+'\012'
return v
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):
binary=self.binary
if binary: v='G'+struct.pack('>d',string.atof(name(self, tag, data)))
else: v='F'+name(self, tag, data)+'\012'
return v
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','')
id = attrs.get('id', '')
if id:
prefix=string.rfind(id,'.')
if prefix >= 0: id=id[prefix+1:]
elif id[0]=='i': id=id[1:]
prefix = id.rfind('.')
if prefix >= 0:
id = id[prefix + 1:]
elif id[0] == 'i':
id = id[1:]
if self.binary:
id=string.atoi(id)
s=mdumps(id)[1:]
if (id < 256):
id=s[0]
put='q'
id = int(id)
if id < 256:
id = BINPUT + chr(id)
else:
id=s
put='r'
id=put+id
id = LONG_BINPUT + struct.pack('<i', id)
else:
id="p"+id+"\012"
return v+id
id = PUT + repr(id) + '\n'
return v + id
return v
def save_string(self, tag, data):
binary=self.binary
v=''
a=data[1]
if len(data)>2:
for x in data[2:]:
v=v+x
encoding=a['encoding']
a = data[1]
v = ''.join(data[2:])
encoding = a['encoding']
if encoding is not '':
v=unconvert(encoding,v)
put='p'
if binary:
l=len(v)
s=mdumps(l)[1:]
if (l<256):
v='U'+s[0]+v
v = unescape(v, encoding)
if self.binary:
l = len(v)
if l < 256:
v = SHORT_BINSTRING + chr(l) + v
else:
v='T'+s+v
put='q'
else: v="S'"+v+"'\012"
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 ')'
return save_put(self, '('+string.join(T,'')+'t', data[1])
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:]
a=data[1]
L = data[2:]
if self.binary:
v=save_put(self, ']', a)
if L: v=v+'('+string.join(L,'')+'e'
v = save_put(self, EMPTY_LIST, data[1])
if L:
v = v + MARK + ''.join(L) + APPENDS
else:
v=save_put(self, '(l', a)
if L: v=string.join(L,'a')+'a'
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:]
D = data[2:]
if self.binary:
v=save_put(self, '}', data[1])
if D: v=v+'('+string.join(D,'')+'u'
v = save_put(self, EMPTY_DICT, data[1])
if D:
v = v + MARK + ''.join(D) + SETITEMS
else:
v=save_put(self, '(d', data[1])
if D: v=v+string.join(D,'s')+'s'
v = save_put(self, MARK + DICT, data[1])
if D:
v = v + SETITEM.join(D) + SETITEM
return v
def save_reference(self, tag, data):
binary=self.binary
a=data[1]
id=a['id']
prefix=string.rfind(id,'.')
if prefix>=0: id=id[prefix+1:]
get='g'
if binary:
id=string.atoi(id)
s=mdumps(id)[1:]
if (id < 256):
id=s[0]
get='h'
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:
id=s
get='j'
v=get+id
else: v=get+id+'\012'
return v
return LONG_BINGET + struct.pack('<i', i)
else:
return GET + repr(id) + '\n'
def save_object(self, tag, data):
v='('+data[2]
x=data[3][1:]
stop=string.rfind(x,'t') # This seems
if stop>=0: x=x[:stop] # wrong!
v=save_put(self, v+x+'o', data[1])
v=v+data[4]+'b' # state
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, 'c'+a['module']+'\012'+a['name']+'\012', a)
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:
v=v+'Q'
v = data[2]
if self.binary:
return v + BINPERSID
else:
v='P'+v
return v
return PERSID + v
class xmlPickler(NoBlanks, xyap):
start_handlers={
start_handlers = {
'pickle': lambda self, tag, attrs: [tag, attrs],
}
end_handlers={
'pickle': lambda self, tag, data: str(data[2])+'.',
'none': lambda self, tag, data: 'N',
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: 'L'+str(data[2])+'L\012',
'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, j=string.join: j(data[2:],''),
'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,
......@@ -661,6 +596,7 @@ class xmlPickler(NoBlanks, xyap):
'state': lambda self, tag, data: data[2],
'global': save_global,
'persistent': save_persis,
'unicode': save_unicode,
}
......@@ -672,16 +608,17 @@ class C:
def test():
import xmllib
c=C()
c.foo=1
c.bar=2
x=[0,1,2,3]
y=('abc','abc',c,c)
import pickle
c = C()
c.foo = 1
c.bar = 2
x = [0, 1, 2, 3]
y = ('abc', 'abc', c, c)
x.append(y)
x.append(y)
t=()
l=[]
s=''
t = ()
l = []
s = ''
L = long('999999999999')
x.append(t)
x.append(l)
......@@ -689,78 +626,52 @@ def test():
x.append(L)
x.append(55555)
x.append(13)
r=[x]
r = [x]
print x
f=pickle.dumps(x)
f = pickle.dumps(x)
print f
r.append(f)
q=ToXMLloads(f)
q=str(q)
q='<?xml version="1.0"?>\n'+q
q = ToXMLloads(f)
q = str(q)
q = '<?xml version="1.0"?>\n' + q
print q
r.append(q)
file=''
F=xmlPickler(file)
p=xmllib.XMLParser()
p.start_handlers=F.start_handlers
p.end_handlers=F.end_handlers
p.handle_data=F.handle_data
p.unknown_starttag=F.unknown_starttag
p.unknown_endtag=F.unknown_endtag
p._stack=F._stack
p.push=F.push
p.append=F.append
p.file=F.file
p.tempfile=F.tempfile
p.binary=1
data=string.split(q,'\n')
F = xmlPickler()
F.binary = 1
p = xmllib.XMLParser()
p.start_handlers = F.start_handlers
p.end_handlers = F.end_handlers
p.handle_data = F.handle_data
p.unknown_starttag = F.unknown_starttag
p.unknown_endtag = F.unknown_endtag
p._stack = F._stack
p.push = F.push
p.append = F.append
data = q.split('\n')
for l in data:
p.feed(l)
p.close()
z=p._stack
z=z[0][0]
print z, '\012'
z = p._stack
z = z[0][0]
print z, '\n'
r.append(z)
l=pickle.loads(z)
print l, '\012'
l = pickle.loads(z)
print l, '\n'
r.append(l)
def test1():
import xmllib
q=open('Data.xml').read()
file=open('out','w'+'b')
F=xmlPickler(file,1)
p=xmllib.XMLParser()
p.start_handlers=F.start_handlers
p.end_handlers=F.end_handlers
p.handle_data=F.handle_data
p.unknown_starttag=F.unknown_starttag
p.unknown_endtag=F.unknown_endtag
p._stack=F._stack
p.push=F.push
p.append=F.append
p.file=F.file
p.tempfile=F.tempfile
data=string.split(q,'\n')
for l in data:
p.feed(l)
p.close()
z=p._stack
z=z[0][0]
print z, '\012'
def test2():
import xml.parsers.expat
c=C()
c.foo=1
c.bar=2
x=[0,1,2,3]
y=('abc','abc',c,c)
import pickle
c = C()
c.foo = 1
c.bar = 2
x = [0, 1, 2, 3]
y = ('abc', 'abc', c, c)
x.append(y)
x.append(y)
t=()
l=[]
s=''
t = ()
l = []
s = ''
L = long('999999999999')
x.append(t)
x.append(l)
......@@ -768,36 +679,21 @@ def test2():
x.append(L)
x.append(5)
x.append(13)
print x, '\012'
f=pickle.dumps(x)
print f, '\012'
q=ToXMLloads(f)
q=str(q)
q='<?xml version="1.0"?>\n'+q
print q, '\012'
file=''
F=xmlPickler()
F.binary=0
p=xml.parsers.expat.ParserCreate()
p.CharacterDataHandler=F.handle_data
p.StartElementHandler=F.unknown_starttag
p.EndElementHandler=F.unknown_endtag
r=p.Parse(q)
print r, '\012'
def test3():
import xml.parsers.expat
data=open('Data.xml').read()
file=open('out','w'+'b')
F=xmlPickler()
F.file=file
F.binary=1
p=xml.parsers.expat.ParserCreate()
p.CharacterDataHandler=F.handle_data
p.StartElementHandler=F.unknown_starttag
p.EndElementHandler=F.unknown_endtag
r=p.Parse(data)
print r, '\012'
print x, '\n'
f = pickle.dumps(x)
print f, '\n'
q = ToXMLloads(f)
q = str(q)
q = '<?xml version="1.0"?>\n' + q
print q, '\n'
F = xmlPickler()
F.binary = 0
p = xml.parsers.expat.ParserCreate()
p.CharacterDataHandler = F.handle_data
p.StartElementHandler = F.unknown_starttag
p.EndElementHandler = F.unknown_endtag
r = p.Parse(q)
print r, '\n'
if __name__ == '__main__':
test()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment