Blob Blame History Raw
From 6eba87f4654d3f142070c1fe9f272bf787885861 Mon Sep 17 00:00:00 2001
From: Andres Gomez <agomez@igalia.com>
Date: Thu, 4 Apr 2013 13:18:06 +0300
Subject: [PATCH] python3: added compatibility

Dodgy solution in which we create a python2 and
python3 compatible wrapper that would import the
old script, or a new automatically migrated
version.

The automatic migration was done with the 2to3
tool after modifying the original script so we can
invoke it as a module.

This is needed since LibreOffice is providing its
own python3 bundled package since 4.x series.
---
 Makefile                   |    2 +
 packaging/rpm/unoconv.spec |    2 +
 unoconv                    | 1154 +-----------------------------------------
 unoconv2.py                | 1195 ++++++++++++++++++++++++++++++++++++++++++++
 unoconv3.py                | 1195 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 2406 insertions(+), 1142 deletions(-)
 create mode 100755 unoconv2.py
 create mode 100755 unoconv3.py

diff --git a/Makefile b/Makefile
index 9bb18f6..b950583 100644
--- a/Makefile
+++ b/Makefile
@@ -111,6 +111,8 @@ install:
 	install -d -m0755 $(DESTDIR)$(bindir)
 	install -d -m0755 $(DESTDIR)$(mandir)/man1/
 	install -p -m0755 unoconv $(DESTDIR)$(bindir)/unoconv
+	install -p -m0755 unoconv2.py $(DESTDIR)$(bindir)/unoconv2.py
+	install -p -m0755 unoconv3.py $(DESTDIR)$(bindir)/unoconv3.py
 	install -p -m0644 doc/unoconv.1 $(DESTDIR)$(mandir)/man1/unoconv.1
 
 install-links: $(links)
diff --git a/packaging/rpm/unoconv.spec b/packaging/rpm/unoconv.spec
index 4801dd3..c077fec 100644
--- a/packaging/rpm/unoconv.spec
+++ b/packaging/rpm/unoconv.spec
@@ -49,6 +49,8 @@ and many more...
 %doc AUTHORS ChangeLog COPYING README* WISHLIST doc/ tests/
 %doc %{_mandir}/man1/unoconv.1*
 %{_bindir}/unoconv
+%{_bindir}/unoconv2.py
+%{_bindir}/unoconv3.py
 
 %changelog
 * Mon Sep 10 2012 Dag Wieers <dag@wieers.com> - 0.6-1
diff --git a/unoconv b/unoconv
index 30e6706..ed603af 100755
--- a/unoconv
+++ b/unoconv
@@ -12,1154 +12,24 @@
 ### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-### Copyright 2007-2010 Dag Wieers <dag@wieers.com>
 
-from distutils.version import LooseVersion
-import getopt
-import glob
-import os
-import subprocess
 import sys
-import time
 
-__version__ = "$Revision$"
-# $Source$
+### Extremely dodgy solution for running python2 or python3 versions
+### of the unoconv script
 
-VERSION = '0.6'
+### This is needed since LibreOffice is providing its own python3
+### bundled package since 4.x series
 
-doctypes = ('document', 'graphics', 'presentation', 'spreadsheet')
+### A much more proper solution would be to modify the code so it
+### would be compatible with both versions or, if not possible, to
+### create real python modules out of the code and import them in a
+### proper way
 
-global convertor, office, ooproc, product
-ooproc = None
-exitcode = 0
-
-class Office:
-    def __init__(self, basepath, urepath, unopath, pyuno, binary, python, pythonhome):
-        self.basepath = basepath
-        self.urepath = urepath
-        self.unopath = unopath
-        self.pyuno = pyuno
-        self.binary = binary
-        self.python = python
-        self.pythonhome = pythonhome
-
-    def __str__(self):
-        return self.basepath
-
-    def __repr__(self):
-        return self.basepath
-
-### Implement a path normalizer in order to make unoconv work on MacOS X
-### (on which 'program' is a symlink to 'MacOSX' which seems to break unoconv)
-def realpath(*args):
-    ''' Implement a combination of os.path.join(), os.path.abspath() and
-        os.path.realpath() in order to normalize path constructions '''
-    ret = ''
-    for arg in args:
-        ret = os.path.join(ret, arg)
-    return os.path.realpath(os.path.abspath(ret))
-
-### The first thing we ought to do is find a suitable Office installation
-### with a compatible pyuno library that we can import.
-###
-### See: http://user.services.openoffice.org/en/forum/viewtopic.php?f=45&t=36370&p=166783
-
-def find_offices():
-    ret = []
-    extrapaths = []
-
-    ### Try using UNO_PATH first (in many incarnations, we'll see what sticks)
-    if 'UNO_PATH' in os.environ:
-        extrapaths += [ os.environ['UNO_PATH'],
-                        os.path.dirname(os.environ['UNO_PATH']),
-                        os.path.dirname(os.path.dirname(os.environ['UNO_PATH'])) ]
-
-    else:
-
-        if os.name in ( 'nt', 'os2' ):
-            if 'PROGRAMFILES' in os.environ.keys():
-                extrapaths += glob.glob(os.environ['PROGRAMFILES']+'\\LibreOffice*') + \
-                              glob.glob(os.environ['PROGRAMFILES']+'\\OpenOffice.org*')
-
-            if 'PROGRAMFILES(X86)' in os.environ.keys():
-                extrapaths += glob.glob(os.environ['PROGRAMFILES(X86)']+'\\LibreOffice*') + \
-                              glob.glob(os.environ['PROGRAMFILES(X86)']+'\\OpenOffice.org*')
-
-        elif os.name in ( 'mac', ) or sys.platform in ( 'darwin', ):
-            extrapaths += [ '/Applications/LibreOffice.app/Contents',
-                            '/Applications/NeoOffice.app/Contents',
-                            '/Applications/OpenOffice.org.app/Contents' ]
-
-        else:
-            extrapaths += glob.glob('/usr/lib*/libreoffice*') + \
-                          glob.glob('/usr/lib*/openoffice*') + \
-                          glob.glob('/usr/lib*/ooo*') + \
-                          glob.glob('/opt/libreoffice*') + \
-                          glob.glob('/opt/openoffice*') + \
-                          glob.glob('/opt/ooo*') + \
-                          glob.glob('/usr/local/libreoffice*') + \
-                          glob.glob('/usr/local/openoffice*') + \
-                          glob.glob('/usr/local/ooo*') + \
-                          glob.glob('/usr/local/lib/libreoffice*')
-
-    ### Find a working set for python UNO bindings
-    for basepath in extrapaths:
-        if os.name in ( 'nt', 'os2' ):
-            officelibraries = ( 'pyuno.pyd', )
-            officebinaries = ( 'soffice.exe' ,)
-            pythonbinaries = ( 'python.exe', )
-            pythonhomes = ()
-        elif os.name in ( 'mac', ) or sys.platform in ( 'darwin', ):
-            officelibraries = ( 'pyuno.so', 'libpyuno.dylib' )
-            officebinaries = ( 'soffice.bin', )
-            pythonbinaries = ( 'python.bin', 'python' )
-            pythonhomes = ( 'OOoPython.framework/Versions/*/lib/python*', )
-        else:
-            officelibraries = ( 'pyuno.so', )
-            officebinaries = ( 'soffice.bin', )
-            pythonbinaries = ( 'python.bin', 'python', )
-            pythonhomes = ( 'python-core-*', )
-
-        ### Older LibreOffice/OpenOffice and Windows use basis-link/ or basis/
-        libpath = 'error'
-        for basis in ( 'basis-link', 'basis', '' ):
-            for lib in officelibraries:
-                if os.path.isfile(realpath(basepath, basis, 'program', lib)):
-                    libpath = realpath(basepath, basis, 'program')
-                    officelibrary = realpath(libpath, lib)
-                    info(3, "Found %s in %s" % (lib, libpath))
-                    # Break the inner loop...
-                    break
-            # Continue if the inner loop wasn't broken.
-            else:
-                continue
-            # Inner loop was broken, break the outer.
-            break
-        else:
-            continue
-
-        ### MacOSX have soffice binaries installed in MacOS subdirectory, not program
-        unopath = 'error'
-        for basis in ( 'basis-link', 'basis', '' ):
-            for bin in officebinaries:
-                if os.path.isfile(realpath(basepath, basis, 'program', bin)):
-                    unopath = realpath(basepath, basis, 'program')
-                    officebinary = realpath(unopath, bin)
-                    info(3, "Found %s in %s" % (bin, unopath))
-                    # Break the inner loop...
-                    break
-            # Continue if the inner loop wasn't broken.
-            else:
-                continue
-            # Inner loop was broken, break the outer.
-            break
-        else:
-            continue
-
-        ### Windows does not provide or need a URE/lib directory ?
-        urepath = ''
-        for basis in ( 'basis-link', 'basis', '' ):
-            for ure in ( 'ure-link', 'ure', 'URE', '' ):
-                if os.path.isfile(realpath(basepath, basis, ure, 'lib', 'unorc')):
-                    urepath = realpath(basepath, basis, ure)
-                    info(3, "Found %s in %s" % ('unorc', realpath(urepath, 'lib')))
-                    # Break the inner loop...
-                    break
-            # Continue if the inner loop wasn't broken.
-            else:
-                continue
-            # Inner loop was broken, break the outer.
-            break
-
-        pythonhome = None
-        for home in pythonhomes:
-            if glob.glob(realpath(libpath, home)):
-                pythonhome = glob.glob(realpath(libpath, home))[0]
-                info(3, "Found %s in %s" % (home, pythonhome))
-                break
-
-#        if not os.path.isfile(realpath(basepath, program, officebinary)):
-#            continue
-#        info(3, "Found %s in %s" % (officebinary, realpath(basepath, program)))
-
-#        if not glob.glob(realpath(basepath, basis, program, 'python-core-*')):
-#            continue
-
-        for pythonbinary in pythonbinaries:
-            if os.path.isfile(realpath(unopath, pythonbinary)):
-                info(3, "Found %s in %s" % (pythonbinary, unopath))
-                ret.append(Office(basepath, urepath, unopath, officelibrary, officebinary,
-                                  realpath(unopath, pythonbinary), pythonhome))
-        else:
-            info(3, "Considering %s" % basepath)
-            ret.append(Office(basepath, urepath, unopath, officelibrary, officebinary,
-                              sys.executable, None))
-    return ret
-
-def office_environ(office):
-    ### Set PATH so that crash_report is found
-    os.environ['PATH'] = realpath(office.basepath, 'program') + os.pathsep + os.environ['PATH']
-
-    ### Set UNO_PATH so that "officehelper.bootstrap()" can find soffice executable:
-    os.environ['UNO_PATH'] = office.unopath
-
-    ### Set URE_BOOTSTRAP so that "uno.getComponentContext()" bootstraps a complete
-    ### UNO environment
-    if os.name in ( 'nt', 'os2' ):
-        os.environ['URE_BOOTSTRAP'] = 'vnd.sun.star.pathname:' + realpath(office.basepath, 'program', 'fundamental.ini')
-    else:
-        os.environ['URE_BOOTSTRAP'] = 'vnd.sun.star.pathname:' + realpath(office.basepath, 'program', 'fundamentalrc')
-
-        ### Set LD_LIBRARY_PATH so that "import pyuno" finds libpyuno.so:
-        if 'LD_LIBRARY_PATH' in os.environ:
-            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
-                                            realpath(office.urepath, 'lib') + os.pathsep + \
-                                            os.environ['LD_LIBRARY_PATH']
-        else:
-            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
-                                            realpath(office.urepath, 'lib')
-
-    if office.pythonhome:
-        for libpath in ( realpath(office.pythonhome, 'lib'),
-                         realpath(office.pythonhome, 'lib', 'lib-dynload'),
-                         realpath(office.pythonhome, 'lib', 'lib-tk'),
-                         realpath(office.pythonhome, 'lib', 'site-packages'),
-                         office.unopath):
-            sys.path.insert(0, libpath)
-    else:
-        ### Still needed for system python using LibreOffice UNO bindings
-        ### Although we prefer to use a system UNO binding in this case
-        sys.path.append(office.unopath)
-
-def debug_office():
-    if 'URE_BOOTSTRAP' in os.environ:
-        print >>sys.stderr, 'URE_BOOTSTRAP=%s' % os.environ['URE_BOOTSTRAP']
-    if 'UNO_PATH' in os.environ:
-        print >>sys.stderr, 'UNO_PATH=%s' % os.environ['UNO_PATH']
-    if 'UNO_TYPES' in os.environ:
-        print >>sys.stderr, 'UNO_TYPES=%s' % os.environ['UNO_TYPES']
-    print 'PATH=%s' % os.environ['PATH']
-    if 'PYTHONHOME' in os.environ:
-        print >>sys.stderr, 'PYTHONHOME=%s' % os.environ['PYTHONHOME']
-    if 'PYTHONPATH' in os.environ:
-        print >>sys.stderr, 'PYTHONPATH=%s' % os.environ['PYTHONPATH']
-    if 'LD_LIBRARY_PATH' in os.environ:
-        print >>sys.stderr, 'LD_LIBRARY_PATH=%s' % os.environ['LD_LIBRARY_PATH']
-
-def python_switch(office):
-    if office.pythonhome:
-        os.environ['PYTHONHOME'] = office.pythonhome
-        os.environ['PYTHONPATH'] = realpath(office.pythonhome, 'lib') + os.pathsep + \
-                                   realpath(office.pythonhome, 'lib', 'lib-dynload') + os.pathsep + \
-                                   realpath(office.pythonhome, 'lib', 'lib-tk') + os.pathsep + \
-                                   realpath(office.pythonhome, 'lib', 'site-packages') + os.pathsep + \
-                                   office.unopath
-
-    os.environ['UNO_PATH'] = office.unopath
-
-    info(3, "-> Switching from %s to %s" % (sys.executable, office.python))
-    if os.name in ('nt', 'os2'):
-        ### os.execv is broken on Windows and can't properly parse command line
-        ### arguments and executable name if they contain whitespaces. subprocess
-        ### fixes that behavior.
-        ret = subprocess.call([office.python] + sys.argv[0:])
-        sys.exit(ret)
-    else:
-
-        ### Set LD_LIBRARY_PATH so that "import pyuno" finds libpyuno.so:
-        if 'LD_LIBRARY_PATH' in os.environ:
-            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
-                                            realpath(office.urepath, 'lib') + os.pathsep + \
-                                            os.environ['LD_LIBRARY_PATH']
-        else:
-            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
-                                            realpath(office.urepath, 'lib')
-
-        try:
-            os.execvpe(office.python, [office.python, ] + sys.argv[0:], os.environ)
-        except OSError:
-            ### Mac OS X versions prior to 10.6 do not support execv in
-            ### a process that contains multiple threads.  Instead of
-            ### re-executing in the current process, start a new one
-            ### and cause the current process to exit.  This isn't
-            ### ideal since the new process is detached from the parent
-            ### terminal and thus cannot easily be killed with ctrl-C,
-            ### but it's better than not being able to autoreload at
-            ### all.
-            ### Unfortunately the errno returned in this case does not
-            ### appear to be consistent, so we can't easily check for
-            ### this error specifically.
-            ret = os.spawnvpe(os.P_WAIT, office.python, [office.python, ] + sys.argv[0:], os.environ)
-            sys.exit(ret)
-
-class Fmt:
-    def __init__(self, doctype, name, extension, summary, filter):
-        self.doctype = doctype
-        self.name = name
-        self.extension = extension
-        self.summary = summary
-        self.filter = filter
-
-    def __str__(self):
-        return "%s [.%s]" % (self.summary, self.extension)
-
-    def __repr__(self):
-        return "%s/%s" % (self.name, self.doctype)
-
-class FmtList:
-    def __init__(self):
-        self.list = []
-
-    def add(self, doctype, name, extension, summary, filter):
-        self.list.append(Fmt(doctype, name, extension, summary, filter))
-
-    def byname(self, name):
-        ret = []
-        for fmt in self.list:
-            if fmt.name == name:
-                ret.append(fmt)
-        return ret
-
-    def byextension(self, extension):
-        ret = []
-        for fmt in self.list:
-            if os.extsep + fmt.extension == extension:
-                ret.append(fmt)
-        return ret
-
-    def bydoctype(self, doctype, name):
-        ret = []
-        for fmt in self.list:
-            if fmt.name == name and fmt.doctype == doctype:
-                ret.append(fmt)
-        return ret
-
-    def display(self, doctype):
-        print >>sys.stderr, "The following list of %s formats are currently available:\n" % doctype
-        for fmt in self.list:
-            if fmt.doctype == doctype:
-                print >>sys.stderr, "  %-8s - %s" % (fmt.name, fmt)
-        print >>sys.stderr
-
-fmts = FmtList()
-
-### TextDocument
-fmts.add('document', 'bib', 'bib', 'BibTeX', 'BibTeX_Writer') ### 22
-fmts.add('document', 'doc', 'doc', 'Microsoft Word 97/2000/XP', 'MS Word 97') ### 29
-fmts.add('document', 'doc6', 'doc', 'Microsoft Word 6.0', 'MS WinWord 6.0') ### 24
-fmts.add('document', 'doc95', 'doc', 'Microsoft Word 95', 'MS Word 95') ### 28
-fmts.add('document', 'docbook', 'xml', 'DocBook', 'DocBook File') ### 39
-fmts.add('document', 'docx', 'docx', 'Microsoft Office Open XML', 'Office Open XML Text')
-fmts.add('document', 'docx7', 'docx', 'Microsoft Office Open XML', 'MS Word 2007 XML')
-fmts.add('document', 'fodt', 'fodt', 'OpenDocument Text (Flat XML)', 'OpenDocument Text Flat XML')
-fmts.add('document', 'html', 'html', 'HTML Document (OpenOffice.org Writer)', 'HTML (StarWriter)') ### 3
-fmts.add('document', 'latex', 'ltx', 'LaTeX 2e', 'LaTeX_Writer') ### 31
-fmts.add('document', 'mediawiki', 'txt', 'MediaWiki', 'MediaWiki')
-fmts.add('document', 'odt', 'odt', 'ODF Text Document', 'writer8') ### 10
-fmts.add('document', 'ooxml', 'xml', 'Microsoft Office Open XML', 'MS Word 2003 XML') ### 11
-fmts.add('document', 'ott', 'ott', 'Open Document Text', 'writer8_template') ### 21
-fmts.add('document', 'pdb', 'pdb', 'AportisDoc (Palm)', 'AportisDoc Palm DB')
-fmts.add('document', 'pdf', 'pdf', 'Portable Document Format', 'writer_pdf_Export') ### 18
-fmts.add('document', 'psw', 'psw', 'Pocket Word', 'PocketWord File')
-fmts.add('document', 'rtf', 'rtf', 'Rich Text Format', 'Rich Text Format') ### 16
-fmts.add('document', 'sdw', 'sdw', 'StarWriter 5.0', 'StarWriter 5.0') ### 23
-fmts.add('document', 'sdw4', 'sdw', 'StarWriter 4.0', 'StarWriter 4.0') ### 2
-fmts.add('document', 'sdw3', 'sdw', 'StarWriter 3.0', 'StarWriter 3.0') ### 20
-fmts.add('document', 'stw', 'stw', 'Open Office.org 1.0 Text Document Template', 'writer_StarOffice_XML_Writer_Template') ### 9
-fmts.add('document', 'sxw', 'sxw', 'Open Office.org 1.0 Text Document', 'StarOffice XML (Writer)') ### 1
-fmts.add('document', 'text', 'txt', 'Text Encoded', 'Text (encoded)') ### 26
-fmts.add('document', 'txt', 'txt', 'Text', 'Text') ### 34
-fmts.add('document', 'uot', 'uot', 'Unified Office Format text','UOF text') ### 27
-fmts.add('document', 'vor', 'vor', 'StarWriter 5.0 Template', 'StarWriter 5.0 Vorlage/Template') ### 6
-fmts.add('document', 'vor4', 'vor', 'StarWriter 4.0 Template', 'StarWriter 4.0 Vorlage/Template') ### 5
-fmts.add('document', 'vor3', 'vor', 'StarWriter 3.0 Template', 'StarWriter 3.0 Vorlage/Template') ### 4
-fmts.add('document', 'xhtml', 'html', 'XHTML Document', 'XHTML Writer File') ### 33
-
-### WebDocument
-fmts.add('web', 'etext', 'txt', 'Text Encoded (OpenOffice.org Writer/Web)', 'Text (encoded) (StarWriter/Web)') ### 14
-fmts.add('web', 'html10', 'html', 'OpenOffice.org 1.0 HTML Template', 'writer_web_StarOffice_XML_Writer_Web_Template') ### 11
-fmts.add('web', 'html', 'html', 'HTML Document', 'HTML') ### 2
-fmts.add('web', 'html', 'html', 'HTML Document Template', 'writerweb8_writer_template') ### 13
-fmts.add('web', 'mediawiki', 'txt', 'MediaWiki', 'MediaWiki_Web') ### 9
-fmts.add('web', 'pdf', 'pdf', 'PDF - Portable Document Format', 'writer_web_pdf_Export') ### 10
-fmts.add('web', 'sdw3', 'sdw', 'StarWriter 3.0 (OpenOffice.org Writer/Web)', 'StarWriter 3.0 (StarWriter/Web)') ### 3
-fmts.add('web', 'sdw4', 'sdw', 'StarWriter 4.0 (OpenOffice.org Writer/Web)', 'StarWriter 4.0 (StarWriter/Web)') ### 4
-fmts.add('web', 'sdw', 'sdw', 'StarWriter 5.0 (OpenOffice.org Writer/Web)', 'StarWriter 5.0 (StarWriter/Web)') ### 5
-fmts.add('web', 'txt', 'txt', 'OpenOffice.org Text (OpenOffice.org Writer/Web)', 'writerweb8_writer') ### 12
-fmts.add('web', 'text10', 'txt', 'OpenOffice.org 1.0 Text Document (OpenOffice.org Writer/Web)', 'writer_web_StarOffice_XML_Writer') ### 15
-fmts.add('web', 'text', 'txt', 'Text (OpenOffice.org Writer/Web)', 'Text (StarWriter/Web)') ### 8
-fmts.add('web', 'vor4', 'vor', 'StarWriter/Web 4.0 Template', 'StarWriter/Web 4.0 Vorlage/Template') ### 6
-fmts.add('web', 'vor', 'vor', 'StarWriter/Web 5.0 Template', 'StarWriter/Web 5.0 Vorlage/Template') ### 7
-
-### Spreadsheet
-fmts.add('spreadsheet', 'csv', 'csv', 'Text CSV', 'Text - txt - csv (StarCalc)') ### 16
-fmts.add('spreadsheet', 'dbf', 'dbf', 'dBASE', 'dBase') ### 22
-fmts.add('spreadsheet', 'dif', 'dif', 'Data Interchange Format', 'DIF') ### 5
-fmts.add('spreadsheet', 'fods', 'fods', 'OpenDocument Spreadsheet (Flat XML)', 'OpenDocument Spreadsheet Flat XML')
-fmts.add('spreadsheet', 'html', 'html', 'HTML Document (OpenOffice.org Calc)', 'HTML (StarCalc)') ### 7
-fmts.add('spreadsheet', 'ods', 'ods', 'ODF Spreadsheet', 'calc8') ### 15
-fmts.add('spreadsheet', 'ooxml', 'xml', 'Microsoft Excel 2003 XML', 'MS Excel 2003 XML') ### 23
-fmts.add('spreadsheet', 'ots', 'ots', 'ODF Spreadsheet Template', 'calc8_template') ### 14
-fmts.add('spreadsheet', 'pdf', 'pdf', 'Portable Document Format', 'calc_pdf_Export') ### 34
-fmts.add('spreadsheet', 'pxl', 'pxl', 'Pocket Excel', 'Pocket Excel')
-fmts.add('spreadsheet', 'sdc', 'sdc', 'StarCalc 5.0', 'StarCalc 5.0') ### 31
-fmts.add('spreadsheet', 'sdc4', 'sdc', 'StarCalc 4.0', 'StarCalc 4.0') ### 11
-fmts.add('spreadsheet', 'sdc3', 'sdc', 'StarCalc 3.0', 'StarCalc 3.0') ### 29
-fmts.add('spreadsheet', 'slk', 'slk', 'SYLK', 'SYLK') ### 35
-fmts.add('spreadsheet', 'stc', 'stc', 'OpenOffice.org 1.0 Spreadsheet Template', 'calc_StarOffice_XML_Calc_Template') ### 2
-fmts.add('spreadsheet', 'sxc', 'sxc', 'OpenOffice.org 1.0 Spreadsheet', 'StarOffice XML (Calc)') ### 3
-fmts.add('spreadsheet', 'uos', 'uos', 'Unified Office Format spreadsheet', 'UOF spreadsheet') ### 9
-fmts.add('spreadsheet', 'vor3', 'vor', 'StarCalc 3.0 Template', 'StarCalc 3.0 Vorlage/Template') ### 18
-fmts.add('spreadsheet', 'vor4', 'vor', 'StarCalc 4.0 Template', 'StarCalc 4.0 Vorlage/Template') ### 19
-fmts.add('spreadsheet', 'vor', 'vor', 'StarCalc 5.0 Template', 'StarCalc 5.0 Vorlage/Template') ### 20
-fmts.add('spreadsheet', 'xhtml', 'xhtml', 'XHTML', 'XHTML Calc File') ### 26
-fmts.add('spreadsheet', 'xls', 'xls', 'Microsoft Excel 97/2000/XP', 'MS Excel 97') ### 12
-fmts.add('spreadsheet', 'xls5', 'xls', 'Microsoft Excel 5.0', 'MS Excel 5.0/95') ### 8
-fmts.add('spreadsheet', 'xls95', 'xls', 'Microsoft Excel 95', 'MS Excel 95') ### 10
-fmts.add('spreadsheet', 'xlt', 'xlt', 'Microsoft Excel 97/2000/XP Template', 'MS Excel 97 Vorlage/Template') ### 6
-fmts.add('spreadsheet', 'xlt5', 'xlt', 'Microsoft Excel 5.0 Template', 'MS Excel 5.0/95 Vorlage/Template') ### 28
-fmts.add('spreadsheet', 'xlt95', 'xlt', 'Microsoft Excel 95 Template', 'MS Excel 95 Vorlage/Template') ### 21
-
-### Graphics
-fmts.add('graphics', 'bmp', 'bmp', 'Windows Bitmap', 'draw_bmp_Export') ### 21
-fmts.add('graphics', 'emf', 'emf', 'Enhanced Metafile', 'draw_emf_Export') ### 15
-fmts.add('graphics', 'eps', 'eps', 'Encapsulated PostScript', 'draw_eps_Export') ### 48
-fmts.add('graphics', 'fodg', 'fodg', 'OpenDocument Drawing (Flat XML)', 'OpenDocument Drawing Flat XML')
-fmts.add('graphics', 'gif', 'gif', 'Graphics Interchange Format', 'draw_gif_Export') ### 30
-fmts.add('graphics', 'html', 'html', 'HTML Document (OpenOffice.org Draw)', 'draw_html_Export') ### 37
-fmts.add('graphics', 'jpg', 'jpg', 'Joint Photographic Experts Group', 'draw_jpg_Export') ### 3
-fmts.add('graphics', 'met', 'met', 'OS/2 Metafile', 'draw_met_Export') ### 43
-fmts.add('graphics', 'odd', 'odd', 'OpenDocument Drawing', 'draw8') ### 6
-fmts.add('graphics', 'otg', 'otg', 'OpenDocument Drawing Template', 'draw8_template') ### 20
-fmts.add('graphics', 'pbm', 'pbm', 'Portable Bitmap', 'draw_pbm_Export') ### 14
-fmts.add('graphics', 'pct', 'pct', 'Mac Pict', 'draw_pct_Export') ### 41
-fmts.add('graphics', 'pdf', 'pdf', 'Portable Document Format', 'draw_pdf_Export') ### 28
-fmts.add('graphics', 'pgm', 'pgm', 'Portable Graymap', 'draw_pgm_Export') ### 11
-fmts.add('graphics', 'png', 'png', 'Portable Network Graphic', 'draw_png_Export') ### 2
-fmts.add('graphics', 'ppm', 'ppm', 'Portable Pixelmap', 'draw_ppm_Export') ### 5
-fmts.add('graphics', 'ras', 'ras', 'Sun Raster Image', 'draw_ras_Export') ## 31
-fmts.add('graphics', 'std', 'std', 'OpenOffice.org 1.0 Drawing Template', 'draw_StarOffice_XML_Draw_Template') ### 53
-fmts.add('graphics', 'svg', 'svg', 'Scalable Vector Graphics', 'draw_svg_Export') ### 50
-fmts.add('graphics', 'svm', 'svm', 'StarView Metafile', 'draw_svm_Export') ### 55
-fmts.add('graphics', 'swf', 'swf', 'Macromedia Flash (SWF)', 'draw_flash_Export') ### 23
-fmts.add('graphics', 'sxd', 'sxd', 'OpenOffice.org 1.0 Drawing', 'StarOffice XML (Draw)') ### 26
-fmts.add('graphics', 'sxd3', 'sxd', 'StarDraw 3.0', 'StarDraw 3.0') ### 40
-fmts.add('graphics', 'sxd5', 'sxd', 'StarDraw 5.0', 'StarDraw 5.0') ### 44
-fmts.add('graphics', 'sxw', 'sxw', 'StarOffice XML (Draw)', 'StarOffice XML (Draw)')
-fmts.add('graphics', 'tiff', 'tiff', 'Tagged Image File Format', 'draw_tif_Export') ### 13
-fmts.add('graphics', 'vor', 'vor', 'StarDraw 5.0 Template', 'StarDraw 5.0 Vorlage') ### 36
-fmts.add('graphics', 'vor3', 'vor', 'StarDraw 3.0 Template', 'StarDraw 3.0 Vorlage') ### 35
-fmts.add('graphics', 'wmf', 'wmf', 'Windows Metafile', 'draw_wmf_Export') ### 8
-fmts.add('graphics', 'xhtml', 'xhtml', 'XHTML', 'XHTML Draw File') ### 45
-fmts.add('graphics', 'xpm', 'xpm', 'X PixMap', 'draw_xpm_Export') ### 19
-
-### Presentation
-fmts.add('presentation', 'bmp', 'bmp', 'Windows Bitmap', 'impress_bmp_Export') ### 15
-fmts.add('presentation', 'emf', 'emf', 'Enhanced Metafile', 'impress_emf_Export') ### 16
-fmts.add('presentation', 'eps', 'eps', 'Encapsulated PostScript', 'impress_eps_Export') ### 17
-fmts.add('presentation', 'fodp', 'fodp', 'OpenDocument Presentation (Flat XML)', 'OpenDocument Presentation Flat XML')
-fmts.add('presentation', 'gif', 'gif', 'Graphics Interchange Format', 'impress_gif_Export') ### 18
-fmts.add('presentation', 'html', 'html', 'HTML Document (OpenOffice.org Impress)', 'impress_html_Export') ### 43
-fmts.add('presentation', 'jpg', 'jpg', 'Joint Photographic Experts Group', 'impress_jpg_Export') ### 19
-fmts.add('presentation', 'met', 'met', 'OS/2 Metafile', 'impress_met_Export') ### 20
-fmts.add('presentation', 'odg', 'odg', 'ODF Drawing (Impress)', 'impress8_draw') ### 29
-fmts.add('presentation', 'odp', 'odp', 'ODF Presentation', 'impress8') ### 9
-fmts.add('presentation', 'otp', 'otp', 'ODF Presentation Template', 'impress8_template') ### 38
-fmts.add('presentation', 'pbm', 'pbm', 'Portable Bitmap', 'impress_pbm_Export') ### 21
-fmts.add('presentation', 'pct', 'pct', 'Mac Pict', 'impress_pct_Export') ### 22
-fmts.add('presentation', 'pdf', 'pdf', 'Portable Document Format', 'impress_pdf_Export') ### 23
-fmts.add('presentation', 'pgm', 'pgm', 'Portable Graymap', 'impress_pgm_Export') ### 24
-fmts.add('presentation', 'png', 'png', 'Portable Network Graphic', 'impress_png_Export') ### 25
-fmts.add('presentation', 'potm', 'potm', 'Microsoft PowerPoint 2007/2010 XML Template', 'Impress MS PowerPoint 2007 XML Template')
-fmts.add('presentation', 'pot', 'pot', 'Microsoft PowerPoint 97/2000/XP Template', 'MS PowerPoint 97 Vorlage') ### 3
-fmts.add('presentation', 'ppm', 'ppm', 'Portable Pixelmap', 'impress_ppm_Export') ### 26
-fmts.add('presentation', 'pptx', 'pptx', 'Microsoft PowerPoint 2007/2010 XML', 'Impress MS PowerPoint 2007 XML') ### 36
-fmts.add('presentation', 'pps', 'pps', 'Microsoft PowerPoint 97/2000/XP (Autoplay)', 'MS PowerPoint 97 Autoplay') ### 36
-fmts.add('presentation', 'ppt', 'ppt', 'Microsoft PowerPoint 97/2000/XP', 'MS PowerPoint 97') ### 36
-fmts.add('presentation', 'pwp', 'pwp', 'PlaceWare', 'placeware_Export') ### 30
-fmts.add('presentation', 'ras', 'ras', 'Sun Raster Image', 'impress_ras_Export') ### 27
-fmts.add('presentation', 'sda', 'sda', 'StarDraw 5.0 (OpenOffice.org Impress)', 'StarDraw 5.0 (StarImpress)') ### 8
-fmts.add('presentation', 'sdd', 'sdd', 'StarImpress 5.0', 'StarImpress 5.0') ### 6
-fmts.add('presentation', 'sdd3', 'sdd', 'StarDraw 3.0 (OpenOffice.org Impress)', 'StarDraw 3.0 (StarImpress)') ### 42
-fmts.add('presentation', 'sdd4', 'sdd', 'StarImpress 4.0', 'StarImpress 4.0') ### 37
-fmts.add('presentation', 'sxd', 'sxd', 'OpenOffice.org 1.0 Drawing (OpenOffice.org Impress)', 'impress_StarOffice_XML_Draw') ### 31
-fmts.add('presentation', 'sti', 'sti', 'OpenOffice.org 1.0 Presentation Template', 'impress_StarOffice_XML_Impress_Template') ### 5
-fmts.add('presentation', 'svg', 'svg', 'Scalable Vector Graphics', 'impress_svg_Export') ### 14
-fmts.add('presentation', 'svm', 'svm', 'StarView Metafile', 'impress_svm_Export') ### 13
-fmts.add('presentation', 'swf', 'swf', 'Macromedia Flash (SWF)', 'impress_flash_Export') ### 34
-fmts.add('presentation', 'sxi', 'sxi', 'OpenOffice.org 1.0 Presentation', 'StarOffice XML (Impress)') ### 41
-fmts.add('presentation', 'tiff', 'tiff', 'Tagged Image File Format', 'impress_tif_Export') ### 12
-fmts.add('presentation', 'uop', 'uop', 'Unified Office Format presentation', 'UOF presentation') ### 4
-fmts.add('presentation', 'vor', 'vor', 'StarImpress 5.0 Template', 'StarImpress 5.0 Vorlage') ### 40
-fmts.add('presentation', 'vor3', 'vor', 'StarDraw 3.0 Template (OpenOffice.org Impress)', 'StarDraw 3.0 Vorlage (StarImpress)') ###1
-fmts.add('presentation', 'vor4', 'vor', 'StarImpress 4.0 Template', 'StarImpress 4.0 Vorlage') ### 39
-fmts.add('presentation', 'vor5', 'vor', 'StarDraw 5.0 Template (OpenOffice.org Impress)', 'StarDraw 5.0 Vorlage (StarImpress)') ### 2
-fmts.add('presentation', 'wmf', 'wmf', 'Windows Metafile', 'impress_wmf_Export') ### 11
-fmts.add('presentation', 'xhtml', 'xml', 'XHTML', 'XHTML Impress File') ### 33
-fmts.add('presentation', 'xpm', 'xpm', 'X PixMap', 'impress_xpm_Export') ### 10
-
-class Options:
-    def __init__(self, args):
-        self.connection = None
-        self.debug = False
-        self.doctype = None
-        self.exportfilter = []
-        self.exportfilteroptions = ""
-        self.filenames = []
-        self.format = None
-        self.importfilter = []
-        self.importfilteroptions = ""
-        self.listener = False
-        self.nolaunch = False
-        self.output = None
-        self.password = None
-        self.pipe = None
-        self.port = '2002'
-        self.server = '127.0.0.1'
-        self.showlist = False
-        self.stdout = False
-        self.template = None
-        self.timeout = 6
-        self.verbose = 0
-
-        ### Get options from the commandline
-        try:
-            opts, args = getopt.getopt (args, 'c:Dd:e:f:hi:Llo:np:s:T:t:vV',
-                ['connection=', 'debug', 'doctype=', 'export=', 'format=',
-                 'help', 'import', 'listener', 'no-launch', 'output=',
-                 'outputpath', 'password=', 'pipe=', 'port=', 'server=',
-                 'timeout=', 'show', 'stdout', 'template', 'verbose',
-                 'version'] )
-        except getopt.error, exc:
-            print 'unoconv: %s, try unoconv -h for a list of all the options' % str(exc)
-            sys.exit(255)
-
-        for opt, arg in opts:
-            if opt in ['-h', '--help']:
-                self.usage()
-                print
-                self.help()
-                sys.exit(1)
-            elif opt in ['-c', '--connection']:
-                self.connection = arg
-            elif opt in ['--debug']:
-                self.debug = True
-            elif opt in ['-d', '--doctype']:
-                self.doctype = arg
-            elif opt in ['-e', '--export']:
-                l = arg.split('=')
-                if len(l) == 2:
-                    (name, value) = l
-                    if name in ('FilterOptions'):
-                        self.exportfilteroptions = value
-                    elif value in ('True', 'true'):
-                        self.exportfilter.append( PropertyValue( name, 0, True, 0 ) )
-                    elif value in ('False', 'false'):
-                        self.exportfilter.append( PropertyValue( name, 0, False, 0 ) )
-                    else:
-                        try:
-                            self.exportfilter.append( PropertyValue( name, 0, int(value), 0 ) )
-                        except ValueError:
-                            self.exportfilter.append( PropertyValue( name, 0, value, 0 ) )
-                else:
-                    print >>sys.stderr, 'Warning: Option %s cannot be parsed, ignoring.' % arg
-            elif opt in ['-f', '--format']:
-                self.format = arg
-            elif opt in ['-i', '--import']:
-                l = arg.split('=')
-                if len(l) == 2:
-                    (name, value) = l
-                    if name in ('FilterOptions'):
-                        self.importfilteroptions = value
-                    elif value in ('True', 'true'):
-                        self.importfilter.append( PropertyValue( name, 0, True, 0 ) )
-                    elif value in ('False', 'false'):
-                        self.importfilter.append( PropertyValue( name, 0, False, 0 ) )
-                    else:
-                        try:
-                            self.importfilter.append( PropertyValue( name, 0, int(value), 0 ) )
-                        except ValueError:
-                            self.importfilter.append( PropertyValue( name, 0, value, 0 ) )
-                else:
-                    print >>sys.stderr, 'Warning: Option %s cannot be parsed, ignoring.' % arg
-            elif opt in ['-l', '--listener']:
-                self.listener = True
-            elif opt in ['-n', '--no-launch']:
-                self.nolaunch = True
-            elif opt in ['-o', '--output']:
-                self.output = arg
-            elif opt in ['--outputpath']:
-                print >>sys.stderr, 'Warning: This option is deprecated by --output.'
-                self.output = arg
-            elif opt in ['--password']:
-                self.password = arg
-            elif opt in ['--pipe']:
-                self.pipe = arg
-            elif opt in ['-p', '--port']:
-                self.port = arg
-            elif opt in ['-s', '--server']:
-                self.server = arg
-            elif opt in ['--show']:
-                self.showlist = True
-            elif opt in ['--stdout']:
-                self.stdout = True
-            elif opt in ['-t', '--template']:
-                self.template = arg
-            elif opt in ['-T', '--timeout']:
-                self.timeout = int(arg)
-            elif opt in ['-v', '--verbose']:
-                self.verbose = self.verbose + 1
-            elif opt in ['-V', '--version']:
-                self.version()
-                sys.exit(255)
-
-        ### Enable verbosity
-        if self.verbose >= 2:
-            print >>sys.stderr, 'Verbosity set to level %d' % self.verbose
-
-        self.filenames = args
-
-        if not self.listener and not self.showlist and self.doctype != 'list' and not self.filenames:
-            print >>sys.stderr, 'unoconv: you have to provide a filename as argument'
-            print >>sys.stderr, 'Try `unoconv -h\' for more information.'
-            sys.exit(255)
-
-        ### Set connection string
-        if not self.connection:
-            if not self.pipe:
-                self.connection = "socket,host=%s,port=%s;urp;StarOffice.ComponentContext" % (self.server, self.port)
-#               self.connection = "socket,host=%s,port=%s;urp;" % (self.server, self.port)
-            else:
-                self.connection = "pipe,name=%s;urp;StarOffice.ComponentContext" % (self.pipe)
-
-        ### Make it easier for people to use a doctype (first letter is enough)
-        if self.doctype:
-            for doctype in doctypes:
-                if doctype.startswith(self.doctype):
-                    self.doctype = doctype
-
-        ### Check if the user request to see the list of formats
-        if self.showlist or self.format == 'list':
-            if self.doctype:
-                fmts.display(self.doctype)
-            else:
-                for t in doctypes:
-                    fmts.display(t)
-            sys.exit(0)
-
-        ### If no format was specified, probe it or provide it
-        if not self.format:
-            l = sys.argv[0].split('2')
-            if len(l) == 2:
-                self.format = l[1]
-            else:
-                self.format = 'pdf'
-
-    def version(self):
-        ### Get office product information
-        product = uno.getComponentContext().ServiceManager.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", UnoProps(nodepath="/org.openoffice.Setup/Product"))
-
-        print 'unoconv %s' % VERSION
-        print 'Written by Dag Wieers <dag@wieers.com>'
-        print 'Homepage at http://dag.wieers.com/home-made/unoconv/'
-        print
-        print 'platform %s/%s' % (os.name, sys.platform)
-        print 'python %s' % sys.version
-        print product.ooName, product.ooSetupVersion
-#        print
-#        print 'build revision $Rev$'
-
-    def usage(self):
-        print >>sys.stderr, 'usage: unoconv [options] file [file2 ..]'
-
-    def help(self):
-        print >>sys.stderr, '''Convert from and to any format supported by LibreOffice
-
-unoconv options:
-  -c, --connection=string  use a custom connection string
-  -d, --doctype=type       specify document type
-                             (document, graphics, presentation, spreadsheet)
-  -e, --export=name=value  set export filter options
-                             eg. -e PageRange=1-2
-  -f, --format=format      specify the output format
-  -i, --import=string      set import filter option string
-                             eg. -i utf8
-  -l, --listener           start a permanent listener to use by unoconv clients
-  -n, --no-launch          fail if no listener is found (default: launch one)
-  -o, --output=name        output basename, filename or directory
-      --pipe=name          alternative method of connection using a pipe
-  -p, --port=port          specify the port (default: 2002)
-                             to be used by client or listener
-      --password=string    provide a password to decrypt the document
-  -s, --server=server      specify the server address (default: 127.0.0.1)
-                             to be used by client or listener
-      --show               list the available output formats
-      --stdout             write output to stdout
-  -t, --template=file      import the styles from template (.ott)
-  -T, --timeout=secs       timeout after secs if connection to listener fails
-  -v, --verbose            be more and more verbose (-vvv for debugging)
-'''
-
-class Convertor:
-    def __init__(self):
-        global exitcode, ooproc, office, product
-        unocontext = None
-
-        ### Do the LibreOffice component dance
-        self.context = uno.getComponentContext()
-        self.svcmgr = self.context.ServiceManager
-        resolver = self.svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", self.context)
-
-        ### Test for an existing connection
-        info(3, 'Connection type: %s' % op.connection)
-        try:
-            unocontext = resolver.resolve("uno:%s" % op.connection)
-        except NoConnectException, e:
-#            info(3, "Existing listener not found.\n%s" % e)
-            info(3, "Existing listener not found.")
-
-            if op.nolaunch:
-                die(113, "Existing listener not found. Unable start listener by parameters. Aborting.")
-
-            ### Start our own OpenOffice instance
-            info(3, "Launching our own listener using %s." % office.binary)
-            try:
-                product = self.svcmgr.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", UnoProps(nodepath="/org.openoffice.Setup/Product"))
-                if product.ooName != "LibreOffice" or LooseVersion(product.ooSetupVersion) <= LooseVersion('3.3'):
-                    ooproc = subprocess.Popen([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nofirststartwizard", "-nologo", "-norestore", "-accept=%s" % op.connection], env=os.environ)
-                else:
-                    ooproc = subprocess.Popen([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nofirststartwizard", "--nologo", "--norestore", "--accept=%s" % op.connection], env=os.environ)
-                info(2, '%s listener successfully started. (pid=%s)' % (product.ooName, ooproc.pid))
-
-                ### Try connection to it for op.timeout seconds (flakky OpenOffice)
-                timeout = 0
-                while timeout <= op.timeout:
-                    ### Is it already/still running ?
-                    retcode = ooproc.poll()
-                    if retcode != None:
-                        info(3, "Process %s (pid=%s) exited with %s." % (office.binary, ooproc.pid, retcode))
-                        break
-                    try:
-                        unocontext = resolver.resolve("uno:%s" % op.connection)
-                        break
-                    except NoConnectException:
-                        time.sleep(0.5)
-                        timeout += 0.5
-                    except:
-                        raise
-                else:
-                    error("Failed to connect to %s (pid=%s) in %d seconds.\n%s" % (office.binary, ooproc.pid, op.timeout, e))
-            except Exception, e:
-                raise
-                error("Launch of %s failed.\n%s" % (office.binary, e))
-
-        if not unocontext:
-            die(251, "Unable to connect or start own listener. Aborting.")
-
-        ### And some more LibreOffice magic
-        unosvcmgr = unocontext.ServiceManager
-        self.desktop = unosvcmgr.createInstanceWithContext("com.sun.star.frame.Desktop", unocontext)
-        self.cwd = unohelper.systemPathToFileUrl( os.getcwd() )
-
-        ### List all filters
-#        self.filters = unosvcmgr.createInstanceWithContext( "com.sun.star.document.FilterFactory", unocontext)
-#        for filter in self.filters.getElementNames():
-#            print filter
-#            #print dir(filter), dir(filter.format)
-
-    def getformat(self, inputfn):
-        doctype = None
-
-        ### Get the output format from mapping
-        if op.doctype:
-            outputfmt = fmts.bydoctype(op.doctype, op.format)
-        else:
-            outputfmt = fmts.byname(op.format)
-
-            if not outputfmt:
-                outputfmt = fmts.byextension(os.extsep + op.format)
-
-        ### If no doctype given, check list of acceptable formats for input file ext doctype
-        ### FIXME: This should go into the for-loop to match each individual input filename
-        if outputfmt:
-            inputext = os.path.splitext(inputfn)[1]
-            inputfmt = fmts.byextension(inputext)
-            if inputfmt:
-                for fmt in outputfmt:
-                    if inputfmt[0].doctype == fmt.doctype:
-                        doctype = inputfmt[0].doctype
-                        outputfmt = fmt
-                        break
-                else:
-                    outputfmt = outputfmt[0]
-    #       print >>sys.stderr, 'unoconv: format `%s\' is part of multiple doctypes %s, selecting `%s\'.' % (format, [fmt.doctype for fmt in outputfmt], outputfmt[0].doctype)
-            else:
-                outputfmt = outputfmt[0]
-
-        ### No format found, throw error
-        if not outputfmt:
-            if doctype:
-                print >>sys.stderr, 'unoconv: format [%s/%s] is not known to unoconv.' % (op.doctype, op.format)
-            else:
-                print >>sys.stderr, 'unoconv: format [%s] is not known to unoconv.' % op.format
-            die(1)
-
-        return outputfmt
-
-    def convert(self, inputfn):
-        global exitcode
-
-        document = None
-        outputfmt = self.getformat(inputfn)
-
-        if op.verbose > 0:
-            print >>sys.stderr, 'Input file:', inputfn
-
-        if not os.path.exists(inputfn):
-            print >>sys.stderr, 'unoconv: file `%s\' does not exist.' % inputfn
-            exitcode = 1
-
-        try:
-            ### Import phase
-            phase = "import"
-
-            ### Load inputfile
-            inputprops = UnoProps(Hidden=True, ReadOnly=True, UpdateDocMode=QUIET_UPDATE)
-
-#            if op.password:
-#                info = UnoProps(algorithm-name="PBKDF2", salt="salt", iteration-count=1024, hash="hash")
-#                inputprops += UnoProps(ModifyPasswordInfo=info)
-
-            ### Cannot use UnoProps for FilterData property
-            if op.importfilteroptions:
-#                print "Import filter options: %s" % op.importfilteroptions
-                inputprops += UnoProps(FilterOptions=op.importfilteroptions)
-
-            ### Cannot use UnoProps for FilterData property
-            if op.importfilter:
-                inputprops += ( PropertyValue( "FilterData", 0, uno.Any("[]com.sun.star.beans.PropertyValue", tuple( op.importfilter ), ), 0 ), )
-
-            inputurl = unohelper.absolutize(self.cwd, unohelper.systemPathToFileUrl(inputfn))
-            document = self.desktop.loadComponentFromURL( inputurl , "_blank", 0, inputprops )
-
-            if not document:
-                raise UnoException("The document '%s' could not be opened." % inputurl, None)
-
-            ### Import style template
-            phase = "import-style"
-            if op.template:
-                if os.path.exists(op.template):
-                    info(1, "Template file: %s" % op.template)
-                    templateprops = UnoProps(OverwriteStyles=True)
-                    templateurl = unohelper.absolutize(self.cwd, unohelper.systemPathToFileUrl(op.template))
-                    document.StyleFamilies.loadStylesFromURL(templateurl, templateprops)
-                else:
-                    print >>sys.stderr, 'unoconv: template file `%s\' does not exist.' % op.template
-                    exitcode = 1
-
-            ### Update document links
-            phase = "update-links"
-            try:
-                document.updateLinks()
-            except AttributeError:
-                # the document doesn't implement the XLinkUpdate interface
-                pass
-
-            ### Update document indexes
-            phase = "update-indexes"
-            try:
-                document.refresh()
-                indexes = document.getDocumentIndexes()
-            except AttributeError:
-                # the document doesn't implement the XRefreshable and/or
-                # XDocumentIndexesSupplier interfaces
-                pass
-            else:
-                for i in range(0, indexes.getCount()):
-                    indexes.getByIndex(i).update()
-
-            info(1, "Selected output format: %s" % outputfmt)
-            info(2, "Selected office filter: %s" % outputfmt.filter)
-            info(2, "Used doctype: %s" % outputfmt.doctype)
-
-            ### Export phase
-            phase = "export"
-
-            outputprops = UnoProps(FilterName=outputfmt.filter, OutputStream=OutputStream(), Overwrite=True)
-
-            ### Set default filter options
-            if op.exportfilteroptions:
-#                print "Export filter options: %s" % op.exportfilteroptions
-                outputprops += UnoProps(FilterOptions=op.exportfilteroptions)
-            else:
-                if outputfmt.filter == 'Text (encoded)':
-                    outputprops += UnoProps(FilterOptions="76,LF")
-
-                elif outputfmt.filter == 'Text':
-                    outputprops += UnoProps(FilterOptions="76")
-
-                elif outputfmt.filter == 'Text - txt - csv (StarCalc)':
-                    outputprops += UnoProps(FilterOptions="44,34,76")
-
-
-            ### Cannot use UnoProps for FilterData property
-            if op.exportfilter:
-                outputprops += ( PropertyValue( "FilterData", 0, uno.Any("[]com.sun.star.beans.PropertyValue", tuple( op.exportfilter ), ), 0 ), )
-
-            if not op.stdout:
-                (outputfn, ext) = os.path.splitext(inputfn)
-                if not op.output:
-                    outputfn = outputfn + os.extsep + outputfmt.extension
-                elif os.path.isdir(op.output):
-                    outputfn = realpath(op.output, os.path.basename(outputfn) + os.extsep + outputfmt.extension)
-                elif len(op.filenames) > 1:
-                    outputfn = op.output + os.extsep + outputfmt.extension
-                else:
-                    outputfn = op.output
-
-                outputurl = unohelper.absolutize( self.cwd, unohelper.systemPathToFileUrl(outputfn) )
-                info(1, "Output file: %s" % outputfn)
-            else:
-                outputurl = "private:stream"
-
-            try:
-                document.storeToURL(outputurl, tuple(outputprops) )
-            except IOException, e:
-                raise UnoException("Unable to store document to %s (ErrCode %d)\n\nProperties: %s" % (outputurl, e.ErrCode, outputprops), None)
-
-            phase = "dispose"
-            document.dispose()
-            document.close(True)
-
-        except SystemError, e:
-            error("unoconv: SystemError during %s phase:\n%s" % (phase, e))
-            exitcode = 1
-
-        except RuntimeException, e:
-            error("unoconv: RuntimeException during %s phase:\nOffice probably died. %s" % (phase, e))
-            exitcode = 6
-
-        except DisposedException, e:
-            error("unoconv: DisposedException during %s phase:\nOffice probably died. %s" % (phase, e))
-            exitcode = 7
-
-        except IllegalArgumentException, e:
-            error("UNO IllegalArgument during %s phase:\nSource file cannot be read. %s" % (phase, e))
-            exitcode = 8
-
-        except IOException, e:
-#            for attr in dir(e): print '%s: %s', (attr, getattr(e, attr))
-            error("unoconv: IOException during %s phase:\n%s" % (phase, e.Message))
-            exitcode = 3
-
-        except CannotConvertException, e:
-#            for attr in dir(e): print '%s: %s', (attr, getattr(e, attr))
-            error("unoconv: CannotConvertException during %s phase:\n%s" % (phase, e.Message))
-            exitcode = 4
-
-        except UnoException, e:
-            if hasattr(e, 'ErrCode'):
-                error("unoconv: UnoException during %s phase in %s (ErrCode %d)" % (phase, repr(e.__class__), e.ErrCode))
-                exitcode = e.ErrCode
-                pass
-            if hasattr(e, 'Message'):
-                error("unoconv: UnoException during %s phase:\n%s" % (phase, e.Message))
-                exitcode = 5
-            else:
-                error("unoconv: UnoException during %s phase in %s" % (phase, repr(e.__class__)))
-                exitcode = 2
-                pass
-
-class Listener:
-    def __init__(self):
-        global product
-
-        info(1, "Start listener on %s:%s" % (op.server, op.port))
-        self.context = uno.getComponentContext()
-        self.svcmgr = self.context.ServiceManager
-        try:
-            resolver = self.svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", self.context)
-            product = self.svcmgr.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", UnoProps(nodepath="/org.openoffice.Setup/Product"))
-            try:
-                unocontext = resolver.resolve("uno:%s" % op.connection)
-            except NoConnectException, e:
-                pass
-            else:
-                info(1, "Existing %s listener found, nothing to do." % product.ooName)
-                return
-            if product.ooName != "LibreOffice" or LooseVersion(product.ooSetupVersion) <= LooseVersion('3.3'):
-                subprocess.call([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nologo", "-nofirststartwizard", "-norestore", "-accept=%s" % op.connection], env=os.environ)
-            else:
-                subprocess.call([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nologo", "--nofirststartwizard", "--norestore", "--accept=%s" % op.connection], env=os.environ)
-        except Exception, e:
-            error("Launch of %s failed.\n%s" % (office.binary, e))
-        else:
-            info(1, "Existing %s listener found, nothing to do." % product.ooName)
-
-def error(msg):
-    "Output error message"
-    print >>sys.stderr, msg
-
-def info(level, msg):
-    "Output info message"
-    if 'op' not in globals():
-        pass
-    elif op.verbose >= 3 and level >= 3:
-        print >>sys.stderr, "DEBUG:", msg
-    elif not op.stdout and level <= op.verbose:
-        print >>sys.stdout, msg
-    elif level <= op.verbose:
-        print >>sys.stderr, msg
-
-def die(ret, msg=None):
-    "Print optional error and exit with errorcode"
-    global convertor, ooproc, office
-
-    if msg:
-        error('Error: %s' % msg)
-
-    ### Did we start our own listener instance ?
-    if not op.listener and ooproc and convertor:
-
-        ### If there is a GUI now attached to the instance, disable listener
-        if convertor.desktop.getCurrentFrame():
-            info(2, 'Trying to stop %s GUI listener.' % product.ooName)
-            try:
-                if product.ooName != "LibreOffice" or product.ooSetupVersion <= 3.3:
-                    subprocess.Popen([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nofirststartwizard", "-nologo", "-norestore", "-unaccept=%s" % op.connection], env=os.environ)
-                else:
-                    subprocess.Popen([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nofirststartwizard", "--nologo", "--norestore", "--unaccept=%s" % op.connection], env=os.environ)
-                ooproc.wait()
-                info(2, '%s listener successfully disabled.' % product.ooName)
-            except Exception, e:
-                error("Terminate using %s failed.\n%s" % (office.binary, e))
-
-        ### If there is no GUI attached to the instance, terminate instance
-        else:
-            info(3, 'Terminating %s instance.' % product.ooName)
-            try:
-                convertor.desktop.terminate()
-            except DisposedException:
-                info(2, '%s instance unsuccessfully closed, sending TERM signal.' % product.ooName)
-                try:
-                    ooproc.terminate()
-                except AttributeError:
-                    os.kill(ooproc.pid, 15)
-            info(3, 'Waiting for %s instance to exit.' % product.ooName)
-            ooproc.wait()
-
-        ### LibreOffice processes may get stuck and we have to kill them
-        ### Is it still running ?
-        if ooproc.poll() == None:
-            info(1, '%s instance still running, please investigate...' % product.ooName)
-            ooproc.wait()
-            info(2, '%s instance unsuccessfully terminated, sending KILL signal.' % product.ooName)
-            try:
-                ooproc.kill()
-            except AttributeError:
-                os.kill(ooproc.pid, 9)
-            info(3, 'Waiting for %s with pid %s to disappear.' % (ooproc.pid, product.ooName))
-            ooproc.wait()
-
-    # allow Python GC to garbage collect pyuno object *before* exit call
-    # which avoids random segmentation faults --vpa
-    convertor = None
-
-    sys.exit(ret)
-
-def main():
-    global convertor, exitcode
-    convertor = None
-
-    try:
-        if op.listener:
-            listener = Listener()
-
-        if op.filenames:
-            convertor = Convertor()
-            for inputfn in op.filenames:
-                convertor.convert(inputfn)
-
-    except NoConnectException, e:
-        error("unoconv: could not find an existing connection to LibreOffice at %s:%s." % (op.server, op.port))
-        if op.connection:
-            info(0, "Please start an LibreOffice instance on server '%s' by doing:\n\n    unoconv --listener --server %s --port %s\n\nor alternatively:\n\n    soffice -nologo -nodefault -accept=\"%s\"" % (op.server, op.server, op.port, op.connection))
-        else:
-            info(0, "Please start an LibreOffice instance on server '%s' by doing:\n\n    unoconv --listener --server %s --port %s\n\nor alternatively:\n\n    soffice -nologo -nodefault -accept=\"socket,host=%s,port=%s;urp;\"" % (op.server, op.server, op.port, op.server, op.port))
-            info(0, "Please start an soffice instance on server '%s' by doing:\n\n    soffice -nologo -nodefault -accept=\"socket,host=127.0.0.1,port=%s;urp;\"" % (op.server, op.port))
-        exitcode = 1
-#    except UnboundLocalError:
-#        die(252, "Failed to connect to remote listener.")
-    except OSError:
-        error("Warning: failed to launch Office suite. Aborting.")
-
-### Main entrance
 if __name__ == '__main__':
-    exitcode = 0
-
-    info(3, 'sysname=%s, platform=%s, python=%s, python-version=%s' % (os.name, sys.platform, sys.executable, sys.version))
-
-    for of in find_offices():
-        if of.python != sys.executable and not sys.executable.startswith(of.basepath):
-            python_switch(of)
-        office_environ(of)
-#        debug_office()
-        try:
-            import uno, unohelper
-            office = of
-            break
-        except:
-#            debug_office()
-            print >>sys.stderr, "unoconv: Cannot find a suitable pyuno library and python binary combination in %s" % of
-            print >>sys.stderr, "ERROR:", sys.exc_info()[1]
-            print >>sys.stderr
+    if sys.version_info < (3,0):
+        from unoconv2 import run
     else:
-#        debug_office()
-        print >>sys.stderr, "unoconv: Cannot find a suitable office installation on your system."
-        print >>sys.stderr, "ERROR: Please locate your office installation and send your feedback to:"
-        print >>sys.stderr, "       http://github.com/dagwieers/unoconv/issues"
-        sys.exit(1)
-
-    ### Now that we have found a working pyuno library, let's import some classes
-    from com.sun.star.beans import PropertyValue
-    from com.sun.star.connection import NoConnectException
-    from com.sun.star.document.UpdateDocMode import QUIET_UPDATE
-    from com.sun.star.lang import DisposedException, IllegalArgumentException
-    from com.sun.star.io import IOException, XOutputStream
-    from com.sun.star.script import CannotConvertException
-    from com.sun.star.uno import Exception as UnoException
-    from com.sun.star.uno import RuntimeException
-
-    ### And now that we have those classes, build on them
-    class OutputStream( unohelper.Base, XOutputStream ):
-        def __init__( self ):
-            self.closed = 0
-
-        def closeOutput(self):
-            self.closed = 1
-
-        def writeBytes( self, seq ):
-            sys.stdout.write( seq.value )
-
-        def flush( self ):
-            pass
-
-    def UnoProps(**args):
-        props = []
-        for key in args:
-            prop = PropertyValue()
-            prop.Name = key
-            prop.Value = args[key]
-            props.append(prop)
-        return tuple(props)
-
-    op = Options(sys.argv[1:])
-
-    info(2, "Using office base path: %s" % office.basepath)
-    info(2, "Using office binary path: %s" % office.unopath)
+        from unoconv3 import run
 
-    try:
-        main()
-    except KeyboardInterrupt, e:
-        die(6, 'Exiting on user request')
-    die(exitcode)
+    run()
diff --git a/unoconv2.py b/unoconv2.py
new file mode 100755
index 0000000..1aecbb6
--- /dev/null
+++ b/unoconv2.py
@@ -0,0 +1,1195 @@
+#!/usr/bin/python
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; version 2 only
+###
+### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+### Copyright 2007-2010 Dag Wieers <dag@wieers.com>
+
+from distutils.version import LooseVersion
+import getopt
+import glob
+import os
+import subprocess
+import sys
+import time
+
+__version__ = "$Revision$"
+# $Source$
+
+VERSION = '0.6'
+
+doctypes = ('document', 'graphics', 'presentation', 'spreadsheet')
+
+global convertor, office, ooproc, product
+ooproc = None
+exitcode = 0
+
+class Office:
+    def __init__(self, basepath, urepath, unopath, pyuno, binary, python, pythonhome):
+        self.basepath = basepath
+        self.urepath = urepath
+        self.unopath = unopath
+        self.pyuno = pyuno
+        self.binary = binary
+        self.python = python
+        self.pythonhome = pythonhome
+
+    def __str__(self):
+        return self.basepath
+
+    def __repr__(self):
+        return self.basepath
+
+### Implement a path normalizer in order to make unoconv work on MacOS X
+### (on which 'program' is a symlink to 'MacOSX' which seems to break unoconv)
+def realpath(*args):
+    ''' Implement a combination of os.path.join(), os.path.abspath() and
+        os.path.realpath() in order to normalize path constructions '''
+    ret = ''
+    for arg in args:
+        ret = os.path.join(ret, arg)
+    return os.path.realpath(os.path.abspath(ret))
+
+### The first thing we ought to do is find a suitable Office installation
+### with a compatible pyuno library that we can import.
+###
+### See: http://user.services.openoffice.org/en/forum/viewtopic.php?f=45&t=36370&p=166783
+
+def find_offices():
+    ret = []
+    extrapaths = []
+
+    ### Try using UNO_PATH first (in many incarnations, we'll see what sticks)
+    if 'UNO_PATH' in os.environ:
+        extrapaths += [ os.environ['UNO_PATH'],
+                        os.path.dirname(os.environ['UNO_PATH']),
+                        os.path.dirname(os.path.dirname(os.environ['UNO_PATH'])) ]
+
+    else:
+
+        if os.name in ( 'nt', 'os2' ):
+            if 'PROGRAMFILES' in os.environ.keys():
+                extrapaths += glob.glob(os.environ['PROGRAMFILES']+'\\LibreOffice*') + \
+                              glob.glob(os.environ['PROGRAMFILES']+'\\OpenOffice.org*')
+
+            if 'PROGRAMFILES(X86)' in os.environ.keys():
+                extrapaths += glob.glob(os.environ['PROGRAMFILES(X86)']+'\\LibreOffice*') + \
+                              glob.glob(os.environ['PROGRAMFILES(X86)']+'\\OpenOffice.org*')
+
+        elif os.name in ( 'mac', ) or sys.platform in ( 'darwin', ):
+            extrapaths += [ '/Applications/LibreOffice.app/Contents',
+                            '/Applications/NeoOffice.app/Contents',
+                            '/Applications/OpenOffice.org.app/Contents' ]
+
+        else:
+            extrapaths += glob.glob('/usr/lib*/libreoffice*') + \
+                          glob.glob('/usr/lib*/openoffice*') + \
+                          glob.glob('/usr/lib*/ooo*') + \
+                          glob.glob('/opt/libreoffice*') + \
+                          glob.glob('/opt/openoffice*') + \
+                          glob.glob('/opt/ooo*') + \
+                          glob.glob('/usr/local/libreoffice*') + \
+                          glob.glob('/usr/local/openoffice*') + \
+                          glob.glob('/usr/local/ooo*') + \
+                          glob.glob('/usr/local/lib/libreoffice*')
+
+    ### Find a working set for python UNO bindings
+    for basepath in extrapaths:
+        if os.name in ( 'nt', 'os2' ):
+            officelibraries = ( 'pyuno.pyd', )
+            officebinaries = ( 'soffice.exe' ,)
+            pythonbinaries = ( 'python.exe', )
+            pythonhomes = ()
+        elif os.name in ( 'mac', ) or sys.platform in ( 'darwin', ):
+            officelibraries = ( 'pyuno.so', 'libpyuno.dylib' )
+            officebinaries = ( 'soffice.bin', )
+            pythonbinaries = ( 'python.bin', 'python' )
+            pythonhomes = ( 'OOoPython.framework/Versions/*/lib/python*', )
+        else:
+            officelibraries = ( 'pyuno.so', )
+            officebinaries = ( 'soffice.bin', )
+            pythonbinaries = ( 'python.bin', 'python', )
+            pythonhomes = ( 'python-core-*', )
+
+        ### Older LibreOffice/OpenOffice and Windows use basis-link/ or basis/
+        libpath = 'error'
+        for basis in ( 'basis-link', 'basis', '' ):
+            for lib in officelibraries:
+                if os.path.isfile(realpath(basepath, basis, 'program', lib)):
+                    libpath = realpath(basepath, basis, 'program')
+                    officelibrary = realpath(libpath, lib)
+                    info(3, "Found %s in %s" % (lib, libpath))
+                    # Break the inner loop...
+                    break
+            # Continue if the inner loop wasn't broken.
+            else:
+                continue
+            # Inner loop was broken, break the outer.
+            break
+        else:
+            continue
+
+        ### MacOSX have soffice binaries installed in MacOS subdirectory, not program
+        unopath = 'error'
+        for basis in ( 'basis-link', 'basis', '' ):
+            for bin in officebinaries:
+                if os.path.isfile(realpath(basepath, basis, 'program', bin)):
+                    unopath = realpath(basepath, basis, 'program')
+                    officebinary = realpath(unopath, bin)
+                    info(3, "Found %s in %s" % (bin, unopath))
+                    # Break the inner loop...
+                    break
+            # Continue if the inner loop wasn't broken.
+            else:
+                continue
+            # Inner loop was broken, break the outer.
+            break
+        else:
+            continue
+
+        ### Windows does not provide or need a URE/lib directory ?
+        urepath = ''
+        for basis in ( 'basis-link', 'basis', '' ):
+            for ure in ( 'ure-link', 'ure', 'URE', '' ):
+                if os.path.isfile(realpath(basepath, basis, ure, 'lib', 'unorc')):
+                    urepath = realpath(basepath, basis, ure)
+                    info(3, "Found %s in %s" % ('unorc', realpath(urepath, 'lib')))
+                    # Break the inner loop...
+                    break
+            # Continue if the inner loop wasn't broken.
+            else:
+                continue
+            # Inner loop was broken, break the outer.
+            break
+
+        pythonhome = None
+        for home in pythonhomes:
+            if glob.glob(realpath(libpath, home)):
+                pythonhome = glob.glob(realpath(libpath, home))[0]
+                info(3, "Found %s in %s" % (home, pythonhome))
+                break
+
+#        if not os.path.isfile(realpath(basepath, program, officebinary)):
+#            continue
+#        info(3, "Found %s in %s" % (officebinary, realpath(basepath, program)))
+
+#        if not glob.glob(realpath(basepath, basis, program, 'python-core-*')):
+#            continue
+
+        for pythonbinary in pythonbinaries:
+            if os.path.isfile(realpath(unopath, pythonbinary)):
+                info(3, "Found %s in %s" % (pythonbinary, unopath))
+                ret.append(Office(basepath, urepath, unopath, officelibrary, officebinary,
+                                  realpath(unopath, pythonbinary), pythonhome))
+        else:
+            info(3, "Considering %s" % basepath)
+            ret.append(Office(basepath, urepath, unopath, officelibrary, officebinary,
+                              sys.executable, None))
+    return ret
+
+def office_environ(office):
+    ### Set PATH so that crash_report is found
+    os.environ['PATH'] = realpath(office.basepath, 'program') + os.pathsep + os.environ['PATH']
+
+    ### Set UNO_PATH so that "officehelper.bootstrap()" can find soffice executable:
+    os.environ['UNO_PATH'] = office.unopath
+
+    ### Set URE_BOOTSTRAP so that "global_uno.getComponentContext()" bootstraps a complete
+    ### UNO environment
+    if os.name in ( 'nt', 'os2' ):
+        os.environ['URE_BOOTSTRAP'] = 'vnd.sun.star.pathname:' + realpath(office.basepath, 'program', 'fundamental.ini')
+    else:
+        os.environ['URE_BOOTSTRAP'] = 'vnd.sun.star.pathname:' + realpath(office.basepath, 'program', 'fundamentalrc')
+
+        ### Set LD_LIBRARY_PATH so that "import pyuno" finds libpyuno.so:
+        if 'LD_LIBRARY_PATH' in os.environ:
+            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
+                                            realpath(office.urepath, 'lib') + os.pathsep + \
+                                            os.environ['LD_LIBRARY_PATH']
+        else:
+            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
+                                            realpath(office.urepath, 'lib')
+
+    if office.pythonhome:
+        for libpath in ( realpath(office.pythonhome, 'lib'),
+                         realpath(office.pythonhome, 'lib', 'lib-dynload'),
+                         realpath(office.pythonhome, 'lib', 'lib-tk'),
+                         realpath(office.pythonhome, 'lib', 'site-packages'),
+                         office.unopath):
+            sys.path.insert(0, libpath)
+    else:
+        ### Still needed for system python using LibreOffice UNO bindings
+        ### Although we prefer to use a system UNO binding in this case
+        sys.path.append(office.unopath)
+
+def debug_office():
+    if 'URE_BOOTSTRAP' in os.environ:
+        print >>sys.stderr, 'URE_BOOTSTRAP=%s' % os.environ['URE_BOOTSTRAP']
+    if 'UNO_PATH' in os.environ:
+        print >>sys.stderr, 'UNO_PATH=%s' % os.environ['UNO_PATH']
+    if 'UNO_TYPES' in os.environ:
+        print >>sys.stderr, 'UNO_TYPES=%s' % os.environ['UNO_TYPES']
+    print 'PATH=%s' % os.environ['PATH']
+    if 'PYTHONHOME' in os.environ:
+        print >>sys.stderr, 'PYTHONHOME=%s' % os.environ['PYTHONHOME']
+    if 'PYTHONPATH' in os.environ:
+        print >>sys.stderr, 'PYTHONPATH=%s' % os.environ['PYTHONPATH']
+    if 'LD_LIBRARY_PATH' in os.environ:
+        print >>sys.stderr, 'LD_LIBRARY_PATH=%s' % os.environ['LD_LIBRARY_PATH']
+
+def python_switch(office):
+    if office.pythonhome:
+        os.environ['PYTHONHOME'] = office.pythonhome
+        os.environ['PYTHONPATH'] = realpath(office.pythonhome, 'lib') + os.pathsep + \
+                                   realpath(office.pythonhome, 'lib', 'lib-dynload') + os.pathsep + \
+                                   realpath(office.pythonhome, 'lib', 'lib-tk') + os.pathsep + \
+                                   realpath(office.pythonhome, 'lib', 'site-packages') + os.pathsep + \
+                                   office.unopath
+
+    os.environ['UNO_PATH'] = office.unopath
+
+    info(3, "-> Switching from %s to %s" % (sys.executable, office.python))
+    if os.name in ('nt', 'os2'):
+        ### os.execv is broken on Windows and can't properly parse command line
+        ### arguments and executable name if they contain whitespaces. subprocess
+        ### fixes that behavior.
+        ret = subprocess.call([office.python] + sys.argv[0:])
+        sys.exit(ret)
+    else:
+
+        ### Set LD_LIBRARY_PATH so that "import pyuno" finds libpyuno.so:
+        if 'LD_LIBRARY_PATH' in os.environ:
+            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
+                                            realpath(office.urepath, 'lib') + os.pathsep + \
+                                            os.environ['LD_LIBRARY_PATH']
+        else:
+            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
+                                            realpath(office.urepath, 'lib')
+
+        try:
+            os.execvpe(office.python, [office.python, ] + sys.argv[0:], os.environ)
+            print(office.python, [office.python, ] + sys.argv[0:], osenviron)
+        except OSError:
+            ### Mac OS X versions prior to 10.6 do not support execv in
+            ### a process that contains multiple threads.  Instead of
+            ### re-executing in the current process, start a new one
+            ### and cause the current process to exit.  This isn't
+            ### ideal since the new process is detached from the parent
+            ### terminal and thus cannot easily be killed with ctrl-C,
+            ### but it's better than not being able to autoreload at
+            ### all.
+            ### Unfortunately the errno returned in this case does not
+            ### appear to be consistent, so we can't easily check for
+            ### this error specifically.
+            ret = os.spawnvpe(os.P_WAIT, office.python, [office.python, ] + sys.argv[0:], os.environ)
+            sys.exit(ret)
+
+class Fmt:
+    def __init__(self, doctype, name, extension, summary, filter):
+        self.doctype = doctype
+        self.name = name
+        self.extension = extension
+        self.summary = summary
+        self.filter = filter
+
+    def __str__(self):
+        return "%s [.%s]" % (self.summary, self.extension)
+
+    def __repr__(self):
+        return "%s/%s" % (self.name, self.doctype)
+
+class FmtList:
+    def __init__(self):
+        self.list = []
+
+    def add(self, doctype, name, extension, summary, filter):
+        self.list.append(Fmt(doctype, name, extension, summary, filter))
+
+    def byname(self, name):
+        ret = []
+        for fmt in self.list:
+            if fmt.name == name:
+                ret.append(fmt)
+        return ret
+
+    def byextension(self, extension):
+        ret = []
+        for fmt in self.list:
+            if os.extsep + fmt.extension == extension:
+                ret.append(fmt)
+        return ret
+
+    def bydoctype(self, doctype, name):
+        ret = []
+        for fmt in self.list:
+            if fmt.name == name and fmt.doctype == doctype:
+                ret.append(fmt)
+        return ret
+
+    def display(self, doctype):
+        print >>sys.stderr, "The following list of %s formats are currently available:\n" % doctype
+        for fmt in self.list:
+            if fmt.doctype == doctype:
+                print >>sys.stderr, "  %-8s - %s" % (fmt.name, fmt)
+        print >>sys.stderr
+
+fmts = FmtList()
+
+### TextDocument
+fmts.add('document', 'bib', 'bib', 'BibTeX', 'BibTeX_Writer') ### 22
+fmts.add('document', 'doc', 'doc', 'Microsoft Word 97/2000/XP', 'MS Word 97') ### 29
+fmts.add('document', 'doc6', 'doc', 'Microsoft Word 6.0', 'MS WinWord 6.0') ### 24
+fmts.add('document', 'doc95', 'doc', 'Microsoft Word 95', 'MS Word 95') ### 28
+fmts.add('document', 'docbook', 'xml', 'DocBook', 'DocBook File') ### 39
+fmts.add('document', 'docx', 'docx', 'Microsoft Office Open XML', 'Office Open XML Text')
+fmts.add('document', 'docx7', 'docx', 'Microsoft Office Open XML', 'MS Word 2007 XML')
+fmts.add('document', 'fodt', 'fodt', 'OpenDocument Text (Flat XML)', 'OpenDocument Text Flat XML')
+fmts.add('document', 'html', 'html', 'HTML Document (OpenOffice.org Writer)', 'HTML (StarWriter)') ### 3
+fmts.add('document', 'latex', 'ltx', 'LaTeX 2e', 'LaTeX_Writer') ### 31
+fmts.add('document', 'mediawiki', 'txt', 'MediaWiki', 'MediaWiki')
+fmts.add('document', 'odt', 'odt', 'ODF Text Document', 'writer8') ### 10
+fmts.add('document', 'ooxml', 'xml', 'Microsoft Office Open XML', 'MS Word 2003 XML') ### 11
+fmts.add('document', 'ott', 'ott', 'Open Document Text', 'writer8_template') ### 21
+fmts.add('document', 'pdb', 'pdb', 'AportisDoc (Palm)', 'AportisDoc Palm DB')
+fmts.add('document', 'pdf', 'pdf', 'Portable Document Format', 'writer_pdf_Export') ### 18
+fmts.add('document', 'psw', 'psw', 'Pocket Word', 'PocketWord File')
+fmts.add('document', 'rtf', 'rtf', 'Rich Text Format', 'Rich Text Format') ### 16
+fmts.add('document', 'sdw', 'sdw', 'StarWriter 5.0', 'StarWriter 5.0') ### 23
+fmts.add('document', 'sdw4', 'sdw', 'StarWriter 4.0', 'StarWriter 4.0') ### 2
+fmts.add('document', 'sdw3', 'sdw', 'StarWriter 3.0', 'StarWriter 3.0') ### 20
+fmts.add('document', 'stw', 'stw', 'Open Office.org 1.0 Text Document Template', 'writer_StarOffice_XML_Writer_Template') ### 9
+fmts.add('document', 'sxw', 'sxw', 'Open Office.org 1.0 Text Document', 'StarOffice XML (Writer)') ### 1
+fmts.add('document', 'text', 'txt', 'Text Encoded', 'Text (encoded)') ### 26
+fmts.add('document', 'txt', 'txt', 'Text', 'Text') ### 34
+fmts.add('document', 'uot', 'uot', 'Unified Office Format text','UOF text') ### 27
+fmts.add('document', 'vor', 'vor', 'StarWriter 5.0 Template', 'StarWriter 5.0 Vorlage/Template') ### 6
+fmts.add('document', 'vor4', 'vor', 'StarWriter 4.0 Template', 'StarWriter 4.0 Vorlage/Template') ### 5
+fmts.add('document', 'vor3', 'vor', 'StarWriter 3.0 Template', 'StarWriter 3.0 Vorlage/Template') ### 4
+fmts.add('document', 'xhtml', 'html', 'XHTML Document', 'XHTML Writer File') ### 33
+
+### WebDocument
+fmts.add('web', 'etext', 'txt', 'Text Encoded (OpenOffice.org Writer/Web)', 'Text (encoded) (StarWriter/Web)') ### 14
+fmts.add('web', 'html10', 'html', 'OpenOffice.org 1.0 HTML Template', 'writer_web_StarOffice_XML_Writer_Web_Template') ### 11
+fmts.add('web', 'html', 'html', 'HTML Document', 'HTML') ### 2
+fmts.add('web', 'html', 'html', 'HTML Document Template', 'writerweb8_writer_template') ### 13
+fmts.add('web', 'mediawiki', 'txt', 'MediaWiki', 'MediaWiki_Web') ### 9
+fmts.add('web', 'pdf', 'pdf', 'PDF - Portable Document Format', 'writer_web_pdf_Export') ### 10
+fmts.add('web', 'sdw3', 'sdw', 'StarWriter 3.0 (OpenOffice.org Writer/Web)', 'StarWriter 3.0 (StarWriter/Web)') ### 3
+fmts.add('web', 'sdw4', 'sdw', 'StarWriter 4.0 (OpenOffice.org Writer/Web)', 'StarWriter 4.0 (StarWriter/Web)') ### 4
+fmts.add('web', 'sdw', 'sdw', 'StarWriter 5.0 (OpenOffice.org Writer/Web)', 'StarWriter 5.0 (StarWriter/Web)') ### 5
+fmts.add('web', 'txt', 'txt', 'OpenOffice.org Text (OpenOffice.org Writer/Web)', 'writerweb8_writer') ### 12
+fmts.add('web', 'text10', 'txt', 'OpenOffice.org 1.0 Text Document (OpenOffice.org Writer/Web)', 'writer_web_StarOffice_XML_Writer') ### 15
+fmts.add('web', 'text', 'txt', 'Text (OpenOffice.org Writer/Web)', 'Text (StarWriter/Web)') ### 8
+fmts.add('web', 'vor4', 'vor', 'StarWriter/Web 4.0 Template', 'StarWriter/Web 4.0 Vorlage/Template') ### 6
+fmts.add('web', 'vor', 'vor', 'StarWriter/Web 5.0 Template', 'StarWriter/Web 5.0 Vorlage/Template') ### 7
+
+### Spreadsheet
+fmts.add('spreadsheet', 'csv', 'csv', 'Text CSV', 'Text - txt - csv (StarCalc)') ### 16
+fmts.add('spreadsheet', 'dbf', 'dbf', 'dBASE', 'dBase') ### 22
+fmts.add('spreadsheet', 'dif', 'dif', 'Data Interchange Format', 'DIF') ### 5
+fmts.add('spreadsheet', 'fods', 'fods', 'OpenDocument Spreadsheet (Flat XML)', 'OpenDocument Spreadsheet Flat XML')
+fmts.add('spreadsheet', 'html', 'html', 'HTML Document (OpenOffice.org Calc)', 'HTML (StarCalc)') ### 7
+fmts.add('spreadsheet', 'ods', 'ods', 'ODF Spreadsheet', 'calc8') ### 15
+fmts.add('spreadsheet', 'ooxml', 'xml', 'Microsoft Excel 2003 XML', 'MS Excel 2003 XML') ### 23
+fmts.add('spreadsheet', 'ots', 'ots', 'ODF Spreadsheet Template', 'calc8_template') ### 14
+fmts.add('spreadsheet', 'pdf', 'pdf', 'Portable Document Format', 'calc_pdf_Export') ### 34
+fmts.add('spreadsheet', 'pxl', 'pxl', 'Pocket Excel', 'Pocket Excel')
+fmts.add('spreadsheet', 'sdc', 'sdc', 'StarCalc 5.0', 'StarCalc 5.0') ### 31
+fmts.add('spreadsheet', 'sdc4', 'sdc', 'StarCalc 4.0', 'StarCalc 4.0') ### 11
+fmts.add('spreadsheet', 'sdc3', 'sdc', 'StarCalc 3.0', 'StarCalc 3.0') ### 29
+fmts.add('spreadsheet', 'slk', 'slk', 'SYLK', 'SYLK') ### 35
+fmts.add('spreadsheet', 'stc', 'stc', 'OpenOffice.org 1.0 Spreadsheet Template', 'calc_StarOffice_XML_Calc_Template') ### 2
+fmts.add('spreadsheet', 'sxc', 'sxc', 'OpenOffice.org 1.0 Spreadsheet', 'StarOffice XML (Calc)') ### 3
+fmts.add('spreadsheet', 'uos', 'uos', 'Unified Office Format spreadsheet', 'UOF spreadsheet') ### 9
+fmts.add('spreadsheet', 'vor3', 'vor', 'StarCalc 3.0 Template', 'StarCalc 3.0 Vorlage/Template') ### 18
+fmts.add('spreadsheet', 'vor4', 'vor', 'StarCalc 4.0 Template', 'StarCalc 4.0 Vorlage/Template') ### 19
+fmts.add('spreadsheet', 'vor', 'vor', 'StarCalc 5.0 Template', 'StarCalc 5.0 Vorlage/Template') ### 20
+fmts.add('spreadsheet', 'xhtml', 'xhtml', 'XHTML', 'XHTML Calc File') ### 26
+fmts.add('spreadsheet', 'xls', 'xls', 'Microsoft Excel 97/2000/XP', 'MS Excel 97') ### 12
+fmts.add('spreadsheet', 'xls5', 'xls', 'Microsoft Excel 5.0', 'MS Excel 5.0/95') ### 8
+fmts.add('spreadsheet', 'xls95', 'xls', 'Microsoft Excel 95', 'MS Excel 95') ### 10
+fmts.add('spreadsheet', 'xlt', 'xlt', 'Microsoft Excel 97/2000/XP Template', 'MS Excel 97 Vorlage/Template') ### 6
+fmts.add('spreadsheet', 'xlt5', 'xlt', 'Microsoft Excel 5.0 Template', 'MS Excel 5.0/95 Vorlage/Template') ### 28
+fmts.add('spreadsheet', 'xlt95', 'xlt', 'Microsoft Excel 95 Template', 'MS Excel 95 Vorlage/Template') ### 21
+
+### Graphics
+fmts.add('graphics', 'bmp', 'bmp', 'Windows Bitmap', 'draw_bmp_Export') ### 21
+fmts.add('graphics', 'emf', 'emf', 'Enhanced Metafile', 'draw_emf_Export') ### 15
+fmts.add('graphics', 'eps', 'eps', 'Encapsulated PostScript', 'draw_eps_Export') ### 48
+fmts.add('graphics', 'fodg', 'fodg', 'OpenDocument Drawing (Flat XML)', 'OpenDocument Drawing Flat XML')
+fmts.add('graphics', 'gif', 'gif', 'Graphics Interchange Format', 'draw_gif_Export') ### 30
+fmts.add('graphics', 'html', 'html', 'HTML Document (OpenOffice.org Draw)', 'draw_html_Export') ### 37
+fmts.add('graphics', 'jpg', 'jpg', 'Joint Photographic Experts Group', 'draw_jpg_Export') ### 3
+fmts.add('graphics', 'met', 'met', 'OS/2 Metafile', 'draw_met_Export') ### 43
+fmts.add('graphics', 'odd', 'odd', 'OpenDocument Drawing', 'draw8') ### 6
+fmts.add('graphics', 'otg', 'otg', 'OpenDocument Drawing Template', 'draw8_template') ### 20
+fmts.add('graphics', 'pbm', 'pbm', 'Portable Bitmap', 'draw_pbm_Export') ### 14
+fmts.add('graphics', 'pct', 'pct', 'Mac Pict', 'draw_pct_Export') ### 41
+fmts.add('graphics', 'pdf', 'pdf', 'Portable Document Format', 'draw_pdf_Export') ### 28
+fmts.add('graphics', 'pgm', 'pgm', 'Portable Graymap', 'draw_pgm_Export') ### 11
+fmts.add('graphics', 'png', 'png', 'Portable Network Graphic', 'draw_png_Export') ### 2
+fmts.add('graphics', 'ppm', 'ppm', 'Portable Pixelmap', 'draw_ppm_Export') ### 5
+fmts.add('graphics', 'ras', 'ras', 'Sun Raster Image', 'draw_ras_Export') ## 31
+fmts.add('graphics', 'std', 'std', 'OpenOffice.org 1.0 Drawing Template', 'draw_StarOffice_XML_Draw_Template') ### 53
+fmts.add('graphics', 'svg', 'svg', 'Scalable Vector Graphics', 'draw_svg_Export') ### 50
+fmts.add('graphics', 'svm', 'svm', 'StarView Metafile', 'draw_svm_Export') ### 55
+fmts.add('graphics', 'swf', 'swf', 'Macromedia Flash (SWF)', 'draw_flash_Export') ### 23
+fmts.add('graphics', 'sxd', 'sxd', 'OpenOffice.org 1.0 Drawing', 'StarOffice XML (Draw)') ### 26
+fmts.add('graphics', 'sxd3', 'sxd', 'StarDraw 3.0', 'StarDraw 3.0') ### 40
+fmts.add('graphics', 'sxd5', 'sxd', 'StarDraw 5.0', 'StarDraw 5.0') ### 44
+fmts.add('graphics', 'sxw', 'sxw', 'StarOffice XML (Draw)', 'StarOffice XML (Draw)')
+fmts.add('graphics', 'tiff', 'tiff', 'Tagged Image File Format', 'draw_tif_Export') ### 13
+fmts.add('graphics', 'vor', 'vor', 'StarDraw 5.0 Template', 'StarDraw 5.0 Vorlage') ### 36
+fmts.add('graphics', 'vor3', 'vor', 'StarDraw 3.0 Template', 'StarDraw 3.0 Vorlage') ### 35
+fmts.add('graphics', 'wmf', 'wmf', 'Windows Metafile', 'draw_wmf_Export') ### 8
+fmts.add('graphics', 'xhtml', 'xhtml', 'XHTML', 'XHTML Draw File') ### 45
+fmts.add('graphics', 'xpm', 'xpm', 'X PixMap', 'draw_xpm_Export') ### 19
+
+### Presentation
+fmts.add('presentation', 'bmp', 'bmp', 'Windows Bitmap', 'impress_bmp_Export') ### 15
+fmts.add('presentation', 'emf', 'emf', 'Enhanced Metafile', 'impress_emf_Export') ### 16
+fmts.add('presentation', 'eps', 'eps', 'Encapsulated PostScript', 'impress_eps_Export') ### 17
+fmts.add('presentation', 'fodp', 'fodp', 'OpenDocument Presentation (Flat XML)', 'OpenDocument Presentation Flat XML')
+fmts.add('presentation', 'gif', 'gif', 'Graphics Interchange Format', 'impress_gif_Export') ### 18
+fmts.add('presentation', 'html', 'html', 'HTML Document (OpenOffice.org Impress)', 'impress_html_Export') ### 43
+fmts.add('presentation', 'jpg', 'jpg', 'Joint Photographic Experts Group', 'impress_jpg_Export') ### 19
+fmts.add('presentation', 'met', 'met', 'OS/2 Metafile', 'impress_met_Export') ### 20
+fmts.add('presentation', 'odg', 'odg', 'ODF Drawing (Impress)', 'impress8_draw') ### 29
+fmts.add('presentation', 'odp', 'odp', 'ODF Presentation', 'impress8') ### 9
+fmts.add('presentation', 'otp', 'otp', 'ODF Presentation Template', 'impress8_template') ### 38
+fmts.add('presentation', 'pbm', 'pbm', 'Portable Bitmap', 'impress_pbm_Export') ### 21
+fmts.add('presentation', 'pct', 'pct', 'Mac Pict', 'impress_pct_Export') ### 22
+fmts.add('presentation', 'pdf', 'pdf', 'Portable Document Format', 'impress_pdf_Export') ### 23
+fmts.add('presentation', 'pgm', 'pgm', 'Portable Graymap', 'impress_pgm_Export') ### 24
+fmts.add('presentation', 'png', 'png', 'Portable Network Graphic', 'impress_png_Export') ### 25
+fmts.add('presentation', 'potm', 'potm', 'Microsoft PowerPoint 2007/2010 XML Template', 'Impress MS PowerPoint 2007 XML Template')
+fmts.add('presentation', 'pot', 'pot', 'Microsoft PowerPoint 97/2000/XP Template', 'MS PowerPoint 97 Vorlage') ### 3
+fmts.add('presentation', 'ppm', 'ppm', 'Portable Pixelmap', 'impress_ppm_Export') ### 26
+fmts.add('presentation', 'pptx', 'pptx', 'Microsoft PowerPoint 2007/2010 XML', 'Impress MS PowerPoint 2007 XML') ### 36
+fmts.add('presentation', 'pps', 'pps', 'Microsoft PowerPoint 97/2000/XP (Autoplay)', 'MS PowerPoint 97 Autoplay') ### 36
+fmts.add('presentation', 'ppt', 'ppt', 'Microsoft PowerPoint 97/2000/XP', 'MS PowerPoint 97') ### 36
+fmts.add('presentation', 'pwp', 'pwp', 'PlaceWare', 'placeware_Export') ### 30
+fmts.add('presentation', 'ras', 'ras', 'Sun Raster Image', 'impress_ras_Export') ### 27
+fmts.add('presentation', 'sda', 'sda', 'StarDraw 5.0 (OpenOffice.org Impress)', 'StarDraw 5.0 (StarImpress)') ### 8
+fmts.add('presentation', 'sdd', 'sdd', 'StarImpress 5.0', 'StarImpress 5.0') ### 6
+fmts.add('presentation', 'sdd3', 'sdd', 'StarDraw 3.0 (OpenOffice.org Impress)', 'StarDraw 3.0 (StarImpress)') ### 42
+fmts.add('presentation', 'sdd4', 'sdd', 'StarImpress 4.0', 'StarImpress 4.0') ### 37
+fmts.add('presentation', 'sxd', 'sxd', 'OpenOffice.org 1.0 Drawing (OpenOffice.org Impress)', 'impress_StarOffice_XML_Draw') ### 31
+fmts.add('presentation', 'sti', 'sti', 'OpenOffice.org 1.0 Presentation Template', 'impress_StarOffice_XML_Impress_Template') ### 5
+fmts.add('presentation', 'svg', 'svg', 'Scalable Vector Graphics', 'impress_svg_Export') ### 14
+fmts.add('presentation', 'svm', 'svm', 'StarView Metafile', 'impress_svm_Export') ### 13
+fmts.add('presentation', 'swf', 'swf', 'Macromedia Flash (SWF)', 'impress_flash_Export') ### 34
+fmts.add('presentation', 'sxi', 'sxi', 'OpenOffice.org 1.0 Presentation', 'StarOffice XML (Impress)') ### 41
+fmts.add('presentation', 'tiff', 'tiff', 'Tagged Image File Format', 'impress_tif_Export') ### 12
+fmts.add('presentation', 'uop', 'uop', 'Unified Office Format presentation', 'UOF presentation') ### 4
+fmts.add('presentation', 'vor', 'vor', 'StarImpress 5.0 Template', 'StarImpress 5.0 Vorlage') ### 40
+fmts.add('presentation', 'vor3', 'vor', 'StarDraw 3.0 Template (OpenOffice.org Impress)', 'StarDraw 3.0 Vorlage (StarImpress)') ###1
+fmts.add('presentation', 'vor4', 'vor', 'StarImpress 4.0 Template', 'StarImpress 4.0 Vorlage') ### 39
+fmts.add('presentation', 'vor5', 'vor', 'StarDraw 5.0 Template (OpenOffice.org Impress)', 'StarDraw 5.0 Vorlage (StarImpress)') ### 2
+fmts.add('presentation', 'wmf', 'wmf', 'Windows Metafile', 'impress_wmf_Export') ### 11
+fmts.add('presentation', 'xhtml', 'xml', 'XHTML', 'XHTML Impress File') ### 33
+fmts.add('presentation', 'xpm', 'xpm', 'X PixMap', 'impress_xpm_Export') ### 10
+
+class Options:
+    def __init__(self, args):
+        self.connection = None
+        self.debug = False
+        self.doctype = None
+        self.exportfilter = []
+        self.exportfilteroptions = ""
+        self.filenames = []
+        self.format = None
+        self.importfilter = []
+        self.importfilteroptions = ""
+        self.listener = False
+        self.nolaunch = False
+        self.output = None
+        self.password = None
+        self.pipe = None
+        self.port = '2002'
+        self.server = '127.0.0.1'
+        self.showlist = False
+        self.stdout = False
+        self.template = None
+        self.timeout = 6
+        self.verbose = 0
+
+        ### Get options from the commandline
+        try:
+            opts, args = getopt.getopt (args, 'c:Dd:e:f:hi:Llo:np:s:T:t:vV',
+                ['connection=', 'debug', 'doctype=', 'export=', 'format=',
+                 'help', 'import', 'listener', 'no-launch', 'output=',
+                 'outputpath', 'password=', 'pipe=', 'port=', 'server=',
+                 'timeout=', 'show', 'stdout', 'template', 'verbose',
+                 'version'] )
+        except getopt.error, exc:
+            print 'unoconv: %s, try unoconv -h for a list of all the options' % str(exc)
+            sys.exit(255)
+
+        for opt, arg in opts:
+            if opt in ['-h', '--help']:
+                self.usage()
+                print
+                self.help()
+                sys.exit(1)
+            elif opt in ['-c', '--connection']:
+                self.connection = arg
+            elif opt in ['--debug']:
+                self.debug = True
+            elif opt in ['-d', '--doctype']:
+                self.doctype = arg
+            elif opt in ['-e', '--export']:
+                l = arg.split('=')
+                if len(l) == 2:
+                    (name, value) = l
+                    if name in ('FilterOptions'):
+                        self.exportfilteroptions = value
+                    elif value in ('True', 'true'):
+                        self.exportfilter.append( UnoPropertyValue( name, 0, True, 0 ) )
+                    elif value in ('False', 'false'):
+                        self.exportfilter.append( UnoPropertyValue( name, 0, False, 0 ) )
+                    else:
+                        try:
+                            self.exportfilter.append( UnoPropertyValue( name, 0, int(value), 0 ) )
+                        except ValueError:
+                            self.exportfilter.append( UnoPropertyValue( name, 0, value, 0 ) )
+                else:
+                    print >>sys.stderr, 'Warning: Option %s cannot be parsed, ignoring.' % arg
+            elif opt in ['-f', '--format']:
+                self.format = arg
+            elif opt in ['-i', '--import']:
+                l = arg.split('=')
+                if len(l) == 2:
+                    (name, value) = l
+                    if name in ('FilterOptions'):
+                        self.importfilteroptions = value
+                    elif value in ('True', 'true'):
+                        self.importfilter.append( UnoPropertyValue( name, 0, True, 0 ) )
+                    elif value in ('False', 'false'):
+                        self.importfilter.append( UnoPropertyValue( name, 0, False, 0 ) )
+                    else:
+                        try:
+                            self.importfilter.append( UnoPropertyValue( name, 0, int(value), 0 ) )
+                        except ValueError:
+                            self.importfilter.append( UnoPropertyValue( name, 0, value, 0 ) )
+                else:
+                    print >>sys.stderr, 'Warning: Option %s cannot be parsed, ignoring.' % arg
+            elif opt in ['-l', '--listener']:
+                self.listener = True
+            elif opt in ['-n', '--no-launch']:
+                self.nolaunch = True
+            elif opt in ['-o', '--output']:
+                self.output = arg
+            elif opt in ['--outputpath']:
+                print >>sys.stderr, 'Warning: This option is deprecated by --output.'
+                self.output = arg
+            elif opt in ['--password']:
+                self.password = arg
+            elif opt in ['--pipe']:
+                self.pipe = arg
+            elif opt in ['-p', '--port']:
+                self.port = arg
+            elif opt in ['-s', '--server']:
+                self.server = arg
+            elif opt in ['--show']:
+                self.showlist = True
+            elif opt in ['--stdout']:
+                self.stdout = True
+            elif opt in ['-t', '--template']:
+                self.template = arg
+            elif opt in ['-T', '--timeout']:
+                self.timeout = int(arg)
+            elif opt in ['-v', '--verbose']:
+                self.verbose = self.verbose + 1
+            elif opt in ['-V', '--version']:
+                self.version()
+                sys.exit(255)
+
+        ### Enable verbosity
+        if self.verbose >= 2:
+            print >>sys.stderr, 'Verbosity set to level %d' % self.verbose
+
+        self.filenames = args
+
+        if not self.listener and not self.showlist and self.doctype != 'list' and not self.filenames:
+            print >>sys.stderr, 'unoconv: you have to provide a filename as argument'
+            print >>sys.stderr, 'Try `unoconv -h\' for more information.'
+            sys.exit(255)
+
+        ### Set connection string
+        if not self.connection:
+            if not self.pipe:
+                self.connection = "socket,host=%s,port=%s;urp;StarOffice.ComponentContext" % (self.server, self.port)
+#               self.connection = "socket,host=%s,port=%s;urp;" % (self.server, self.port)
+            else:
+                self.connection = "pipe,name=%s;urp;StarOffice.ComponentContext" % (self.pipe)
+
+        ### Make it easier for people to use a doctype (first letter is enough)
+        if self.doctype:
+            for doctype in doctypes:
+                if doctype.startswith(self.doctype):
+                    self.doctype = doctype
+
+        ### Check if the user request to see the list of formats
+        if self.showlist or self.format == 'list':
+            if self.doctype:
+                fmts.display(self.doctype)
+            else:
+                for t in doctypes:
+                    fmts.display(t)
+            sys.exit(0)
+
+        ### If no format was specified, probe it or provide it
+        if not self.format:
+            l = sys.argv[0].split('2')
+            if len(l) == 2:
+                self.format = l[1]
+            else:
+                self.format = 'pdf'
+
+    def version(self):
+        ### Get office product information
+        product = global_uno.getComponentContext().ServiceManager.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", GlobalUnoProps(nodepath="/org.openoffice.Setup/Product"))
+
+        print 'unoconv %s' % VERSION
+        print 'Written by Dag Wieers <dag@wieers.com>'
+        print 'Homepage at http://dag.wieers.com/home-made/unoconv/'
+        print
+        print 'platform %s/%s' % (os.name, sys.platform)
+        print 'python %s' % sys.version
+        print product.ooName, product.ooSetupVersion
+#        print
+#        print 'build revision $Rev$'
+
+    def usage(self):
+        print >>sys.stderr, 'usage: unoconv [options] file [file2 ..]'
+
+    def help(self):
+        print >>sys.stderr, '''Convert from and to any format supported by LibreOffice
+
+unoconv options:
+  -c, --connection=string  use a custom connection string
+  -d, --doctype=type       specify document type
+                             (document, graphics, presentation, spreadsheet)
+  -e, --export=name=value  set export filter options
+                             eg. -e PageRange=1-2
+  -f, --format=format      specify the output format
+  -i, --import=string      set import filter option string
+                             eg. -i utf8
+  -l, --listener           start a permanent listener to use by unoconv clients
+  -n, --no-launch          fail if no listener is found (default: launch one)
+  -o, --output=name        output basename, filename or directory
+      --pipe=name          alternative method of connection using a pipe
+  -p, --port=port          specify the port (default: 2002)
+                             to be used by client or listener
+      --password=string    provide a password to decrypt the document
+  -s, --server=server      specify the server address (default: 127.0.0.1)
+                             to be used by client or listener
+      --show               list the available output formats
+      --stdout             write output to stdout
+  -t, --template=file      import the styles from template (.ott)
+  -T, --timeout=secs       timeout after secs if connection to listener fails
+  -v, --verbose            be more and more verbose (-vvv for debugging)
+'''
+
+class Convertor:
+    def __init__(self):
+        global exitcode, ooproc, office, product
+        unocontext = None
+
+        ### Do the LibreOffice component dance
+        self.context = global_uno.getComponentContext()
+        self.svcmgr = self.context.ServiceManager
+        resolver = self.svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", self.context)
+
+        ### Test for an existing connection
+        info(3, 'Connection type: %s' % op.connection)
+        try:
+            unocontext = resolver.resolve("uno:%s" % op.connection)
+        except UnoNoConnectException, e:
+#            info(3, "Existing listener not found.\n%s" % e)
+            info(3, "Existing listener not found.")
+
+            if op.nolaunch:
+                die(113, "Existing listener not found. Unable start listener by parameters. Aborting.")
+
+            ### Start our own OpenOffice instance
+            info(3, "Launching our own listener using %s." % office.binary)
+            try:
+                product = self.svcmgr.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", GlobalUnoProps(nodepath="/org.openoffice.Setup/Product"))
+                if product.ooName != "LibreOffice" or LooseVersion(product.ooSetupVersion) <= LooseVersion('3.3'):
+                    ooproc = subprocess.Popen([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nofirststartwizard", "-nologo", "-norestore", "-accept=%s" % op.connection], env=os.environ)
+                else:
+                    ooproc = subprocess.Popen([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nofirststartwizard", "--nologo", "--norestore", "--accept=%s" % op.connection], env=os.environ)
+                info(2, '%s listener successfully started. (pid=%s)' % (product.ooName, ooproc.pid))
+
+                ### Try connection to it for op.timeout seconds (flakky OpenOffice)
+                timeout = 0
+                while timeout <= op.timeout:
+                    ### Is it already/still running ?
+                    retcode = ooproc.poll()
+                    if retcode != None:
+                        info(3, "Process %s (pid=%s) exited with %s." % (office.binary, ooproc.pid, retcode))
+                        break
+                    try:
+                        unocontext = resolver.resolve("uno:%s" % op.connection)
+                        break
+                    except UnoNoConnectException:
+                        time.sleep(0.5)
+                        timeout += 0.5
+                    except:
+                        raise
+                else:
+                    error("Failed to connect to %s (pid=%s) in %d seconds.\n%s" % (office.binary, ooproc.pid, op.timeout, e))
+            except Exception, e:
+                raise
+                error("Launch of %s failed.\n%s" % (office.binary, e))
+
+        if not unocontext:
+            die(251, "Unable to connect or start own listener. Aborting.")
+
+        ### And some more LibreOffice magic
+        unosvcmgr = unocontext.ServiceManager
+        self.desktop = unosvcmgr.createInstanceWithContext("com.sun.star.frame.Desktop", unocontext)
+        self.cwd = global_unohelper.systemPathToFileUrl( os.getcwd() )
+
+        ### List all filters
+#        self.filters = unosvcmgr.createInstanceWithContext( "com.sun.star.document.FilterFactory", unocontext)
+#        for filter in self.filters.getElementNames():
+#            print filter
+#            #print dir(filter), dir(filter.format)
+
+    def getformat(self, inputfn):
+        doctype = None
+
+        ### Get the output format from mapping
+        if op.doctype:
+            outputfmt = fmts.bydoctype(op.doctype, op.format)
+        else:
+            outputfmt = fmts.byname(op.format)
+
+            if not outputfmt:
+                outputfmt = fmts.byextension(os.extsep + op.format)
+
+        ### If no doctype given, check list of acceptable formats for input file ext doctype
+        ### FIXME: This should go into the for-loop to match each individual input filename
+        if outputfmt:
+            inputext = os.path.splitext(inputfn)[1]
+            inputfmt = fmts.byextension(inputext)
+            if inputfmt:
+                for fmt in outputfmt:
+                    if inputfmt[0].doctype == fmt.doctype:
+                        doctype = inputfmt[0].doctype
+                        outputfmt = fmt
+                        break
+                else:
+                    outputfmt = outputfmt[0]
+    #       print >>sys.stderr, 'unoconv: format `%s\' is part of multiple doctypes %s, selecting `%s\'.' % (format, [fmt.doctype for fmt in outputfmt], outputfmt[0].doctype)
+            else:
+                outputfmt = outputfmt[0]
+
+        ### No format found, throw error
+        if not outputfmt:
+            if doctype:
+                print >>sys.stderr, 'unoconv: format [%s/%s] is not known to unoconv.' % (op.doctype, op.format)
+            else:
+                print >>sys.stderr, 'unoconv: format [%s] is not known to unoconv.' % op.format
+            die(1)
+
+        return outputfmt
+
+    def convert(self, inputfn):
+        global exitcode
+
+        document = None
+        outputfmt = self.getformat(inputfn)
+
+        if op.verbose > 0:
+            print >>sys.stderr, 'Input file:', inputfn
+
+        if not os.path.exists(inputfn):
+            print >>sys.stderr, 'unoconv: file `%s\' does not exist.' % inputfn
+            exitcode = 1
+
+        try:
+            ### Import phase
+            phase = "import"
+
+            ### Load inputfile
+            inputprops = GlobalUnoProps(Hidden=True, ReadOnly=True, UpdateDocMode=UNO_QUIET_UPDATE)
+
+#            if op.password:
+#                info = GlobalUnoProps(algorithm-name="PBKDF2", salt="salt", iteration-count=1024, hash="hash")
+#                inputprops += GlobalUnoProps(ModifyPasswordInfo=info)
+
+            ### Cannot use GlobalUnoProps for FilterData property
+            if op.importfilteroptions:
+#                print "Import filter options: %s" % op.importfilteroptions
+                inputprops += GlobalUnoProps(FilterOptions=op.importfilteroptions)
+
+            ### Cannot use GlobalUnoProps for FilterData property
+            if op.importfilter:
+                inputprops += ( UnoPropertyValue( "FilterData", 0, global_uno.Any("[]com.sun.star.beans.PropertyValue", tuple( op.importfilter ), ), 0 ), )
+
+            inputurl = global_unohelper.absolutize(self.cwd, global_unohelper.systemPathToFileUrl(inputfn))
+            document = self.desktop.loadComponentFromURL( inputurl , "_blank", 0, inputprops )
+
+            if not document:
+                raise UnoException("The document '%s' could not be opened." % inputurl, None)
+
+            ### Import style template
+            phase = "import-style"
+            if op.template:
+                if os.path.exists(op.template):
+                    info(1, "Template file: %s" % op.template)
+                    templateprops = GlobalUnoProps(OverwriteStyles=True)
+                    templateurl = global_unohelper.absolutize(self.cwd, global_unohelper.systemPathToFileUrl(op.template))
+                    document.StyleFamilies.loadStylesFromURL(templateurl, templateprops)
+                else:
+                    print >>sys.stderr, 'unoconv: template file `%s\' does not exist.' % op.template
+                    exitcode = 1
+
+            ### Update document links
+            phase = "update-links"
+            try:
+                document.updateLinks()
+            except AttributeError:
+                # the document doesn't implement the XLinkUpdate interface
+                pass
+
+            ### Update document indexes
+            phase = "update-indexes"
+            try:
+                document.refresh()
+                indexes = document.getDocumentIndexes()
+            except AttributeError:
+                # the document doesn't implement the XRefreshable and/or
+                # XDocumentIndexesSupplier interfaces
+                pass
+            else:
+                for i in range(0, indexes.getCount()):
+                    indexes.getByIndex(i).update()
+
+            info(1, "Selected output format: %s" % outputfmt)
+            info(2, "Selected office filter: %s" % outputfmt.filter)
+            info(2, "Used doctype: %s" % outputfmt.doctype)
+
+            ### Export phase
+            phase = "export"
+
+            outputprops = GlobalUnoProps(FilterName=outputfmt.filter, OutputStream=GlobalOutputStream(), Overwrite=True)
+
+            ### Set default filter options
+            if op.exportfilteroptions:
+#                print "Export filter options: %s" % op.exportfilteroptions
+                outputprops += GlobalUnoProps(FilterOptions=op.exportfilteroptions)
+            else:
+                if outputfmt.filter == 'Text (encoded)':
+                    outputprops += GlobalUnoProps(FilterOptions="76,LF")
+
+                elif outputfmt.filter == 'Text':
+                    outputprops += GlobalUnoProps(FilterOptions="76")
+
+                elif outputfmt.filter == 'Text - txt - csv (StarCalc)':
+                    outputprops += GlobalUnoProps(FilterOptions="44,34,76")
+
+
+            ### Cannot use GlobalUnoProps for FilterData property
+            if op.exportfilter:
+                outputprops += ( UnoPropertyValue( "FilterData", 0, global_uno.Any("[]com.sun.star.beans.PropertyValue", tuple( op.exportfilter ), ), 0 ), )
+
+            if not op.stdout:
+                (outputfn, ext) = os.path.splitext(inputfn)
+                if not op.output:
+                    outputfn = outputfn + os.extsep + outputfmt.extension
+                elif os.path.isdir(op.output):
+                    outputfn = realpath(op.output, os.path.basename(outputfn) + os.extsep + outputfmt.extension)
+                elif len(op.filenames) > 1:
+                    outputfn = op.output + os.extsep + outputfmt.extension
+                else:
+                    outputfn = op.output
+
+                outputurl = global_unohelper.absolutize( self.cwd, global_unohelper.systemPathToFileUrl(outputfn) )
+                info(1, "Output file: %s" % outputfn)
+            else:
+                outputurl = "private:stream"
+
+            try:
+                document.storeToURL(outputurl, tuple(outputprops) )
+            except UnoIOException, e:
+                raise UnoException("Unable to store document to %s (ErrCode %d)\n\nProperties: %s" % (outputurl, e.ErrCode, outputprops), None)
+
+            phase = "dispose"
+            document.dispose()
+            document.close(True)
+
+        except SystemError, e:
+            error("unoconv: SystemError during %s phase:\n%s" % (phase, e))
+            exitcode = 1
+
+        except UnoRuntimeException, e:
+            error("unoconv: RuntimeException during %s phase:\nOffice probably died. %s" % (phase, e))
+            exitcode = 6
+
+        except UnoDisposedException, e:
+            error("unoconv: DisposedException during %s phase:\nOffice probably died. %s" % (phase, e))
+            exitcode = 7
+
+        except UnoIllegalArgumentException, e:
+            error("UNO IllegalArgument during %s phase:\nSource file cannot be read. %s" % (phase, e))
+            exitcode = 8
+
+        except UnoIOException, e:
+#            for attr in dir(e): print '%s: %s', (attr, getattr(e, attr))
+            error("unoconv: IOException during %s phase:\n%s" % (phase, e.Message))
+            exitcode = 3
+
+        except UnoCannotConvertException, e:
+#            for attr in dir(e): print '%s: %s', (attr, getattr(e, attr))
+            error("unoconv: CannotConvertException during %s phase:\n%s" % (phase, e.Message))
+            exitcode = 4
+
+        except UnoException, e:
+            if hasattr(e, 'ErrCode'):
+                error("unoconv: UnoException during %s phase in %s (ErrCode %d)" % (phase, repr(e.__class__), e.ErrCode))
+                exitcode = e.ErrCode
+                pass
+            if hasattr(e, 'Message'):
+                error("unoconv: UnoException during %s phase:\n%s" % (phase, e.Message))
+                exitcode = 5
+            else:
+                error("unoconv: UnoException during %s phase in %s" % (phase, repr(e.__class__)))
+                exitcode = 2
+                pass
+
+class Listener:
+    def __init__(self):
+        global product
+
+        info(1, "Start listener on %s:%s" % (op.server, op.port))
+        self.context = global_uno.getComponentContext()
+        self.svcmgr = self.context.ServiceManager
+        try:
+            resolver = self.svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", self.context)
+            product = self.svcmgr.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", GlobalUnoProps(nodepath="/org.openoffice.Setup/Product"))
+            try:
+                unocontext = resolver.resolve("uno:%s" % op.connection)
+            except UnoNoConnectException, e:
+                pass
+            else:
+                info(1, "Existing %s listener found, nothing to do." % product.ooName)
+                return
+            if product.ooName != "LibreOffice" or LooseVersion(product.ooSetupVersion) <= LooseVersion('3.3'):
+                subprocess.call([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nologo", "-nofirststartwizard", "-norestore", "-accept=%s" % op.connection], env=os.environ)
+            else:
+                subprocess.call([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nologo", "--nofirststartwizard", "--norestore", "--accept=%s" % op.connection], env=os.environ)
+        except Exception, e:
+            error("Launch of %s failed.\n%s" % (office.binary, e))
+        else:
+            info(1, "Existing %s listener found, nothing to do." % product.ooName)
+
+def error(msg):
+    "Output error message"
+    print >>sys.stderr, msg
+
+def info(level, msg):
+    "Output info message"
+    if 'op' not in globals():
+        pass
+    elif op.verbose >= 3 and level >= 3:
+        print >>sys.stderr, "DEBUG:", msg
+    elif not op.stdout and level <= op.verbose:
+        print >>sys.stdout, msg
+    elif level <= op.verbose:
+        print >>sys.stderr, msg
+
+def die(ret, msg=None):
+    "Print optional error and exit with errorcode"
+    global convertor, ooproc, office
+
+    if msg:
+        error('Error: %s' % msg)
+
+    ### Did we start our own listener instance ?
+    if not op.listener and ooproc and convertor:
+
+        ### If there is a GUI now attached to the instance, disable listener
+        if convertor.desktop.getCurrentFrame():
+            info(2, 'Trying to stop %s GUI listener.' % product.ooName)
+            try:
+                if product.ooName != "LibreOffice" or product.ooSetupVersion <= 3.3:
+                    subprocess.Popen([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nofirststartwizard", "-nologo", "-norestore", "-unaccept=%s" % op.connection], env=os.environ)
+                else:
+                    subprocess.Popen([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nofirststartwizard", "--nologo", "--norestore", "--unaccept=%s" % op.connection], env=os.environ)
+                ooproc.wait()
+                info(2, '%s listener successfully disabled.' % product.ooName)
+            except Exception, e:
+                error("Terminate using %s failed.\n%s" % (office.binary, e))
+
+        ### If there is no GUI attached to the instance, terminate instance
+        else:
+            info(3, 'Terminating %s instance.' % product.ooName)
+            try:
+                convertor.desktop.terminate()
+            except UnoDisposedException:
+                info(2, '%s instance unsuccessfully closed, sending TERM signal.' % product.ooName)
+                try:
+                    ooproc.terminate()
+                except AttributeError:
+                    os.kill(ooproc.pid, 15)
+            info(3, 'Waiting for %s instance to exit.' % product.ooName)
+            ooproc.wait()
+
+        ### LibreOffice processes may get stuck and we have to kill them
+        ### Is it still running ?
+        if ooproc.poll() == None:
+            info(1, '%s instance still running, please investigate...' % product.ooName)
+            ooproc.wait()
+            info(2, '%s instance unsuccessfully terminated, sending KILL signal.' % product.ooName)
+            try:
+                ooproc.kill()
+            except AttributeError:
+                os.kill(ooproc.pid, 9)
+            info(3, 'Waiting for %s with pid %s to disappear.' % (ooproc.pid, product.ooName))
+            ooproc.wait()
+
+    # allow Python GC to garbage collect pyuno object *before* exit call
+    # which avoids random segmentation faults --vpa
+    convertor = None
+
+    sys.exit(ret)
+
+def main():
+    global convertor, exitcode
+    convertor = None
+
+    try:
+        if op.listener:
+            listener = Listener()
+
+        if op.filenames:
+            convertor = Convertor()
+            for inputfn in op.filenames:
+                convertor.convert(inputfn)
+
+    except UnoNoConnectException, e:
+        error("unoconv: could not find an existing connection to LibreOffice at %s:%s." % (op.server, op.port))
+        if op.connection:
+            info(0, "Please start an LibreOffice instance on server '%s' by doing:\n\n    unoconv --listener --server %s --port %s\n\nor alternatively:\n\n    soffice -nologo -nodefault -accept=\"%s\"" % (op.server, op.server, op.port, op.connection))
+        else:
+            info(0, "Please start an LibreOffice instance on server '%s' by doing:\n\n    unoconv --listener --server %s --port %s\n\nor alternatively:\n\n    soffice -nologo -nodefault -accept=\"socket,host=%s,port=%s;urp;\"" % (op.server, op.server, op.port, op.server, op.port))
+            info(0, "Please start an soffice instance on server '%s' by doing:\n\n    soffice -nologo -nodefault -accept=\"socket,host=127.0.0.1,port=%s;urp;\"" % (op.server, op.port))
+        exitcode = 1
+#    except UnboundLocalError:
+#        die(252, "Failed to connect to remote listener.")
+    except OSError:
+        error("Warning: failed to launch Office suite. Aborting.")
+
+### Main entrance
+def run():
+    global exitcode
+    exitcode = 0
+
+    info(3, 'sysname=%s, platform=%s, python=%s, python-version=%s' % (os.name, sys.platform, sys.executable, sys.version))
+
+    for of in find_offices():
+        if of.python != sys.executable and not sys.executable.startswith(of.basepath):
+            python_switch(of)
+        office_environ(of)
+#        debug_office()
+        try:
+            global global_uno
+            global global_unohelper
+
+            import uno as global_uno
+            import unohelper as global_unohelper
+            global office
+            office = of
+            break
+        except:
+#            debug_office()
+            print >>sys.stderr, "unoconv: Cannot find a suitable pyuno library and python binary combination in %s" % of
+            print >>sys.stderr, "ERROR:", sys.exc_info()[1]
+            print >>sys.stderr
+    else:
+#        debug_office()
+        print >>sys.stderr, "unoconv: Cannot find a suitable office installation on your system."
+        print >>sys.stderr, "ERROR: Please locate your office installation and send your feedback to:"
+        print >>sys.stderr, "       http://github.com/dagwieers/unoconv/issues"
+        sys.exit(1)
+
+    ### Now that we have found a working pyuno library, let's import some classes
+    global UnoPropertyValue
+    global UnoNoConnectException
+    global UNO_QUIET_UPDATE
+    global UnoDisposedException
+    global UnoIllegalArgumentException
+    global UnoIOException
+    global UnoXOutputStream
+    global UnoCannotConvertException
+    global UnoException
+    global UnoRuntimeException
+
+    from com.sun.star.beans import PropertyValue as UnoPropertyValue
+    from com.sun.star.connection import NoConnectException as UnoNoConnectException
+    from com.sun.star.document.UpdateDocMode import QUIET_UPDATE as UNO_QUIET_UPDATE
+    from com.sun.star.lang import DisposedException as UnoDisposedException
+    from com.sun.star.lang import IllegalArgumentException as UnoIllegalArgumentException
+    from com.sun.star.io import IOException as UnoIOException
+    from com.sun.star.io import XOutputStream as UnoXOutputStream
+    from com.sun.star.script import CannotConvertException as UnoCannotConvertException
+    from com.sun.star.uno import Exception as UnoException
+    from com.sun.star.uno import RuntimeException as UnoRuntimeException
+
+    ### And now that we have those classes, build on them
+    class OutputStream( global_unohelper.Base, UnoXOutputStream ):
+        def __init__( self ):
+            self.closed = 0
+
+        def closeOutput(self):
+            self.closed = 1
+
+        def writeBytes( self, seq ):
+            sys.stdout.write( seq.value )
+
+        def flush( self ):
+            pass
+
+    global GlobalOutputStream
+    GlobalOutputStream = OutputStream
+
+    def UnoProps(**args):
+        props = []
+        for key in args:
+            prop = UnoPropertyValue()
+            prop.Name = key
+            prop.Value = args[key]
+            props.append(prop)
+        return tuple(props)
+
+    global GlobalUnoProps
+    GlobalUnoProps = UnoProps
+
+    global op
+    op = Options(sys.argv[1:])
+
+    info(2, "Using office base path: %s" % office.basepath)
+    info(2, "Using office binary path: %s" % office.unopath)
+
+    try:
+        main()
+    except KeyboardInterrupt, e:
+        die(6, 'Exiting on user request')
+    die(exitcode)
+
+if __name__ == '__main__':
+    run()
diff --git a/unoconv3.py b/unoconv3.py
new file mode 100755
index 0000000..09d88c2
--- /dev/null
+++ b/unoconv3.py
@@ -0,0 +1,1195 @@
+#!/usr/bin/python3
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; version 2 only
+###
+### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+### Copyright 2007-2010 Dag Wieers <dag@wieers.com>
+
+from distutils.version import LooseVersion
+import getopt
+import glob
+import os
+import subprocess
+import sys
+import time
+
+__version__ = "$Revision$"
+# $Source$
+
+VERSION = '0.6'
+
+doctypes = ('document', 'graphics', 'presentation', 'spreadsheet')
+
+global convertor, office, ooproc, product
+ooproc = None
+exitcode = 0
+
+class Office:
+    def __init__(self, basepath, urepath, unopath, pyuno, binary, python, pythonhome):
+        self.basepath = basepath
+        self.urepath = urepath
+        self.unopath = unopath
+        self.pyuno = pyuno
+        self.binary = binary
+        self.python = python
+        self.pythonhome = pythonhome
+
+    def __str__(self):
+        return self.basepath
+
+    def __repr__(self):
+        return self.basepath
+
+### Implement a path normalizer in order to make unoconv work on MacOS X
+### (on which 'program' is a symlink to 'MacOSX' which seems to break unoconv)
+def realpath(*args):
+    ''' Implement a combination of os.path.join(), os.path.abspath() and
+        os.path.realpath() in order to normalize path constructions '''
+    ret = ''
+    for arg in args:
+        ret = os.path.join(ret, arg)
+    return os.path.realpath(os.path.abspath(ret))
+
+### The first thing we ought to do is find a suitable Office installation
+### with a compatible pyuno library that we can import.
+###
+### See: http://user.services.openoffice.org/en/forum/viewtopic.php?f=45&t=36370&p=166783
+
+def find_offices():
+    ret = []
+    extrapaths = []
+
+    ### Try using UNO_PATH first (in many incarnations, we'll see what sticks)
+    if 'UNO_PATH' in os.environ:
+        extrapaths += [ os.environ['UNO_PATH'],
+                        os.path.dirname(os.environ['UNO_PATH']),
+                        os.path.dirname(os.path.dirname(os.environ['UNO_PATH'])) ]
+
+    else:
+
+        if os.name in ( 'nt', 'os2' ):
+            if 'PROGRAMFILES' in list(os.environ.keys()):
+                extrapaths += glob.glob(os.environ['PROGRAMFILES']+'\\LibreOffice*') + \
+                              glob.glob(os.environ['PROGRAMFILES']+'\\OpenOffice.org*')
+
+            if 'PROGRAMFILES(X86)' in list(os.environ.keys()):
+                extrapaths += glob.glob(os.environ['PROGRAMFILES(X86)']+'\\LibreOffice*') + \
+                              glob.glob(os.environ['PROGRAMFILES(X86)']+'\\OpenOffice.org*')
+
+        elif os.name in ( 'mac', ) or sys.platform in ( 'darwin', ):
+            extrapaths += [ '/Applications/LibreOffice.app/Contents',
+                            '/Applications/NeoOffice.app/Contents',
+                            '/Applications/OpenOffice.org.app/Contents' ]
+
+        else:
+            extrapaths += glob.glob('/usr/lib*/libreoffice*') + \
+                          glob.glob('/usr/lib*/openoffice*') + \
+                          glob.glob('/usr/lib*/ooo*') + \
+                          glob.glob('/opt/libreoffice*') + \
+                          glob.glob('/opt/openoffice*') + \
+                          glob.glob('/opt/ooo*') + \
+                          glob.glob('/usr/local/libreoffice*') + \
+                          glob.glob('/usr/local/openoffice*') + \
+                          glob.glob('/usr/local/ooo*') + \
+                          glob.glob('/usr/local/lib/libreoffice*')
+
+    ### Find a working set for python UNO bindings
+    for basepath in extrapaths:
+        if os.name in ( 'nt', 'os2' ):
+            officelibraries = ( 'pyuno.pyd', )
+            officebinaries = ( 'soffice.exe' ,)
+            pythonbinaries = ( 'python.exe', )
+            pythonhomes = ()
+        elif os.name in ( 'mac', ) or sys.platform in ( 'darwin', ):
+            officelibraries = ( 'pyuno.so', 'libpyuno.dylib' )
+            officebinaries = ( 'soffice.bin', )
+            pythonbinaries = ( 'python.bin', 'python' )
+            pythonhomes = ( 'OOoPython.framework/Versions/*/lib/python*', )
+        else:
+            officelibraries = ( 'pyuno.so', )
+            officebinaries = ( 'soffice.bin', )
+            pythonbinaries = ( 'python.bin', 'python', )
+            pythonhomes = ( 'python-core-*', )
+
+        ### Older LibreOffice/OpenOffice and Windows use basis-link/ or basis/
+        libpath = 'error'
+        for basis in ( 'basis-link', 'basis', '' ):
+            for lib in officelibraries:
+                if os.path.isfile(realpath(basepath, basis, 'program', lib)):
+                    libpath = realpath(basepath, basis, 'program')
+                    officelibrary = realpath(libpath, lib)
+                    info(3, "Found %s in %s" % (lib, libpath))
+                    # Break the inner loop...
+                    break
+            # Continue if the inner loop wasn't broken.
+            else:
+                continue
+            # Inner loop was broken, break the outer.
+            break
+        else:
+            continue
+
+        ### MacOSX have soffice binaries installed in MacOS subdirectory, not program
+        unopath = 'error'
+        for basis in ( 'basis-link', 'basis', '' ):
+            for bin in officebinaries:
+                if os.path.isfile(realpath(basepath, basis, 'program', bin)):
+                    unopath = realpath(basepath, basis, 'program')
+                    officebinary = realpath(unopath, bin)
+                    info(3, "Found %s in %s" % (bin, unopath))
+                    # Break the inner loop...
+                    break
+            # Continue if the inner loop wasn't broken.
+            else:
+                continue
+            # Inner loop was broken, break the outer.
+            break
+        else:
+            continue
+
+        ### Windows does not provide or need a URE/lib directory ?
+        urepath = ''
+        for basis in ( 'basis-link', 'basis', '' ):
+            for ure in ( 'ure-link', 'ure', 'URE', '' ):
+                if os.path.isfile(realpath(basepath, basis, ure, 'lib', 'unorc')):
+                    urepath = realpath(basepath, basis, ure)
+                    info(3, "Found %s in %s" % ('unorc', realpath(urepath, 'lib')))
+                    # Break the inner loop...
+                    break
+            # Continue if the inner loop wasn't broken.
+            else:
+                continue
+            # Inner loop was broken, break the outer.
+            break
+
+        pythonhome = None
+        for home in pythonhomes:
+            if glob.glob(realpath(libpath, home)):
+                pythonhome = glob.glob(realpath(libpath, home))[0]
+                info(3, "Found %s in %s" % (home, pythonhome))
+                break
+
+#        if not os.path.isfile(realpath(basepath, program, officebinary)):
+#            continue
+#        info(3, "Found %s in %s" % (officebinary, realpath(basepath, program)))
+
+#        if not glob.glob(realpath(basepath, basis, program, 'python-core-*')):
+#            continue
+
+        for pythonbinary in pythonbinaries:
+            if os.path.isfile(realpath(unopath, pythonbinary)):
+                info(3, "Found %s in %s" % (pythonbinary, unopath))
+                ret.append(Office(basepath, urepath, unopath, officelibrary, officebinary,
+                                  realpath(unopath, pythonbinary), pythonhome))
+        else:
+            info(3, "Considering %s" % basepath)
+            ret.append(Office(basepath, urepath, unopath, officelibrary, officebinary,
+                              sys.executable, None))
+    return ret
+
+def office_environ(office):
+    ### Set PATH so that crash_report is found
+    os.environ['PATH'] = realpath(office.basepath, 'program') + os.pathsep + os.environ['PATH']
+
+    ### Set UNO_PATH so that "officehelper.bootstrap()" can find soffice executable:
+    os.environ['UNO_PATH'] = office.unopath
+
+    ### Set URE_BOOTSTRAP so that "global_uno.getComponentContext()" bootstraps a complete
+    ### UNO environment
+    if os.name in ( 'nt', 'os2' ):
+        os.environ['URE_BOOTSTRAP'] = 'vnd.sun.star.pathname:' + realpath(office.basepath, 'program', 'fundamental.ini')
+    else:
+        os.environ['URE_BOOTSTRAP'] = 'vnd.sun.star.pathname:' + realpath(office.basepath, 'program', 'fundamentalrc')
+
+        ### Set LD_LIBRARY_PATH so that "import pyuno" finds libpyuno.so:
+        if 'LD_LIBRARY_PATH' in os.environ:
+            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
+                                            realpath(office.urepath, 'lib') + os.pathsep + \
+                                            os.environ['LD_LIBRARY_PATH']
+        else:
+            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
+                                            realpath(office.urepath, 'lib')
+
+    if office.pythonhome:
+        for libpath in ( realpath(office.pythonhome, 'lib'),
+                         realpath(office.pythonhome, 'lib', 'lib-dynload'),
+                         realpath(office.pythonhome, 'lib', 'lib-tk'),
+                         realpath(office.pythonhome, 'lib', 'site-packages'),
+                         office.unopath):
+            sys.path.insert(0, libpath)
+    else:
+        ### Still needed for system python using LibreOffice UNO bindings
+        ### Although we prefer to use a system UNO binding in this case
+        sys.path.append(office.unopath)
+
+def debug_office():
+    if 'URE_BOOTSTRAP' in os.environ:
+        print('URE_BOOTSTRAP=%s' % os.environ['URE_BOOTSTRAP'], file=sys.stderr)
+    if 'UNO_PATH' in os.environ:
+        print('UNO_PATH=%s' % os.environ['UNO_PATH'], file=sys.stderr)
+    if 'UNO_TYPES' in os.environ:
+        print('UNO_TYPES=%s' % os.environ['UNO_TYPES'], file=sys.stderr)
+    print('PATH=%s' % os.environ['PATH'])
+    if 'PYTHONHOME' in os.environ:
+        print('PYTHONHOME=%s' % os.environ['PYTHONHOME'], file=sys.stderr)
+    if 'PYTHONPATH' in os.environ:
+        print('PYTHONPATH=%s' % os.environ['PYTHONPATH'], file=sys.stderr)
+    if 'LD_LIBRARY_PATH' in os.environ:
+        print('LD_LIBRARY_PATH=%s' % os.environ['LD_LIBRARY_PATH'], file=sys.stderr)
+
+def python_switch(office):
+    if office.pythonhome:
+        os.environ['PYTHONHOME'] = office.pythonhome
+        os.environ['PYTHONPATH'] = realpath(office.pythonhome, 'lib') + os.pathsep + \
+                                   realpath(office.pythonhome, 'lib', 'lib-dynload') + os.pathsep + \
+                                   realpath(office.pythonhome, 'lib', 'lib-tk') + os.pathsep + \
+                                   realpath(office.pythonhome, 'lib', 'site-packages') + os.pathsep + \
+                                   office.unopath
+
+    os.environ['UNO_PATH'] = office.unopath
+
+    info(3, "-> Switching from %s to %s" % (sys.executable, office.python))
+    if os.name in ('nt', 'os2'):
+        ### os.execv is broken on Windows and can't properly parse command line
+        ### arguments and executable name if they contain whitespaces. subprocess
+        ### fixes that behavior.
+        ret = subprocess.call([office.python] + sys.argv[0:])
+        sys.exit(ret)
+    else:
+
+        ### Set LD_LIBRARY_PATH so that "import pyuno" finds libpyuno.so:
+        if 'LD_LIBRARY_PATH' in os.environ:
+            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
+                                            realpath(office.urepath, 'lib') + os.pathsep + \
+                                            os.environ['LD_LIBRARY_PATH']
+        else:
+            os.environ['LD_LIBRARY_PATH'] = office.unopath + os.pathsep + \
+                                            realpath(office.urepath, 'lib')
+
+        try:
+            os.execvpe(office.python, [office.python, ] + sys.argv[0:], os.environ)
+            print((office.python, [office.python, ] + sys.argv[0:], osenviron))
+        except OSError:
+            ### Mac OS X versions prior to 10.6 do not support execv in
+            ### a process that contains multiple threads.  Instead of
+            ### re-executing in the current process, start a new one
+            ### and cause the current process to exit.  This isn't
+            ### ideal since the new process is detached from the parent
+            ### terminal and thus cannot easily be killed with ctrl-C,
+            ### but it's better than not being able to autoreload at
+            ### all.
+            ### Unfortunately the errno returned in this case does not
+            ### appear to be consistent, so we can't easily check for
+            ### this error specifically.
+            ret = os.spawnvpe(os.P_WAIT, office.python, [office.python, ] + sys.argv[0:], os.environ)
+            sys.exit(ret)
+
+class Fmt:
+    def __init__(self, doctype, name, extension, summary, filter):
+        self.doctype = doctype
+        self.name = name
+        self.extension = extension
+        self.summary = summary
+        self.filter = filter
+
+    def __str__(self):
+        return "%s [.%s]" % (self.summary, self.extension)
+
+    def __repr__(self):
+        return "%s/%s" % (self.name, self.doctype)
+
+class FmtList:
+    def __init__(self):
+        self.list = []
+
+    def add(self, doctype, name, extension, summary, filter):
+        self.list.append(Fmt(doctype, name, extension, summary, filter))
+
+    def byname(self, name):
+        ret = []
+        for fmt in self.list:
+            if fmt.name == name:
+                ret.append(fmt)
+        return ret
+
+    def byextension(self, extension):
+        ret = []
+        for fmt in self.list:
+            if os.extsep + fmt.extension == extension:
+                ret.append(fmt)
+        return ret
+
+    def bydoctype(self, doctype, name):
+        ret = []
+        for fmt in self.list:
+            if fmt.name == name and fmt.doctype == doctype:
+                ret.append(fmt)
+        return ret
+
+    def display(self, doctype):
+        print("The following list of %s formats are currently available:\n" % doctype, file=sys.stderr)
+        for fmt in self.list:
+            if fmt.doctype == doctype:
+                print("  %-8s - %s" % (fmt.name, fmt), file=sys.stderr)
+        print(file=sys.stderr)
+
+fmts = FmtList()
+
+### TextDocument
+fmts.add('document', 'bib', 'bib', 'BibTeX', 'BibTeX_Writer') ### 22
+fmts.add('document', 'doc', 'doc', 'Microsoft Word 97/2000/XP', 'MS Word 97') ### 29
+fmts.add('document', 'doc6', 'doc', 'Microsoft Word 6.0', 'MS WinWord 6.0') ### 24
+fmts.add('document', 'doc95', 'doc', 'Microsoft Word 95', 'MS Word 95') ### 28
+fmts.add('document', 'docbook', 'xml', 'DocBook', 'DocBook File') ### 39
+fmts.add('document', 'docx', 'docx', 'Microsoft Office Open XML', 'Office Open XML Text')
+fmts.add('document', 'docx7', 'docx', 'Microsoft Office Open XML', 'MS Word 2007 XML')
+fmts.add('document', 'fodt', 'fodt', 'OpenDocument Text (Flat XML)', 'OpenDocument Text Flat XML')
+fmts.add('document', 'html', 'html', 'HTML Document (OpenOffice.org Writer)', 'HTML (StarWriter)') ### 3
+fmts.add('document', 'latex', 'ltx', 'LaTeX 2e', 'LaTeX_Writer') ### 31
+fmts.add('document', 'mediawiki', 'txt', 'MediaWiki', 'MediaWiki')
+fmts.add('document', 'odt', 'odt', 'ODF Text Document', 'writer8') ### 10
+fmts.add('document', 'ooxml', 'xml', 'Microsoft Office Open XML', 'MS Word 2003 XML') ### 11
+fmts.add('document', 'ott', 'ott', 'Open Document Text', 'writer8_template') ### 21
+fmts.add('document', 'pdb', 'pdb', 'AportisDoc (Palm)', 'AportisDoc Palm DB')
+fmts.add('document', 'pdf', 'pdf', 'Portable Document Format', 'writer_pdf_Export') ### 18
+fmts.add('document', 'psw', 'psw', 'Pocket Word', 'PocketWord File')
+fmts.add('document', 'rtf', 'rtf', 'Rich Text Format', 'Rich Text Format') ### 16
+fmts.add('document', 'sdw', 'sdw', 'StarWriter 5.0', 'StarWriter 5.0') ### 23
+fmts.add('document', 'sdw4', 'sdw', 'StarWriter 4.0', 'StarWriter 4.0') ### 2
+fmts.add('document', 'sdw3', 'sdw', 'StarWriter 3.0', 'StarWriter 3.0') ### 20
+fmts.add('document', 'stw', 'stw', 'Open Office.org 1.0 Text Document Template', 'writer_StarOffice_XML_Writer_Template') ### 9
+fmts.add('document', 'sxw', 'sxw', 'Open Office.org 1.0 Text Document', 'StarOffice XML (Writer)') ### 1
+fmts.add('document', 'text', 'txt', 'Text Encoded', 'Text (encoded)') ### 26
+fmts.add('document', 'txt', 'txt', 'Text', 'Text') ### 34
+fmts.add('document', 'uot', 'uot', 'Unified Office Format text','UOF text') ### 27
+fmts.add('document', 'vor', 'vor', 'StarWriter 5.0 Template', 'StarWriter 5.0 Vorlage/Template') ### 6
+fmts.add('document', 'vor4', 'vor', 'StarWriter 4.0 Template', 'StarWriter 4.0 Vorlage/Template') ### 5
+fmts.add('document', 'vor3', 'vor', 'StarWriter 3.0 Template', 'StarWriter 3.0 Vorlage/Template') ### 4
+fmts.add('document', 'xhtml', 'html', 'XHTML Document', 'XHTML Writer File') ### 33
+
+### WebDocument
+fmts.add('web', 'etext', 'txt', 'Text Encoded (OpenOffice.org Writer/Web)', 'Text (encoded) (StarWriter/Web)') ### 14
+fmts.add('web', 'html10', 'html', 'OpenOffice.org 1.0 HTML Template', 'writer_web_StarOffice_XML_Writer_Web_Template') ### 11
+fmts.add('web', 'html', 'html', 'HTML Document', 'HTML') ### 2
+fmts.add('web', 'html', 'html', 'HTML Document Template', 'writerweb8_writer_template') ### 13
+fmts.add('web', 'mediawiki', 'txt', 'MediaWiki', 'MediaWiki_Web') ### 9
+fmts.add('web', 'pdf', 'pdf', 'PDF - Portable Document Format', 'writer_web_pdf_Export') ### 10
+fmts.add('web', 'sdw3', 'sdw', 'StarWriter 3.0 (OpenOffice.org Writer/Web)', 'StarWriter 3.0 (StarWriter/Web)') ### 3
+fmts.add('web', 'sdw4', 'sdw', 'StarWriter 4.0 (OpenOffice.org Writer/Web)', 'StarWriter 4.0 (StarWriter/Web)') ### 4
+fmts.add('web', 'sdw', 'sdw', 'StarWriter 5.0 (OpenOffice.org Writer/Web)', 'StarWriter 5.0 (StarWriter/Web)') ### 5
+fmts.add('web', 'txt', 'txt', 'OpenOffice.org Text (OpenOffice.org Writer/Web)', 'writerweb8_writer') ### 12
+fmts.add('web', 'text10', 'txt', 'OpenOffice.org 1.0 Text Document (OpenOffice.org Writer/Web)', 'writer_web_StarOffice_XML_Writer') ### 15
+fmts.add('web', 'text', 'txt', 'Text (OpenOffice.org Writer/Web)', 'Text (StarWriter/Web)') ### 8
+fmts.add('web', 'vor4', 'vor', 'StarWriter/Web 4.0 Template', 'StarWriter/Web 4.0 Vorlage/Template') ### 6
+fmts.add('web', 'vor', 'vor', 'StarWriter/Web 5.0 Template', 'StarWriter/Web 5.0 Vorlage/Template') ### 7
+
+### Spreadsheet
+fmts.add('spreadsheet', 'csv', 'csv', 'Text CSV', 'Text - txt - csv (StarCalc)') ### 16
+fmts.add('spreadsheet', 'dbf', 'dbf', 'dBASE', 'dBase') ### 22
+fmts.add('spreadsheet', 'dif', 'dif', 'Data Interchange Format', 'DIF') ### 5
+fmts.add('spreadsheet', 'fods', 'fods', 'OpenDocument Spreadsheet (Flat XML)', 'OpenDocument Spreadsheet Flat XML')
+fmts.add('spreadsheet', 'html', 'html', 'HTML Document (OpenOffice.org Calc)', 'HTML (StarCalc)') ### 7
+fmts.add('spreadsheet', 'ods', 'ods', 'ODF Spreadsheet', 'calc8') ### 15
+fmts.add('spreadsheet', 'ooxml', 'xml', 'Microsoft Excel 2003 XML', 'MS Excel 2003 XML') ### 23
+fmts.add('spreadsheet', 'ots', 'ots', 'ODF Spreadsheet Template', 'calc8_template') ### 14
+fmts.add('spreadsheet', 'pdf', 'pdf', 'Portable Document Format', 'calc_pdf_Export') ### 34
+fmts.add('spreadsheet', 'pxl', 'pxl', 'Pocket Excel', 'Pocket Excel')
+fmts.add('spreadsheet', 'sdc', 'sdc', 'StarCalc 5.0', 'StarCalc 5.0') ### 31
+fmts.add('spreadsheet', 'sdc4', 'sdc', 'StarCalc 4.0', 'StarCalc 4.0') ### 11
+fmts.add('spreadsheet', 'sdc3', 'sdc', 'StarCalc 3.0', 'StarCalc 3.0') ### 29
+fmts.add('spreadsheet', 'slk', 'slk', 'SYLK', 'SYLK') ### 35
+fmts.add('spreadsheet', 'stc', 'stc', 'OpenOffice.org 1.0 Spreadsheet Template', 'calc_StarOffice_XML_Calc_Template') ### 2
+fmts.add('spreadsheet', 'sxc', 'sxc', 'OpenOffice.org 1.0 Spreadsheet', 'StarOffice XML (Calc)') ### 3
+fmts.add('spreadsheet', 'uos', 'uos', 'Unified Office Format spreadsheet', 'UOF spreadsheet') ### 9
+fmts.add('spreadsheet', 'vor3', 'vor', 'StarCalc 3.0 Template', 'StarCalc 3.0 Vorlage/Template') ### 18
+fmts.add('spreadsheet', 'vor4', 'vor', 'StarCalc 4.0 Template', 'StarCalc 4.0 Vorlage/Template') ### 19
+fmts.add('spreadsheet', 'vor', 'vor', 'StarCalc 5.0 Template', 'StarCalc 5.0 Vorlage/Template') ### 20
+fmts.add('spreadsheet', 'xhtml', 'xhtml', 'XHTML', 'XHTML Calc File') ### 26
+fmts.add('spreadsheet', 'xls', 'xls', 'Microsoft Excel 97/2000/XP', 'MS Excel 97') ### 12
+fmts.add('spreadsheet', 'xls5', 'xls', 'Microsoft Excel 5.0', 'MS Excel 5.0/95') ### 8
+fmts.add('spreadsheet', 'xls95', 'xls', 'Microsoft Excel 95', 'MS Excel 95') ### 10
+fmts.add('spreadsheet', 'xlt', 'xlt', 'Microsoft Excel 97/2000/XP Template', 'MS Excel 97 Vorlage/Template') ### 6
+fmts.add('spreadsheet', 'xlt5', 'xlt', 'Microsoft Excel 5.0 Template', 'MS Excel 5.0/95 Vorlage/Template') ### 28
+fmts.add('spreadsheet', 'xlt95', 'xlt', 'Microsoft Excel 95 Template', 'MS Excel 95 Vorlage/Template') ### 21
+
+### Graphics
+fmts.add('graphics', 'bmp', 'bmp', 'Windows Bitmap', 'draw_bmp_Export') ### 21
+fmts.add('graphics', 'emf', 'emf', 'Enhanced Metafile', 'draw_emf_Export') ### 15
+fmts.add('graphics', 'eps', 'eps', 'Encapsulated PostScript', 'draw_eps_Export') ### 48
+fmts.add('graphics', 'fodg', 'fodg', 'OpenDocument Drawing (Flat XML)', 'OpenDocument Drawing Flat XML')
+fmts.add('graphics', 'gif', 'gif', 'Graphics Interchange Format', 'draw_gif_Export') ### 30
+fmts.add('graphics', 'html', 'html', 'HTML Document (OpenOffice.org Draw)', 'draw_html_Export') ### 37
+fmts.add('graphics', 'jpg', 'jpg', 'Joint Photographic Experts Group', 'draw_jpg_Export') ### 3
+fmts.add('graphics', 'met', 'met', 'OS/2 Metafile', 'draw_met_Export') ### 43
+fmts.add('graphics', 'odd', 'odd', 'OpenDocument Drawing', 'draw8') ### 6
+fmts.add('graphics', 'otg', 'otg', 'OpenDocument Drawing Template', 'draw8_template') ### 20
+fmts.add('graphics', 'pbm', 'pbm', 'Portable Bitmap', 'draw_pbm_Export') ### 14
+fmts.add('graphics', 'pct', 'pct', 'Mac Pict', 'draw_pct_Export') ### 41
+fmts.add('graphics', 'pdf', 'pdf', 'Portable Document Format', 'draw_pdf_Export') ### 28
+fmts.add('graphics', 'pgm', 'pgm', 'Portable Graymap', 'draw_pgm_Export') ### 11
+fmts.add('graphics', 'png', 'png', 'Portable Network Graphic', 'draw_png_Export') ### 2
+fmts.add('graphics', 'ppm', 'ppm', 'Portable Pixelmap', 'draw_ppm_Export') ### 5
+fmts.add('graphics', 'ras', 'ras', 'Sun Raster Image', 'draw_ras_Export') ## 31
+fmts.add('graphics', 'std', 'std', 'OpenOffice.org 1.0 Drawing Template', 'draw_StarOffice_XML_Draw_Template') ### 53
+fmts.add('graphics', 'svg', 'svg', 'Scalable Vector Graphics', 'draw_svg_Export') ### 50
+fmts.add('graphics', 'svm', 'svm', 'StarView Metafile', 'draw_svm_Export') ### 55
+fmts.add('graphics', 'swf', 'swf', 'Macromedia Flash (SWF)', 'draw_flash_Export') ### 23
+fmts.add('graphics', 'sxd', 'sxd', 'OpenOffice.org 1.0 Drawing', 'StarOffice XML (Draw)') ### 26
+fmts.add('graphics', 'sxd3', 'sxd', 'StarDraw 3.0', 'StarDraw 3.0') ### 40
+fmts.add('graphics', 'sxd5', 'sxd', 'StarDraw 5.0', 'StarDraw 5.0') ### 44
+fmts.add('graphics', 'sxw', 'sxw', 'StarOffice XML (Draw)', 'StarOffice XML (Draw)')
+fmts.add('graphics', 'tiff', 'tiff', 'Tagged Image File Format', 'draw_tif_Export') ### 13
+fmts.add('graphics', 'vor', 'vor', 'StarDraw 5.0 Template', 'StarDraw 5.0 Vorlage') ### 36
+fmts.add('graphics', 'vor3', 'vor', 'StarDraw 3.0 Template', 'StarDraw 3.0 Vorlage') ### 35
+fmts.add('graphics', 'wmf', 'wmf', 'Windows Metafile', 'draw_wmf_Export') ### 8
+fmts.add('graphics', 'xhtml', 'xhtml', 'XHTML', 'XHTML Draw File') ### 45
+fmts.add('graphics', 'xpm', 'xpm', 'X PixMap', 'draw_xpm_Export') ### 19
+
+### Presentation
+fmts.add('presentation', 'bmp', 'bmp', 'Windows Bitmap', 'impress_bmp_Export') ### 15
+fmts.add('presentation', 'emf', 'emf', 'Enhanced Metafile', 'impress_emf_Export') ### 16
+fmts.add('presentation', 'eps', 'eps', 'Encapsulated PostScript', 'impress_eps_Export') ### 17
+fmts.add('presentation', 'fodp', 'fodp', 'OpenDocument Presentation (Flat XML)', 'OpenDocument Presentation Flat XML')
+fmts.add('presentation', 'gif', 'gif', 'Graphics Interchange Format', 'impress_gif_Export') ### 18
+fmts.add('presentation', 'html', 'html', 'HTML Document (OpenOffice.org Impress)', 'impress_html_Export') ### 43
+fmts.add('presentation', 'jpg', 'jpg', 'Joint Photographic Experts Group', 'impress_jpg_Export') ### 19
+fmts.add('presentation', 'met', 'met', 'OS/2 Metafile', 'impress_met_Export') ### 20
+fmts.add('presentation', 'odg', 'odg', 'ODF Drawing (Impress)', 'impress8_draw') ### 29
+fmts.add('presentation', 'odp', 'odp', 'ODF Presentation', 'impress8') ### 9
+fmts.add('presentation', 'otp', 'otp', 'ODF Presentation Template', 'impress8_template') ### 38
+fmts.add('presentation', 'pbm', 'pbm', 'Portable Bitmap', 'impress_pbm_Export') ### 21
+fmts.add('presentation', 'pct', 'pct', 'Mac Pict', 'impress_pct_Export') ### 22
+fmts.add('presentation', 'pdf', 'pdf', 'Portable Document Format', 'impress_pdf_Export') ### 23
+fmts.add('presentation', 'pgm', 'pgm', 'Portable Graymap', 'impress_pgm_Export') ### 24
+fmts.add('presentation', 'png', 'png', 'Portable Network Graphic', 'impress_png_Export') ### 25
+fmts.add('presentation', 'potm', 'potm', 'Microsoft PowerPoint 2007/2010 XML Template', 'Impress MS PowerPoint 2007 XML Template')
+fmts.add('presentation', 'pot', 'pot', 'Microsoft PowerPoint 97/2000/XP Template', 'MS PowerPoint 97 Vorlage') ### 3
+fmts.add('presentation', 'ppm', 'ppm', 'Portable Pixelmap', 'impress_ppm_Export') ### 26
+fmts.add('presentation', 'pptx', 'pptx', 'Microsoft PowerPoint 2007/2010 XML', 'Impress MS PowerPoint 2007 XML') ### 36
+fmts.add('presentation', 'pps', 'pps', 'Microsoft PowerPoint 97/2000/XP (Autoplay)', 'MS PowerPoint 97 Autoplay') ### 36
+fmts.add('presentation', 'ppt', 'ppt', 'Microsoft PowerPoint 97/2000/XP', 'MS PowerPoint 97') ### 36
+fmts.add('presentation', 'pwp', 'pwp', 'PlaceWare', 'placeware_Export') ### 30
+fmts.add('presentation', 'ras', 'ras', 'Sun Raster Image', 'impress_ras_Export') ### 27
+fmts.add('presentation', 'sda', 'sda', 'StarDraw 5.0 (OpenOffice.org Impress)', 'StarDraw 5.0 (StarImpress)') ### 8
+fmts.add('presentation', 'sdd', 'sdd', 'StarImpress 5.0', 'StarImpress 5.0') ### 6
+fmts.add('presentation', 'sdd3', 'sdd', 'StarDraw 3.0 (OpenOffice.org Impress)', 'StarDraw 3.0 (StarImpress)') ### 42
+fmts.add('presentation', 'sdd4', 'sdd', 'StarImpress 4.0', 'StarImpress 4.0') ### 37
+fmts.add('presentation', 'sxd', 'sxd', 'OpenOffice.org 1.0 Drawing (OpenOffice.org Impress)', 'impress_StarOffice_XML_Draw') ### 31
+fmts.add('presentation', 'sti', 'sti', 'OpenOffice.org 1.0 Presentation Template', 'impress_StarOffice_XML_Impress_Template') ### 5
+fmts.add('presentation', 'svg', 'svg', 'Scalable Vector Graphics', 'impress_svg_Export') ### 14
+fmts.add('presentation', 'svm', 'svm', 'StarView Metafile', 'impress_svm_Export') ### 13
+fmts.add('presentation', 'swf', 'swf', 'Macromedia Flash (SWF)', 'impress_flash_Export') ### 34
+fmts.add('presentation', 'sxi', 'sxi', 'OpenOffice.org 1.0 Presentation', 'StarOffice XML (Impress)') ### 41
+fmts.add('presentation', 'tiff', 'tiff', 'Tagged Image File Format', 'impress_tif_Export') ### 12
+fmts.add('presentation', 'uop', 'uop', 'Unified Office Format presentation', 'UOF presentation') ### 4
+fmts.add('presentation', 'vor', 'vor', 'StarImpress 5.0 Template', 'StarImpress 5.0 Vorlage') ### 40
+fmts.add('presentation', 'vor3', 'vor', 'StarDraw 3.0 Template (OpenOffice.org Impress)', 'StarDraw 3.0 Vorlage (StarImpress)') ###1
+fmts.add('presentation', 'vor4', 'vor', 'StarImpress 4.0 Template', 'StarImpress 4.0 Vorlage') ### 39
+fmts.add('presentation', 'vor5', 'vor', 'StarDraw 5.0 Template (OpenOffice.org Impress)', 'StarDraw 5.0 Vorlage (StarImpress)') ### 2
+fmts.add('presentation', 'wmf', 'wmf', 'Windows Metafile', 'impress_wmf_Export') ### 11
+fmts.add('presentation', 'xhtml', 'xml', 'XHTML', 'XHTML Impress File') ### 33
+fmts.add('presentation', 'xpm', 'xpm', 'X PixMap', 'impress_xpm_Export') ### 10
+
+class Options:
+    def __init__(self, args):
+        self.connection = None
+        self.debug = False
+        self.doctype = None
+        self.exportfilter = []
+        self.exportfilteroptions = ""
+        self.filenames = []
+        self.format = None
+        self.importfilter = []
+        self.importfilteroptions = ""
+        self.listener = False
+        self.nolaunch = False
+        self.output = None
+        self.password = None
+        self.pipe = None
+        self.port = '2002'
+        self.server = '127.0.0.1'
+        self.showlist = False
+        self.stdout = False
+        self.template = None
+        self.timeout = 6
+        self.verbose = 0
+
+        ### Get options from the commandline
+        try:
+            opts, args = getopt.getopt (args, 'c:Dd:e:f:hi:Llo:np:s:T:t:vV',
+                ['connection=', 'debug', 'doctype=', 'export=', 'format=',
+                 'help', 'import', 'listener', 'no-launch', 'output=',
+                 'outputpath', 'password=', 'pipe=', 'port=', 'server=',
+                 'timeout=', 'show', 'stdout', 'template', 'verbose',
+                 'version'] )
+        except getopt.error as exc:
+            print('unoconv: %s, try unoconv -h for a list of all the options' % str(exc))
+            sys.exit(255)
+
+        for opt, arg in opts:
+            if opt in ['-h', '--help']:
+                self.usage()
+                print()
+                self.help()
+                sys.exit(1)
+            elif opt in ['-c', '--connection']:
+                self.connection = arg
+            elif opt in ['--debug']:
+                self.debug = True
+            elif opt in ['-d', '--doctype']:
+                self.doctype = arg
+            elif opt in ['-e', '--export']:
+                l = arg.split('=')
+                if len(l) == 2:
+                    (name, value) = l
+                    if name in ('FilterOptions'):
+                        self.exportfilteroptions = value
+                    elif value in ('True', 'true'):
+                        self.exportfilter.append( UnoPropertyValue( name, 0, True, 0 ) )
+                    elif value in ('False', 'false'):
+                        self.exportfilter.append( UnoPropertyValue( name, 0, False, 0 ) )
+                    else:
+                        try:
+                            self.exportfilter.append( UnoPropertyValue( name, 0, int(value), 0 ) )
+                        except ValueError:
+                            self.exportfilter.append( UnoPropertyValue( name, 0, value, 0 ) )
+                else:
+                    print('Warning: Option %s cannot be parsed, ignoring.' % arg, file=sys.stderr)
+            elif opt in ['-f', '--format']:
+                self.format = arg
+            elif opt in ['-i', '--import']:
+                l = arg.split('=')
+                if len(l) == 2:
+                    (name, value) = l
+                    if name in ('FilterOptions'):
+                        self.importfilteroptions = value
+                    elif value in ('True', 'true'):
+                        self.importfilter.append( UnoPropertyValue( name, 0, True, 0 ) )
+                    elif value in ('False', 'false'):
+                        self.importfilter.append( UnoPropertyValue( name, 0, False, 0 ) )
+                    else:
+                        try:
+                            self.importfilter.append( UnoPropertyValue( name, 0, int(value), 0 ) )
+                        except ValueError:
+                            self.importfilter.append( UnoPropertyValue( name, 0, value, 0 ) )
+                else:
+                    print('Warning: Option %s cannot be parsed, ignoring.' % arg, file=sys.stderr)
+            elif opt in ['-l', '--listener']:
+                self.listener = True
+            elif opt in ['-n', '--no-launch']:
+                self.nolaunch = True
+            elif opt in ['-o', '--output']:
+                self.output = arg
+            elif opt in ['--outputpath']:
+                print('Warning: This option is deprecated by --output.', file=sys.stderr)
+                self.output = arg
+            elif opt in ['--password']:
+                self.password = arg
+            elif opt in ['--pipe']:
+                self.pipe = arg
+            elif opt in ['-p', '--port']:
+                self.port = arg
+            elif opt in ['-s', '--server']:
+                self.server = arg
+            elif opt in ['--show']:
+                self.showlist = True
+            elif opt in ['--stdout']:
+                self.stdout = True
+            elif opt in ['-t', '--template']:
+                self.template = arg
+            elif opt in ['-T', '--timeout']:
+                self.timeout = int(arg)
+            elif opt in ['-v', '--verbose']:
+                self.verbose = self.verbose + 1
+            elif opt in ['-V', '--version']:
+                self.version()
+                sys.exit(255)
+
+        ### Enable verbosity
+        if self.verbose >= 2:
+            print('Verbosity set to level %d' % self.verbose, file=sys.stderr)
+
+        self.filenames = args
+
+        if not self.listener and not self.showlist and self.doctype != 'list' and not self.filenames:
+            print('unoconv: you have to provide a filename as argument', file=sys.stderr)
+            print('Try `unoconv -h\' for more information.', file=sys.stderr)
+            sys.exit(255)
+
+        ### Set connection string
+        if not self.connection:
+            if not self.pipe:
+                self.connection = "socket,host=%s,port=%s;urp;StarOffice.ComponentContext" % (self.server, self.port)
+#               self.connection = "socket,host=%s,port=%s;urp;" % (self.server, self.port)
+            else:
+                self.connection = "pipe,name=%s;urp;StarOffice.ComponentContext" % (self.pipe)
+
+        ### Make it easier for people to use a doctype (first letter is enough)
+        if self.doctype:
+            for doctype in doctypes:
+                if doctype.startswith(self.doctype):
+                    self.doctype = doctype
+
+        ### Check if the user request to see the list of formats
+        if self.showlist or self.format == 'list':
+            if self.doctype:
+                fmts.display(self.doctype)
+            else:
+                for t in doctypes:
+                    fmts.display(t)
+            sys.exit(0)
+
+        ### If no format was specified, probe it or provide it
+        if not self.format:
+            l = sys.argv[0].split('2')
+            if len(l) == 2:
+                self.format = l[1]
+            else:
+                self.format = 'pdf'
+
+    def version(self):
+        ### Get office product information
+        product = global_uno.getComponentContext().ServiceManager.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", GlobalUnoProps(nodepath="/org.openoffice.Setup/Product"))
+
+        print('unoconv %s' % VERSION)
+        print('Written by Dag Wieers <dag@wieers.com>')
+        print('Homepage at http://dag.wieers.com/home-made/unoconv/')
+        print()
+        print('platform %s/%s' % (os.name, sys.platform))
+        print('python %s' % sys.version)
+        print(product.ooName, product.ooSetupVersion)
+#        print
+#        print 'build revision $Rev$'
+
+    def usage(self):
+        print('usage: unoconv [options] file [file2 ..]', file=sys.stderr)
+
+    def help(self):
+        print('''Convert from and to any format supported by LibreOffice
+
+unoconv options:
+  -c, --connection=string  use a custom connection string
+  -d, --doctype=type       specify document type
+                             (document, graphics, presentation, spreadsheet)
+  -e, --export=name=value  set export filter options
+                             eg. -e PageRange=1-2
+  -f, --format=format      specify the output format
+  -i, --import=string      set import filter option string
+                             eg. -i utf8
+  -l, --listener           start a permanent listener to use by unoconv clients
+  -n, --no-launch          fail if no listener is found (default: launch one)
+  -o, --output=name        output basename, filename or directory
+      --pipe=name          alternative method of connection using a pipe
+  -p, --port=port          specify the port (default: 2002)
+                             to be used by client or listener
+      --password=string    provide a password to decrypt the document
+  -s, --server=server      specify the server address (default: 127.0.0.1)
+                             to be used by client or listener
+      --show               list the available output formats
+      --stdout             write output to stdout
+  -t, --template=file      import the styles from template (.ott)
+  -T, --timeout=secs       timeout after secs if connection to listener fails
+  -v, --verbose            be more and more verbose (-vvv for debugging)
+''', file=sys.stderr)
+
+class Convertor:
+    def __init__(self):
+        global exitcode, ooproc, office, product
+        unocontext = None
+
+        ### Do the LibreOffice component dance
+        self.context = global_uno.getComponentContext()
+        self.svcmgr = self.context.ServiceManager
+        resolver = self.svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", self.context)
+
+        ### Test for an existing connection
+        info(3, 'Connection type: %s' % op.connection)
+        try:
+            unocontext = resolver.resolve("uno:%s" % op.connection)
+        except UnoNoConnectException as e:
+#            info(3, "Existing listener not found.\n%s" % e)
+            info(3, "Existing listener not found.")
+
+            if op.nolaunch:
+                die(113, "Existing listener not found. Unable start listener by parameters. Aborting.")
+
+            ### Start our own OpenOffice instance
+            info(3, "Launching our own listener using %s." % office.binary)
+            try:
+                product = self.svcmgr.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", GlobalUnoProps(nodepath="/org.openoffice.Setup/Product"))
+                if product.ooName != "LibreOffice" or LooseVersion(product.ooSetupVersion) <= LooseVersion('3.3'):
+                    ooproc = subprocess.Popen([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nofirststartwizard", "-nologo", "-norestore", "-accept=%s" % op.connection], env=os.environ)
+                else:
+                    ooproc = subprocess.Popen([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nofirststartwizard", "--nologo", "--norestore", "--accept=%s" % op.connection], env=os.environ)
+                info(2, '%s listener successfully started. (pid=%s)' % (product.ooName, ooproc.pid))
+
+                ### Try connection to it for op.timeout seconds (flakky OpenOffice)
+                timeout = 0
+                while timeout <= op.timeout:
+                    ### Is it already/still running ?
+                    retcode = ooproc.poll()
+                    if retcode != None:
+                        info(3, "Process %s (pid=%s) exited with %s." % (office.binary, ooproc.pid, retcode))
+                        break
+                    try:
+                        unocontext = resolver.resolve("uno:%s" % op.connection)
+                        break
+                    except UnoNoConnectException:
+                        time.sleep(0.5)
+                        timeout += 0.5
+                    except:
+                        raise
+                else:
+                    error("Failed to connect to %s (pid=%s) in %d seconds.\n%s" % (office.binary, ooproc.pid, op.timeout, e))
+            except Exception as e:
+                raise
+                error("Launch of %s failed.\n%s" % (office.binary, e))
+
+        if not unocontext:
+            die(251, "Unable to connect or start own listener. Aborting.")
+
+        ### And some more LibreOffice magic
+        unosvcmgr = unocontext.ServiceManager
+        self.desktop = unosvcmgr.createInstanceWithContext("com.sun.star.frame.Desktop", unocontext)
+        self.cwd = global_unohelper.systemPathToFileUrl( os.getcwd() )
+
+        ### List all filters
+#        self.filters = unosvcmgr.createInstanceWithContext( "com.sun.star.document.FilterFactory", unocontext)
+#        for filter in self.filters.getElementNames():
+#            print filter
+#            #print dir(filter), dir(filter.format)
+
+    def getformat(self, inputfn):
+        doctype = None
+
+        ### Get the output format from mapping
+        if op.doctype:
+            outputfmt = fmts.bydoctype(op.doctype, op.format)
+        else:
+            outputfmt = fmts.byname(op.format)
+
+            if not outputfmt:
+                outputfmt = fmts.byextension(os.extsep + op.format)
+
+        ### If no doctype given, check list of acceptable formats for input file ext doctype
+        ### FIXME: This should go into the for-loop to match each individual input filename
+        if outputfmt:
+            inputext = os.path.splitext(inputfn)[1]
+            inputfmt = fmts.byextension(inputext)
+            if inputfmt:
+                for fmt in outputfmt:
+                    if inputfmt[0].doctype == fmt.doctype:
+                        doctype = inputfmt[0].doctype
+                        outputfmt = fmt
+                        break
+                else:
+                    outputfmt = outputfmt[0]
+    #       print >>sys.stderr, 'unoconv: format `%s\' is part of multiple doctypes %s, selecting `%s\'.' % (format, [fmt.doctype for fmt in outputfmt], outputfmt[0].doctype)
+            else:
+                outputfmt = outputfmt[0]
+
+        ### No format found, throw error
+        if not outputfmt:
+            if doctype:
+                print('unoconv: format [%s/%s] is not known to unoconv.' % (op.doctype, op.format), file=sys.stderr)
+            else:
+                print('unoconv: format [%s] is not known to unoconv.' % op.format, file=sys.stderr)
+            die(1)
+
+        return outputfmt
+
+    def convert(self, inputfn):
+        global exitcode
+
+        document = None
+        outputfmt = self.getformat(inputfn)
+
+        if op.verbose > 0:
+            print('Input file:', inputfn, file=sys.stderr)
+
+        if not os.path.exists(inputfn):
+            print('unoconv: file `%s\' does not exist.' % inputfn, file=sys.stderr)
+            exitcode = 1
+
+        try:
+            ### Import phase
+            phase = "import"
+
+            ### Load inputfile
+            inputprops = GlobalUnoProps(Hidden=True, ReadOnly=True, UpdateDocMode=UNO_QUIET_UPDATE)
+
+#            if op.password:
+#                info = GlobalUnoProps(algorithm-name="PBKDF2", salt="salt", iteration-count=1024, hash="hash")
+#                inputprops += GlobalUnoProps(ModifyPasswordInfo=info)
+
+            ### Cannot use GlobalUnoProps for FilterData property
+            if op.importfilteroptions:
+#                print "Import filter options: %s" % op.importfilteroptions
+                inputprops += GlobalUnoProps(FilterOptions=op.importfilteroptions)
+
+            ### Cannot use GlobalUnoProps for FilterData property
+            if op.importfilter:
+                inputprops += ( UnoPropertyValue( "FilterData", 0, global_uno.Any("[]com.sun.star.beans.PropertyValue", tuple( op.importfilter ), ), 0 ), )
+
+            inputurl = global_unohelper.absolutize(self.cwd, global_unohelper.systemPathToFileUrl(inputfn))
+            document = self.desktop.loadComponentFromURL( inputurl , "_blank", 0, inputprops )
+
+            if not document:
+                raise UnoException("The document '%s' could not be opened." % inputurl, None)
+
+            ### Import style template
+            phase = "import-style"
+            if op.template:
+                if os.path.exists(op.template):
+                    info(1, "Template file: %s" % op.template)
+                    templateprops = GlobalUnoProps(OverwriteStyles=True)
+                    templateurl = global_unohelper.absolutize(self.cwd, global_unohelper.systemPathToFileUrl(op.template))
+                    document.StyleFamilies.loadStylesFromURL(templateurl, templateprops)
+                else:
+                    print('unoconv: template file `%s\' does not exist.' % op.template, file=sys.stderr)
+                    exitcode = 1
+
+            ### Update document links
+            phase = "update-links"
+            try:
+                document.updateLinks()
+            except AttributeError:
+                # the document doesn't implement the XLinkUpdate interface
+                pass
+
+            ### Update document indexes
+            phase = "update-indexes"
+            try:
+                document.refresh()
+                indexes = document.getDocumentIndexes()
+            except AttributeError:
+                # the document doesn't implement the XRefreshable and/or
+                # XDocumentIndexesSupplier interfaces
+                pass
+            else:
+                for i in range(0, indexes.getCount()):
+                    indexes.getByIndex(i).update()
+
+            info(1, "Selected output format: %s" % outputfmt)
+            info(2, "Selected office filter: %s" % outputfmt.filter)
+            info(2, "Used doctype: %s" % outputfmt.doctype)
+
+            ### Export phase
+            phase = "export"
+
+            outputprops = GlobalUnoProps(FilterName=outputfmt.filter, OutputStream=GlobalOutputStream(), Overwrite=True)
+
+            ### Set default filter options
+            if op.exportfilteroptions:
+#                print "Export filter options: %s" % op.exportfilteroptions
+                outputprops += GlobalUnoProps(FilterOptions=op.exportfilteroptions)
+            else:
+                if outputfmt.filter == 'Text (encoded)':
+                    outputprops += GlobalUnoProps(FilterOptions="76,LF")
+
+                elif outputfmt.filter == 'Text':
+                    outputprops += GlobalUnoProps(FilterOptions="76")
+
+                elif outputfmt.filter == 'Text - txt - csv (StarCalc)':
+                    outputprops += GlobalUnoProps(FilterOptions="44,34,76")
+
+
+            ### Cannot use GlobalUnoProps for FilterData property
+            if op.exportfilter:
+                outputprops += ( UnoPropertyValue( "FilterData", 0, global_uno.Any("[]com.sun.star.beans.PropertyValue", tuple( op.exportfilter ), ), 0 ), )
+
+            if not op.stdout:
+                (outputfn, ext) = os.path.splitext(inputfn)
+                if not op.output:
+                    outputfn = outputfn + os.extsep + outputfmt.extension
+                elif os.path.isdir(op.output):
+                    outputfn = realpath(op.output, os.path.basename(outputfn) + os.extsep + outputfmt.extension)
+                elif len(op.filenames) > 1:
+                    outputfn = op.output + os.extsep + outputfmt.extension
+                else:
+                    outputfn = op.output
+
+                outputurl = global_unohelper.absolutize( self.cwd, global_unohelper.systemPathToFileUrl(outputfn) )
+                info(1, "Output file: %s" % outputfn)
+            else:
+                outputurl = "private:stream"
+
+            try:
+                document.storeToURL(outputurl, tuple(outputprops) )
+            except UnoIOException as e:
+                raise UnoException("Unable to store document to %s (ErrCode %d)\n\nProperties: %s" % (outputurl, e.ErrCode, outputprops), None)
+
+            phase = "dispose"
+            document.dispose()
+            document.close(True)
+
+        except SystemError as e:
+            error("unoconv: SystemError during %s phase:\n%s" % (phase, e))
+            exitcode = 1
+
+        except UnoRuntimeException as e:
+            error("unoconv: RuntimeException during %s phase:\nOffice probably died. %s" % (phase, e))
+            exitcode = 6
+
+        except UnoDisposedException as e:
+            error("unoconv: DisposedException during %s phase:\nOffice probably died. %s" % (phase, e))
+            exitcode = 7
+
+        except UnoIllegalArgumentException as e:
+            error("UNO IllegalArgument during %s phase:\nSource file cannot be read. %s" % (phase, e))
+            exitcode = 8
+
+        except UnoIOException as e:
+#            for attr in dir(e): print '%s: %s', (attr, getattr(e, attr))
+            error("unoconv: IOException during %s phase:\n%s" % (phase, e.Message))
+            exitcode = 3
+
+        except UnoCannotConvertException as e:
+#            for attr in dir(e): print '%s: %s', (attr, getattr(e, attr))
+            error("unoconv: CannotConvertException during %s phase:\n%s" % (phase, e.Message))
+            exitcode = 4
+
+        except UnoException as e:
+            if hasattr(e, 'ErrCode'):
+                error("unoconv: UnoException during %s phase in %s (ErrCode %d)" % (phase, repr(e.__class__), e.ErrCode))
+                exitcode = e.ErrCode
+                pass
+            if hasattr(e, 'Message'):
+                error("unoconv: UnoException during %s phase:\n%s" % (phase, e.Message))
+                exitcode = 5
+            else:
+                error("unoconv: UnoException during %s phase in %s" % (phase, repr(e.__class__)))
+                exitcode = 2
+                pass
+
+class Listener:
+    def __init__(self):
+        global product
+
+        info(1, "Start listener on %s:%s" % (op.server, op.port))
+        self.context = global_uno.getComponentContext()
+        self.svcmgr = self.context.ServiceManager
+        try:
+            resolver = self.svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", self.context)
+            product = self.svcmgr.createInstance("com.sun.star.configuration.ConfigurationProvider").createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", GlobalUnoProps(nodepath="/org.openoffice.Setup/Product"))
+            try:
+                unocontext = resolver.resolve("uno:%s" % op.connection)
+            except UnoNoConnectException as e:
+                pass
+            else:
+                info(1, "Existing %s listener found, nothing to do." % product.ooName)
+                return
+            if product.ooName != "LibreOffice" or LooseVersion(product.ooSetupVersion) <= LooseVersion('3.3'):
+                subprocess.call([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nologo", "-nofirststartwizard", "-norestore", "-accept=%s" % op.connection], env=os.environ)
+            else:
+                subprocess.call([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nologo", "--nofirststartwizard", "--norestore", "--accept=%s" % op.connection], env=os.environ)
+        except Exception as e:
+            error("Launch of %s failed.\n%s" % (office.binary, e))
+        else:
+            info(1, "Existing %s listener found, nothing to do." % product.ooName)
+
+def error(msg):
+    "Output error message"
+    print(msg, file=sys.stderr)
+
+def info(level, msg):
+    "Output info message"
+    if 'op' not in globals():
+        pass
+    elif op.verbose >= 3 and level >= 3:
+        print("DEBUG:", msg, file=sys.stderr)
+    elif not op.stdout and level <= op.verbose:
+        print(msg, file=sys.stdout)
+    elif level <= op.verbose:
+        print(msg, file=sys.stderr)
+
+def die(ret, msg=None):
+    "Print optional error and exit with errorcode"
+    global convertor, ooproc, office
+
+    if msg:
+        error('Error: %s' % msg)
+
+    ### Did we start our own listener instance ?
+    if not op.listener and ooproc and convertor:
+
+        ### If there is a GUI now attached to the instance, disable listener
+        if convertor.desktop.getCurrentFrame():
+            info(2, 'Trying to stop %s GUI listener.' % product.ooName)
+            try:
+                if product.ooName != "LibreOffice" or product.ooSetupVersion <= 3.3:
+                    subprocess.Popen([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nofirststartwizard", "-nologo", "-norestore", "-unaccept=%s" % op.connection], env=os.environ)
+                else:
+                    subprocess.Popen([office.binary, "--headless", "--invisible", "--nocrashreport", "--nodefault", "--nofirststartwizard", "--nologo", "--norestore", "--unaccept=%s" % op.connection], env=os.environ)
+                ooproc.wait()
+                info(2, '%s listener successfully disabled.' % product.ooName)
+            except Exception as e:
+                error("Terminate using %s failed.\n%s" % (office.binary, e))
+
+        ### If there is no GUI attached to the instance, terminate instance
+        else:
+            info(3, 'Terminating %s instance.' % product.ooName)
+            try:
+                convertor.desktop.terminate()
+            except UnoDisposedException:
+                info(2, '%s instance unsuccessfully closed, sending TERM signal.' % product.ooName)
+                try:
+                    ooproc.terminate()
+                except AttributeError:
+                    os.kill(ooproc.pid, 15)
+            info(3, 'Waiting for %s instance to exit.' % product.ooName)
+            ooproc.wait()
+
+        ### LibreOffice processes may get stuck and we have to kill them
+        ### Is it still running ?
+        if ooproc.poll() == None:
+            info(1, '%s instance still running, please investigate...' % product.ooName)
+            ooproc.wait()
+            info(2, '%s instance unsuccessfully terminated, sending KILL signal.' % product.ooName)
+            try:
+                ooproc.kill()
+            except AttributeError:
+                os.kill(ooproc.pid, 9)
+            info(3, 'Waiting for %s with pid %s to disappear.' % (ooproc.pid, product.ooName))
+            ooproc.wait()
+
+    # allow Python GC to garbage collect pyuno object *before* exit call
+    # which avoids random segmentation faults --vpa
+    convertor = None
+
+    sys.exit(ret)
+
+def main():
+    global convertor, exitcode
+    convertor = None
+
+    try:
+        if op.listener:
+            listener = Listener()
+
+        if op.filenames:
+            convertor = Convertor()
+            for inputfn in op.filenames:
+                convertor.convert(inputfn)
+
+    except UnoNoConnectException as e:
+        error("unoconv: could not find an existing connection to LibreOffice at %s:%s." % (op.server, op.port))
+        if op.connection:
+            info(0, "Please start an LibreOffice instance on server '%s' by doing:\n\n    unoconv --listener --server %s --port %s\n\nor alternatively:\n\n    soffice -nologo -nodefault -accept=\"%s\"" % (op.server, op.server, op.port, op.connection))
+        else:
+            info(0, "Please start an LibreOffice instance on server '%s' by doing:\n\n    unoconv --listener --server %s --port %s\n\nor alternatively:\n\n    soffice -nologo -nodefault -accept=\"socket,host=%s,port=%s;urp;\"" % (op.server, op.server, op.port, op.server, op.port))
+            info(0, "Please start an soffice instance on server '%s' by doing:\n\n    soffice -nologo -nodefault -accept=\"socket,host=127.0.0.1,port=%s;urp;\"" % (op.server, op.port))
+        exitcode = 1
+#    except UnboundLocalError:
+#        die(252, "Failed to connect to remote listener.")
+    except OSError:
+        error("Warning: failed to launch Office suite. Aborting.")
+
+### Main entrance
+def run():
+    global exitcode
+    exitcode = 0
+
+    info(3, 'sysname=%s, platform=%s, python=%s, python-version=%s' % (os.name, sys.platform, sys.executable, sys.version))
+
+    for of in find_offices():
+        if of.python != sys.executable and not sys.executable.startswith(of.basepath):
+            python_switch(of)
+        office_environ(of)
+#        debug_office()
+        try:
+            global global_uno
+            global global_unohelper
+
+            import uno as global_uno
+            import unohelper as global_unohelper
+            global office
+            office = of
+            break
+        except:
+#            debug_office()
+            print("unoconv: Cannot find a suitable pyuno library and python binary combination in %s" % of, file=sys.stderr)
+            print("ERROR:", sys.exc_info()[1], file=sys.stderr)
+            print(file=sys.stderr)
+    else:
+#        debug_office()
+        print("unoconv: Cannot find a suitable office installation on your system.", file=sys.stderr)
+        print("ERROR: Please locate your office installation and send your feedback to:", file=sys.stderr)
+        print("       http://github.com/dagwieers/unoconv/issues", file=sys.stderr)
+        sys.exit(1)
+
+    ### Now that we have found a working pyuno library, let's import some classes
+    global UnoPropertyValue
+    global UnoNoConnectException
+    global UNO_QUIET_UPDATE
+    global UnoDisposedException
+    global UnoIllegalArgumentException
+    global UnoIOException
+    global UnoXOutputStream
+    global UnoCannotConvertException
+    global UnoException
+    global UnoRuntimeException
+
+    from com.sun.star.beans import PropertyValue as UnoPropertyValue
+    from com.sun.star.connection import NoConnectException as UnoNoConnectException
+    from com.sun.star.document.UpdateDocMode import QUIET_UPDATE as UNO_QUIET_UPDATE
+    from com.sun.star.lang import DisposedException as UnoDisposedException
+    from com.sun.star.lang import IllegalArgumentException as UnoIllegalArgumentException
+    from com.sun.star.io import IOException as UnoIOException
+    from com.sun.star.io import XOutputStream as UnoXOutputStream
+    from com.sun.star.script import CannotConvertException as UnoCannotConvertException
+    from com.sun.star.uno import Exception as UnoException
+    from com.sun.star.uno import RuntimeException as UnoRuntimeException
+
+    ### And now that we have those classes, build on them
+    class OutputStream( global_unohelper.Base, UnoXOutputStream ):
+        def __init__( self ):
+            self.closed = 0
+
+        def closeOutput(self):
+            self.closed = 1
+
+        def writeBytes( self, seq ):
+            sys.stdout.write( seq.value )
+
+        def flush( self ):
+            pass
+
+    global GlobalOutputStream
+    GlobalOutputStream = OutputStream
+
+    def UnoProps(**args):
+        props = []
+        for key in args:
+            prop = UnoPropertyValue()
+            prop.Name = key
+            prop.Value = args[key]
+            props.append(prop)
+        return tuple(props)
+
+    global GlobalUnoProps
+    GlobalUnoProps = UnoProps
+
+    global op
+    op = Options(sys.argv[1:])
+
+    info(2, "Using office base path: %s" % office.basepath)
+    info(2, "Using office binary path: %s" % office.unopath)
+
+    try:
+        main()
+    except KeyboardInterrupt as e:
+        die(6, 'Exiting on user request')
+    die(exitcode)
+
+if __name__ == '__main__':
+    run()
-- 
1.7.11.7