#!/var/www/html/soyintegro/venv/bin/python
# -*- coding: utf-8 -*-
# Copyright (C) 2006 Søren Roug, European Environment Agency
#
# This is free software. You may redistribute it under the terms
# of the Apache license and the GNU General Public License Version
# 2 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# Contributor(s):
#
#
# OpenDocument can be a complete office document in a single
# XML document. This script will take such a document and create
# a package
import io
import zipfile,time, sys, getopt
import xml.sax, xml.sax.saxutils
from odf import manifest
class SplitWriter:
def __init__(self):
self.activefiles = []
self._content = []
self._meta = []
self._styles = []
self._settings = []
self.files = {'content': self._content, 'meta': self._meta,
'styles':self._styles, 'settings': self._settings }
def write(self, str):
for f in self.activefiles:
f.append(str)
def activate(self, filename):
file = self.files[filename]
if file not in self.activefiles:
self.activefiles.append(file)
def deactivate(self, filename):
file = self.files[filename]
if file in self.activefiles:
self.activefiles.remove(file)
odmimetypes = {
'application/vnd.oasis.opendocument.text': '.odt',
'application/vnd.oasis.opendocument.text-template': '.ott',
'application/vnd.oasis.opendocument.graphics': '.odg',
'application/vnd.oasis.opendocument.graphics-template': '.otg',
'application/vnd.oasis.opendocument.presentation': '.odp',
'application/vnd.oasis.opendocument.presentation-template': '.otp',
'application/vnd.oasis.opendocument.spreadsheet': '.ods',
'application/vnd.oasis.opendocument.spreadsheet-template': '.ots',
'application/vnd.oasis.opendocument.chart': '.odc',
'application/vnd.oasis.opendocument.chart-template': '.otc',
'application/vnd.oasis.opendocument.image': '.odi',
'application/vnd.oasis.opendocument.image-template': '.oti',
'application/vnd.oasis.opendocument.formula': '.odf',
'application/vnd.oasis.opendocument.formula-template': '.otf',
'application/vnd.oasis.opendocument.text-master': '.odm',
'application/vnd.oasis.opendocument.text-web': '.oth',
}
OFFICENS = u"urn:oasis:names:tc:opendocument:xmlns:office:1.0"
base = xml.sax.saxutils.XMLGenerator
class odfsplitter(base):
def __init__(self):
self._mimetype = ''
self.output = SplitWriter()
self._prefixes = []
base.__init__(self, self.output, 'utf-8')
def startPrefixMapping(self, prefix, uri):
base.startPrefixMapping(self, prefix, uri)
self._prefixes.append('xmlns:%s="%s"' % (prefix, uri))
def startElementNS(self, name, qname, attrs):
if name == (OFFICENS, u"document"):
self._mimetype = attrs.get((OFFICENS, "mimetype"))
elif name == (OFFICENS, u"meta"):
self.output.activate('meta')
elif name == (OFFICENS, u"settings"):
self.output.activate('settings')
elif name == (OFFICENS, u"scripts"):
self.output.activate('content')
elif name == (OFFICENS, u"font-face-decls"):
self.output.activate('content')
self.output.activate('styles')
elif name == (OFFICENS, u"styles"):
self.output.activate('styles')
elif name == (OFFICENS, u"automatic-styles"):
self.output.activate('content')
self.output.activate('styles')
elif name == (OFFICENS, u"master-styles"):
self.output.activate('styles')
elif name == (OFFICENS, u"body"):
self.output.activate('content')
base.startElementNS(self, name, qname, attrs)
def endElementNS(self, name, qname):
base.endElementNS(self, name, qname)
if name == (OFFICENS, u"meta"):
self.output.deactivate('meta')
elif name == (OFFICENS, u"settings"):
self.output.deactivate('settings')
elif name == (OFFICENS, u"scripts"):
self.output.deactivate('content')
elif name == (OFFICENS, u"font-face-decls"):
self.output.deactivate('content')
self.output.deactivate('styles')
elif name == (OFFICENS, u"styles"):
self.output.deactivate('styles')
elif name == (OFFICENS, u"automatic-styles"):
self.output.deactivate('content')
self.output.deactivate('styles')
elif name == (OFFICENS, u"master-styles"):
self.output.deactivate('styles')
elif name == (OFFICENS, u"body"):
self.output.deactivate('content')
def content(self):
""" Return the content inside a wrapper called
"""
prefixes = ' '.join(self._prefixes)
return ''.join(['\n' % prefixes] + list(map(lambda x: x.decode("utf-8"), self.output._content)) + [''])
def settings(self):
prefixes = ' '.join(self._prefixes).encode('utf-8')
return ''.join( ['\n' % prefixes] + self.output._settings + [''''''])
def styles(self):
prefixes = ' '.join(self._prefixes)
return ''.join( ['\n' % prefixes] + list(map(lambda x: x.decode("utf-8"), self.output._styles)) + [''''''])
def meta(self):
prefixes = ' '.join(self._prefixes)
return ''.join( ['\n' % prefixes] + list(map(lambda x: x.decode("utf-8"), self.output._meta)) + [''''''])
def usage():
sys.stderr.write("Usage: %s [-o outputfile] [-s] inputfile\n" % sys.argv[0])
def manifestxml(m):
""" Generates the content of the manifest.xml file """
xml=io.StringIO()
xml.write(u"\n")
m.toXml(0,xml)
return xml.getvalue()
try:
opts, args = getopt.getopt(sys.argv[1:], "o:s", ["output=","suffix"])
except getopt.GetoptError:
usage()
sys.exit(2)
outputfile = '-'
addsuffix = False
for o, a in opts:
if o in ("-o", "--output"):
outputfile = a
if o in ("-s", "--suffix"):
addsuffix = True
if len(args) > 1:
usage()
sys.exit(2)
odfs = odfsplitter()
parser = xml.sax.make_parser()
parser.setFeature(xml.sax.handler.feature_namespaces, 1)
parser.setContentHandler(odfs)
if len(args) == 0:
parser.parse(sys.stdin)
else:
parser.parse(open(args[0],"r"))
mimetype = odfs._mimetype
suffix = odmimetypes.get(mimetype,'.xxx')
if outputfile == '-':
if sys.stdout.isatty():
sys.stderr.write("Won't write ODF file to terminal\n")
sys.exit(1)
z = zipfile.ZipFile(sys.stdout,"w")
else:
if addsuffix:
outputfile = outputfile + suffix
z = zipfile.ZipFile(outputfile,"w")
now = time.localtime()[:6]
# Write mimetype
zi = zipfile.ZipInfo('mimetype', now)
zi.compress_type = zipfile.ZIP_STORED
z.writestr(zi,mimetype)
# Write content
zi = zipfile.ZipInfo("content.xml", now)
zi.compress_type = zipfile.ZIP_DEFLATED
z.writestr(zi,odfs.content() )
# Write styles
zi = zipfile.ZipInfo("styles.xml", now)
zi.compress_type = zipfile.ZIP_DEFLATED
z.writestr(zi,odfs.styles() )
# Write meta
zi = zipfile.ZipInfo("meta.xml", now)
zi.compress_type = zipfile.ZIP_DEFLATED
z.writestr(zi,odfs.meta() )
m = manifest.Manifest()
m.addElement(manifest.FileEntry(fullpath="/", mediatype=mimetype))
m.addElement(manifest.FileEntry(fullpath="content.xml",mediatype="text/xml"))
m.addElement(manifest.FileEntry(fullpath="styles.xml", mediatype="text/xml"))
m.addElement(manifest.FileEntry(fullpath="meta.xml", mediatype="text/xml"))
# Write manifest
zi = zipfile.ZipInfo("META-INF/manifest.xml", now)
zi.compress_type = zipfile.ZIP_DEFLATED
z.writestr(zi, manifestxml(m).encode("utf-8") )
z.close()
# Local Variables: ***
# mode: python ***
# End: ***