~ubuntu-branches/ubuntu/precise/unoconv/precise

« back to all changes in this revision

Viewing changes to unoconv

  • Committer: Bazaar Package Importer
  • Author(s): Vincent Bernat
  • Date: 2007-11-17 11:38:42 UTC
  • Revision ID: james.westby@ubuntu.com-20071117113842-xjxqf59n012r5trb
Tags: upstream-0.3
ImportĀ upstreamĀ versionĀ 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
### This program is free software; you can redistribute it and/or modify
 
4
### it under the terms of the GNU Library General Public License as published by
 
5
### the Free Software Foundation; version 2 only
 
6
###
 
7
### This program is distributed in the hope that it will be useful,
 
8
### but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
### GNU Library General Public License for more details.
 
11
###
 
12
### You should have received a copy of the GNU Library General Public License
 
13
### along with this program; if not, write to the Free Software
 
14
### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
15
### Copyright 2007 Dag Wieers <dag@wieers.com>
 
16
 
 
17
import getopt, sys, os, glob, time
 
18
 
 
19
#extrapaths = ('/usr/lib/openoffice/program/', '/usr/lib/openoffice.org2.0/program/')
 
20
extrapaths = glob.glob('/usr/lib*/openoffice*/program/') + glob.glob('/usr/lib*/ooo*/program') + [ '/Applications/NeoOffice.app/Contents/program', ]
 
21
for path in extrapaths:
 
22
    try:
 
23
        sys.path.append(path)   
 
24
        import uno, unohelper
 
25
        os.environ['PATH'] = '%s:' % path + os.environ['PATH']
 
26
        break
 
27
    except ImportError:
 
28
        sys.path.remove(path)
 
29
        continue
 
30
else:
 
31
    print >>sys.stderr, "unoconv: Cannot find the pyuno.so library in sys.path and known paths."
 
32
    print >>sys.stderr, "Please locate this library and send your feedback to <tools@lists.rpmforge.net>."
 
33
    sys.exit(1)
 
34
 
 
35
from com.sun.star.beans import PropertyValue
 
36
from com.sun.star.connection import NoConnectException
 
37
from com.sun.star.io import IOException, XOutputStream
 
38
from com.sun.star.script import CannotConvertException
 
39
from com.sun.star.uno import Exception as UnoException
 
40
 
 
41
__version__ = "$Revision$"
 
42
# $Source$
 
43
 
 
44
VERSION = '0.3'
 
45
 
 
46
doctypes = ('document', 'graphics', 'presentation', 'spreadsheet')
 
47
 
 
48
oopid = None
 
49
 
 
50
class Fmt:
 
51
    def __init__(self, doctype, name, extension, summary, filter):
 
52
        self.doctype = doctype
 
53
        self.name = name
 
54
        self.extension = extension
 
55
        self.summary = summary
 
56
        self.filter = filter
 
57
 
 
58
    def __str__(self):
 
59
        return "%s [.%s]" % (self.summary, self.extension)
 
60
 
 
61
    def __repr__(self):
 
62
        return "%s/%s" % (self.name, self.doctype)
 
63
 
 
64
class FmtList:
 
65
    def __init__(self):
 
66
        self.list = []
 
67
 
 
68
    def add(self, doctype, name, extension, summary, filter):
 
69
        self.list.append(Fmt(doctype, name, extension, summary, filter))
 
70
 
 
71
    def byname(self, name):
 
72
        ret = []
 
73
        for fmt in self.list:
 
74
            if fmt.name == name:
 
75
                ret.append(fmt)
 
76
        return ret
 
77
 
 
78
    def byextension(self, extension):
 
79
        ret = []
 
80
        for fmt in self.list:
 
81
            if '.'+fmt.extension == extension:
 
82
                ret.append(fmt)
 
83
        return ret
 
84
 
 
85
    def bydoctype(self, doctype, name):
 
86
        ret = []
 
87
        for fmt in self.list:
 
88
            if fmt.name == name and fmt.doctype == doctype:
 
89
                ret.append(fmt)
 
90
                return ret
 
91
 
 
92
    def display(self, doctype):
 
93
        print >>sys.stderr, "The following list of %s formats are currently available:\n" % doctype
 
94
        for fmt in self.list:
 
95
            if fmt.doctype == doctype:
 
96
                print >>sys.stderr, "  %-8s - %s" % (fmt.name, fmt)
 
97
        print >>sys.stderr
 
98
 
 
99
class OutputStream( unohelper.Base, XOutputStream ):
 
100
    def __init__( self ):
 
101
        self.closed = 0
 
102
 
 
103
    def closeOutput(self):
 
104
        self.closed = 1
 
105
 
 
106
    def writeBytes( self, seq ):
 
107
        sys.stdout.write( seq.value )
 
108
 
 
109
    def flush( self ):
 
110
        pass
 
111
 
 
112
fmts = FmtList()
 
113
 
 
114
### Document / Writer
 
115
fmts.add('document', 'bib', 'bib', 'BibTeX', 'BibTeX_Writer')
 
116
fmts.add('document', 'doc', 'doc', 'Microsoft Word 97/2000/XP', 'MS Word 97')
 
117
fmts.add('document', 'doc6', 'doc', 'Microsoft Word 6.0', 'MS WinWord 6.0')
 
118
fmts.add('document', 'doc95', 'doc', 'Microsoft Word 95', 'MS Word 95')
 
119
fmts.add('document', 'docbook', 'xml', 'DocBook', 'DocBook File')
 
120
fmts.add('document', 'html', 'html', 'HTML Document (OpenOffice.org Writer)', 'HTML (StarWriter)')
 
121
fmts.add('document', 'odt', 'odt', 'Open Document Text', 'writer8')
 
122
fmts.add('document', 'ott', 'ott', 'Open Document Text', 'writer8_template')
 
123
fmts.add('document', 'ooxml', 'xml', 'Microsoft Office Open XML', 'MS Word 2003 XML')
 
124
fmts.add('document', 'pdb', 'pdb', 'AportisDoc (Palm)', 'AportisDoc Palm DB')
 
125
fmts.add('document', 'pdf', 'pdf', 'Portable Document Format', 'writer_pdf_Export')
 
126
fmts.add('document', 'psw', 'psw', 'Pocket Word', 'PocketWord File')
 
127
fmts.add('document', 'rtf', 'rtf', 'Rich Text Format', 'Rich Text Format')
 
128
fmts.add('document', 'latex', 'ltx', 'LaTeX 2e', 'LaTeX_Writer')
 
129
fmts.add('document', 'sdw', 'sdw', 'StarWriter 5.0', 'StarWriter 5.0')
 
130
fmts.add('document', 'sdw4', 'sdw', 'StarWriter 4.0', 'StarWriter 4.0')
 
131
fmts.add('document', 'sdw3', 'sdw', 'StarWriter 3.0', 'StarWriter 3.0')
 
132
fmts.add('document', 'stw', 'stw', 'Open Office.org 1.0 Text Document Template', 'writer_StarOffice_XML_Writer_Template')
 
133
fmts.add('document', 'sxw', 'sxw', 'Open Office.org 1.0 Text Document', 'StarOffice XML (Writer)')
 
134
fmts.add('document', 'text', 'txt', 'Text Encoded', 'Text (encoded)')
 
135
fmts.add('document', 'txt', 'txt', 'Plain Text', 'Text')
 
136
fmts.add('document', 'vor', 'vor', 'StarWriter 5.0 Template', 'StarWriter 5.0 Vorlage/Template')
 
137
fmts.add('document', 'vor4', 'vor', 'StarWriter 4.0 Template', 'StarWriter 4.0 Vorlage/Template')
 
138
fmts.add('document', 'vor3', 'vor', 'StarWriter 3.0 Template', 'StarWriter 3.0 Vorlage/Template')
 
139
fmts.add('document', 'xhtml', 'html', 'XHTML Document', 'XHTML Writer File')
 
140
 
 
141
### Spreadsheet
 
142
fmts.add('spreadsheet', 'csv', 'csv', 'Text CSV', 'Text - txt - csv (StarCalc)')
 
143
fmts.add('spreadsheet', 'dbf', 'dbf', 'dBase', 'dBase')
 
144
fmts.add('spreadsheet', 'dif', 'dif', 'Data Interchange Format', 'DIF')
 
145
fmts.add('spreadsheet', 'html', 'html', 'HTML Document (OpenOffice.org Calc)', 'HTML (StarCalc)')
 
146
fmts.add('spreadsheet', 'ods', 'ods', 'Open Document Spreadsheet', 'calc8')
 
147
fmts.add('spreadsheet', 'ooxml', 'xml', 'Microsoft Excel 2003 XML', 'MS Excel 2003 XML')
 
148
fmts.add('spreadsheet', 'pdf', 'pdf', 'Portable Document Format', 'calc_pdf_Export')
 
149
fmts.add('spreadsheet', 'pts', 'pts', 'OpenDocument Spreadsheet Template', 'calc8_template')
 
150
fmts.add('spreadsheet', 'pxl', 'pxl', 'Pocket Excel', 'Pocket Excel')
 
151
fmts.add('spreadsheet', 'sdc', 'sdc', 'StarCalc 5.0', 'StarCalc 5.0')
 
152
fmts.add('spreadsheet', 'sdc4', 'sdc', 'StarCalc 4.0', 'StarCalc 4.0')
 
153
fmts.add('spreadsheet', 'sdc3', 'sdc', 'StarCalc 3.0', 'StarCalc 3.0')
 
154
fmts.add('spreadsheet', 'slk', 'slk', 'SYLK', 'SYLK')
 
155
fmts.add('spreadsheet', 'stc', 'stc', 'OpenOffice.org 1.0 Spreadsheet Template', 'calc_StarOffice_XML_Calc_Template')
 
156
fmts.add('spreadsheet', 'sxc', 'sxc', 'OpenOffice.org 1.0 Spreadsheet', 'StarOffice XML (Calc)')
 
157
fmts.add('spreadsheet', 'vor3', 'vor', 'StarCalc 3.0 Template', 'StarCalc 3.0 Vorlage/Template')
 
158
fmts.add('spreadsheet', 'vor4', 'vor', 'StarCalc 4.0 Template', 'StarCalc 4.0 Vorlage/Template')
 
159
fmts.add('spreadsheet', 'vor', 'vor', 'StarCalc 5.0 Template', 'StarCalc 5.0 Vorlage/Template')
 
160
fmts.add('spreadsheet', 'xhtml', 'xhtml', 'XHTML', 'XHTML Calc File')
 
161
fmts.add('spreadsheet', 'xls', 'xls', 'Microsoft Excel 97/2000/XP', 'MS Excel 97')
 
162
fmts.add('spreadsheet', 'xls5', 'xls', 'Microsoft Excel 5.0', 'MS Excel 5.0/95')
 
163
fmts.add('spreadsheet', 'xls95', 'xls', 'Microsoft Excel 95', 'MS Excel 95')
 
164
fmts.add('spreadsheet', 'xlt', 'xlt', 'Microsoft Excel 97/2000/XP Template', 'MS Excel 97 Vorlage/Template')
 
165
fmts.add('spreadsheet', 'xlt5', 'xlt', 'Microsoft Excel 5.0 Template', 'MS Excel 5.0/95 Vorlage/Template')
 
166
fmts.add('spreadsheet', 'xlt95', 'xlt', 'Microsoft Excel 95 Template', 'MS Excel 95 Vorlage/Template')
 
167
 
 
168
### Graphics
 
169
fmts.add('graphics', 'bmp', 'bmp', 'Windows Bitmap', 'draw_bmp_Export')
 
170
fmts.add('graphics', 'emf', 'emf', 'Enhanced Metafile', 'draw_emf_Export')
 
171
fmts.add('graphics', 'eps', 'eps', 'Encapsulated PostScript', 'draw_eps_Export')
 
172
fmts.add('graphics', 'gif', 'gif', 'Graphics Interchange Format', 'draw_gif_Export')
 
173
fmts.add('graphics', 'html', 'html', 'HTML Document (OpenOffice.org Draw)', 'draw_html_Export')
 
174
fmts.add('graphics', 'jpg', 'jpg', 'Joint Photographic Experts Group', 'draw_jpg_Export')
 
175
fmts.add('graphics', 'met', 'met', 'OS/2 Metafile', 'draw_met_Export')
 
176
fmts.add('graphics', 'odd', 'odd', 'OpenDocument Drawing', 'draw8')
 
177
fmts.add('graphics', 'otg', 'otg', 'OpenDocument Drawing Template', 'draw8_template')
 
178
fmts.add('graphics', 'pbm', 'pbm', 'Portable Bitmap', 'draw_pbm_Export')
 
179
fmts.add('graphics', 'pct', 'pct', 'Mac Pict', 'draw_pct_Export')
 
180
fmts.add('graphics', 'pdf', 'pdf', 'Portable Document Format', 'draw_pdf_Export')
 
181
fmts.add('graphics', 'pgm', 'pgm', 'Portable Graymap', 'draw_pgm_Export')
 
182
fmts.add('graphics', 'png', 'png', 'Portable Network Graphic', 'draw_png_Export')
 
183
fmts.add('graphics', 'ppm', 'ppm', 'Portable Pixelmap', 'draw_ppm_Export')
 
184
fmts.add('graphics', 'ras', 'ras', 'Sun Raster Image', 'draw_ras_Export')
 
185
fmts.add('graphics', 'std', 'std', 'OpenOffice.org 1.0 Drawing Template', 'draw_StarOffice_XML_Draw_Template')
 
186
fmts.add('graphics', 'svg', 'svg', 'Scalable Vector Graphics', 'draw_svg_Export')
 
187
fmts.add('graphics', 'svm', 'svm', 'StarView Metafile', 'draw_svm_Export')
 
188
fmts.add('graphics', 'swf', 'swf', 'Macromedia Flash (SWF)', 'draw_flash_Export')
 
189
fmts.add('graphics', 'sxd', 'sxd', 'OpenOffice.org 1.0 Drawing', 'StarOffice XML (Draw)')
 
190
fmts.add('graphics', 'sxd3', 'sxd', 'StarDraw 3.0', 'StarDraw 3.0')
 
191
fmts.add('graphics', 'sxd5', 'sxd', 'StarDraw 5.0', 'StarDraw 5.0')
 
192
fmts.add('graphics', 'tiff', 'tiff', 'Tagged Image File Format', 'draw_tif_Export')
 
193
fmts.add('graphics', 'vor', 'vor', 'StarDraw 5.0 Template', 'StarDraw 5.0 Vorlage')
 
194
fmts.add('graphics', 'vor3', 'vor', 'StarDraw 3.0 Template', 'StarDraw 3.0 Vorlage')
 
195
fmts.add('graphics', 'wmf', 'wmf', 'Windows Metafile', 'draw_wmf_Export')
 
196
fmts.add('graphics', 'xhtml', 'xhtml', 'XHTML', 'XHTML Draw File')
 
197
fmts.add('graphics', 'xpm', 'xpm', 'X PixMap', 'draw_xpm_Export')
 
198
 
 
199
### Presentation
 
200
fmts.add('presentation', 'bmp', 'bmp', 'Windows Bitmap', 'impress_bmp_Export')
 
201
fmts.add('presentation', 'emf', 'emf', 'Enhanced Metafile', 'impress_emf_Export')
 
202
fmts.add('presentation', 'eps', 'eps', 'Encapsulated PostScript', 'impress_eps_Export')
 
203
fmts.add('presentation', 'gif', 'gif', 'Graphics Interchange Format', 'impress_gif_Export')
 
204
fmts.add('presentation', 'html', 'html', 'HTML Document (OpenOffice.org Impress)', 'impress_html_Export')
 
205
fmts.add('presentation', 'jpg', 'jpg', 'Joint Photographic Experts Group', 'impress_jpg_Export')
 
206
fmts.add('presentation', 'met', 'met', 'OS/2 Metafile', 'impress_met_Export')
 
207
fmts.add('presentation', 'odd', 'odd', 'OpenDocument Drawing (Impress)', 'impress8_draw')
 
208
fmts.add('presentation', 'odg', 'odg', 'OpenOffice.org 1.0 Drawing (OpenOffice.org Impress)', 'impress_StarOffice_XML_Draw')
 
209
fmts.add('presentation', 'odp', 'odp', 'OpenDocument Presentation', 'impress8')
 
210
fmts.add('presentation', 'pbm', 'pbm', 'Portable Bitmap', 'impress_pbm_Export')
 
211
fmts.add('presentation', 'pct', 'pct', 'Mac Pict', 'impress_pct_Export')
 
212
fmts.add('presentation', 'pdf', 'pdf', 'Portable Document Format', 'impress_pdf_Export')
 
213
fmts.add('presentation', 'pgm', 'pgm', 'Portable Graymap', 'impress_pgm_Export')
 
214
fmts.add('presentation', 'png', 'png', 'Portable Network Graphic', 'impress_png_Export')
 
215
fmts.add('presentation', 'pot', 'pot', 'Microsoft PowerPoint 97/2000/XP Template', 'MS PowerPoint 97 Vorlage')
 
216
fmts.add('presentation', 'ppm', 'ppm', 'Portable Pixelmap', 'impress_ppm_Export')
 
217
fmts.add('presentation', 'ppt', 'ppt', 'Microsoft PowerPoint 97/2000/XP', 'MS PowerPoint 97')
 
218
fmts.add('presentation', 'pwp', 'pwp', 'PlaceWare', 'placeware_Export')
 
219
fmts.add('presentation', 'ras', 'ras', 'Sun Raster Image', 'impress_ras_Export')
 
220
fmts.add('presentation', 'sda', 'sda', 'StarDraw 5.0 (OpenOffice.org Impress)', 'StarDraw 5.0 (StarImpress)')
 
221
fmts.add('presentation', 'sdd', 'sdd', 'StarImpress 5.0', 'StarImpress 5.0')
 
222
fmts.add('presentation', 'sdd3', 'sdd', 'StarDraw 3.0 (OpenOffice.org Impress)', 'StarDraw 3.0 (StarImpress)')
 
223
fmts.add('presentation', 'sdd4', 'sdd', 'StarImpress 4.0', 'StarImpress 4.0')
 
224
fmts.add('presentation', 'sti', 'sti', 'OpenOffice.org 1.0 Presentation Template', 'impress_StarOffice_XML_Impress_Template')
 
225
fmts.add('presentation', 'stp', 'stp', 'OpenDocument Presentation Template', 'impress8_template')
 
226
fmts.add('presentation', 'svg', 'svg', 'Scalable Vector Graphics', 'impress_svg_Export')
 
227
fmts.add('presentation', 'svm', 'svm', 'StarView Metafile', 'impress_svm_Export')
 
228
fmts.add('presentation', 'swf', 'swf', 'Macromedia Flash (SWF)', 'impress_flash_Export')
 
229
fmts.add('presentation', 'sxi', 'sxi', 'OpenOffice.org 1.0 Presentation', 'StarOffice XML (Impress)')
 
230
fmts.add('presentation', 'tiff', 'tiff', 'Tagged Image File Format', 'impress_tif_Export')
 
231
fmts.add('presentation', 'vor', 'vor', 'StarImpress 5.0 Template', 'StarImpress 5.0 Vorlage')
 
232
fmts.add('presentation', 'vor3', 'vor', 'StarDraw 3.0 Template (OpenOffice.org Impress)', 'StarDraw 3.0 Vorlage (StarImpress)')
 
233
fmts.add('presentation', 'vor4', 'vor', 'StarImpress 4.0 Template', 'StarImpress 4.0 Vorlage')
 
234
fmts.add('presentation', 'vor5', 'vor', 'StarDraw 5.0 Template (OpenOffice.org Impress)', 'StarDraw 5.0 Vorlage (StarImpress)')
 
235
fmts.add('presentation', 'wmf', 'wmf', 'Windows Metafile', 'impress_wmf_Export')
 
236
fmts.add('presentation', 'xhtml', 'xml', 'XHTML', 'XHTML Impress File')
 
237
fmts.add('presentation', 'xpm', 'xpm', 'X PixMap', 'impress_xpm_Export')
 
238
 
 
239
class Options:
 
240
    def __init__(self, args):
 
241
        self.stdout = False
 
242
        self.showlist = False
 
243
        self.listener = False
 
244
        self.format = None
 
245
        self.verbose = 0
 
246
        self.doctype = None
 
247
        self.server = 'localhost'
 
248
        self.port = '2002'
 
249
        self.connection = None
 
250
        self.filenames = []
 
251
 
 
252
        ### Get options from the commandline
 
253
        try:
 
254
            opts, args = getopt.getopt (args, 'c:d:f:hLlp:s:t:v',
 
255
                ['connection=', 'doctype=', 'format=', 'help', 'listener', 'port=', 'server=', 'show', 'stdout', 'verbose', 'version'] )
 
256
        except getopt.error, exc:
 
257
            print 'unoconv: %s, try unoconv -h for a list of all the options' % str(exc)
 
258
            sys.exit(255)
 
259
 
 
260
        for opt, arg in opts:
 
261
            if opt in ['-h', '--help']:
 
262
                self.usage()
 
263
                print
 
264
                self.help()
 
265
                sys.exit(1)
 
266
            elif opt in ['-c', '--connection']:
 
267
                self.connection = arg
 
268
            elif opt in ['-d', '--doctype']:
 
269
                self.doctype = arg
 
270
            elif opt in ['-f', '--format']:
 
271
                self.format = arg
 
272
            elif opt in ['-l', '--listener']:
 
273
                self.listener = True
 
274
            elif opt in ['--show']:
 
275
                self.showlist = True
 
276
            elif opt in ['-p', '--port']:
 
277
                self.port = arg
 
278
            elif opt in ['-s', '--server']:
 
279
                self.server = arg
 
280
            elif opt in ['--stdout']:
 
281
                self.stdout = True
 
282
            elif opt in ['-v', '--verbose']:
 
283
                self.verbose = self.verbose + 1
 
284
            elif opt in ['--version']:
 
285
                self.version()
 
286
                sys.exit(255)
 
287
 
 
288
        ### Enable verbosity
 
289
        if self.verbose >= 3:
 
290
            print >>sys.stderr, 'Verbosity set to level %d' % (self.verbose - 1)
 
291
 
 
292
        self.filenames = args
 
293
 
 
294
        if not self.listener and not self.showlist and self.doctype != 'list' and not self.filenames:
 
295
            print >>sys.stderr, 'unoconv: you have to provide a filename as argument'
 
296
            print >>sys.stderr, 'Try `unoconv -h\' for more information.'
 
297
            sys.exit(255)
 
298
 
 
299
        ### Set connection string
 
300
        if not self.connection:
 
301
            self.connection = "socket,host=%s,port=%s;urp;StarOffice.ComponentContext" % (self.server, self.port)
 
302
#            self.connection = "socket,host=%s,port=%s;urp;" % (self.server, self.port)
 
303
 
 
304
        ### Make it easier for people to use a doctype (first letter is enough)
 
305
        if self.doctype:
 
306
            for doctype in doctypes:
 
307
                if doctype.startswith(self.doctype):
 
308
                    self.doctype = doctype
 
309
 
 
310
        ### Check if the user request to see the list of formats
 
311
        if self.showlist or self.format == 'list':
 
312
            if self.doctype:
 
313
                fmts.display(self.doctype)
 
314
            else:
 
315
                for t in doctypes:
 
316
                    fmts.display(t)
 
317
            sys.exit(0)
 
318
 
 
319
        ### If no format was specified, probe it or provide it
 
320
        if not self.format:
 
321
            l = sys.argv[0].split('2')
 
322
            if len(l) == 2:
 
323
                self.format = l[1]
 
324
            else:
 
325
                self.format = 'pdf'
 
326
 
 
327
    def version(self):
 
328
        print 'unoconv %s' % VERSION
 
329
        print 'Written by Dag Wieers <dag@wieers.com>'
 
330
        print 'Homepage at http://dag.wieers.com/home-made/unoconv/'
 
331
        print
 
332
        print 'platform %s/%s' % (os.name, sys.platform)
 
333
        print 'python %s' % sys.version
 
334
        print
 
335
        print 'build revision $Rev$'
 
336
 
 
337
    def usage(self):
 
338
        print >>sys.stderr, 'usage: unoconv [options] file [file2 ..]'
 
339
 
 
340
    def help(self):
 
341
        print >>sys.stderr, '''Convert from and to any format supported by OpenOffice
 
342
 
 
343
unoconv options:
 
344
  -c, --connection=string  use a custom connection string
 
345
  -d, --doctype=type       specify document type
 
346
                           (document, graphics, presentation, spreadsheet)
 
347
  -f, --format=format      specify the output format
 
348
  -l, --listener           start a listener to use by unoconv clients
 
349
  -p, --port               specify the port (default: 2002) 
 
350
                           to be used by client or listener
 
351
  -s, --server             specify the server address (default: localhost)
 
352
                           to be used by client or listener
 
353
      --show               list the available output formats
 
354
      --stdout             write output to stdout
 
355
  -v, --verbose            be more and more verbose
 
356
'''
 
357
 
 
358
class Convertor:
 
359
    def __init__(self):
 
360
        global oopid
 
361
        unocontext = None
 
362
 
 
363
        ### Do the OpenOffice component dance
 
364
        self.context = uno.getComponentContext()
 
365
        resolver = self.context.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", self.context)
 
366
 
 
367
        ### Test for an existing connection
 
368
        try:
 
369
            unocontext = resolver.resolve("uno:%s" % op.connection)
 
370
        except Exception, e:
 
371
            error(2, "Existing listener not found.\n%s" % e)
 
372
 
 
373
            ### Test if we can use an Openoffice *binary* in our (modified) path
 
374
            for bin in ('soffice.bin', 'soffice', ):
 
375
                error(2, "Trying to launch our own listener using %s." % bin)
 
376
                try:
 
377
                    oopid = os.spawnvp(os.P_NOWAIT, bin, [bin, "-nologo", "-nodefault", "-accept=%s" % op.connection]);
 
378
                    time.sleep(1)
 
379
                    unocontext = resolver.resolve("uno:%s" % op.connection)
 
380
                    break
 
381
                except Exception, e:
 
382
                    error(3, "Launch of %s failed.\n%s" % (bin, e))
 
383
                    continue
 
384
 
 
385
        if not unocontext:
 
386
            die(251, "Unable to connect or start own listener. Aborting.")
 
387
 
 
388
        ### And some more OpenOffice magic
 
389
        unosvcmgr = unocontext.ServiceManager
 
390
        self.desktop = unosvcmgr.createInstanceWithContext("com.sun.star.frame.Desktop", unocontext)
 
391
        self.cwd = unohelper.systemPathToFileUrl( os.getcwd() )
 
392
 
 
393
    def getformat(self, inputfn):
 
394
        doctype = None
 
395
 
 
396
        ### Get the output format from mapping
 
397
        if op.doctype:
 
398
            outputfmt = fmts.bydoctype(op.doctype, op.format)
 
399
        else:
 
400
            outputfmt = fmts.byname(op.format)
 
401
 
 
402
            if not outputfmt:
 
403
                outputfmt = fmts.byextension('.'+op.format)
 
404
 
 
405
        ### If no doctype given, check list of acceptable formats for input file ext doctype
 
406
        ### FIXME: This should go into the for-loop to match each individual input filename
 
407
        if outputfmt:
 
408
            inputext = os.path.splitext(inputfn)[1]
 
409
            inputfmt = fmts.byextension(inputext)
 
410
            if inputfmt:
 
411
                for fmt in outputfmt:
 
412
                    if inputfmt[0].doctype == fmt.doctype:
 
413
                        doctype = inputfmt[0].doctype
 
414
                        outputfmt = fmt
 
415
                        break
 
416
                else:
 
417
                    outputfmt = outputfmt[0]
 
418
    #       print >>sys.stderr, 'unoconv: format `%s\' is part of multiple doctypes %s, selecting `%s\'.' % (format, [fmt.doctype for fmt in outputfmt], outputfmt[0].doctype)
 
419
            else:
 
420
                outputfmt = outputfmt[0]
 
421
 
 
422
        ### No format found, throw error
 
423
        if not outputfmt:
 
424
            if doctype:
 
425
                print >>sys.stderr, 'unoconv: format [%s/%s] is not known to unoconv.' % (op.doctype, op.format)
 
426
            else:
 
427
                print >>sys.stderr, 'unoconv: format [%s] is not known to unoconv.' % op.format
 
428
            die(1)
 
429
 
 
430
        return outputfmt
 
431
 
 
432
    def convert(self, inputfn):
 
433
        doc = None
 
434
        outputfmt = self.getformat(inputfn)
 
435
 
 
436
        if op.verbose > 0:
 
437
            print >>sys.stderr, 'Input file:', inputfn
 
438
 
 
439
        if not os.path.exists(inputfn):
 
440
            print >>sys.stderr, 'unoconv: file `%s\' does not exist.' % inputfn
 
441
            exitcode = 1
 
442
            return
 
443
 
 
444
        try:
 
445
            ### Load inputfile
 
446
            inputprops = ( PropertyValue( "Hidden" , 0 , True, 0 ), )
 
447
 
 
448
            inputurl = unohelper.absolutize(self.cwd, unohelper.systemPathToFileUrl(inputfn))
 
449
            doc = self.desktop.loadComponentFromURL( inputurl , "_blank", 0, inputprops )
 
450
 
 
451
            if not doc:
 
452
                raise UnoException("File could not be loaded by OpenOffice", None)
 
453
 
 
454
            error(1, "Selected output format: %s" % outputfmt)
 
455
            error(1, "Selected ooffice filter: %s" % outputfmt.filter)
 
456
            error(1, "Used doctype: %s" % outputfmt.doctype)
 
457
 
 
458
            ### Write outputfile
 
459
            outputprops = (
 
460
                    PropertyValue( "FilterName" , 0, outputfmt.filter , 0 ),
 
461
                    PropertyValue( "Overwrite" , 0, True , 0 ),
 
462
                    PropertyValue( "OutputStream", 0, OutputStream(), 0),
 
463
                   )
 
464
 
 
465
            if not op.stdout:
 
466
                (outputfn, ext) = os.path.splitext(inputfn)
 
467
                outputfn = outputfn + '.' + outputfmt.extension
 
468
                outputurl = unohelper.absolutize( self.cwd, unohelper.systemPathToFileUrl(outputfn) )
 
469
                doc.storeToURL(outputurl, outputprops)
 
470
                error(1, "Output file: %s" % outputfn)
 
471
            else:
 
472
                doc.storeToURL("private:stream", outputprops)
 
473
 
 
474
            doc.dispose()
 
475
 
 
476
        except SystemError, e:
 
477
            error(0, "unoconv: SystemError during conversion: %s" % e)
 
478
            error(0, "The provided document cannot be converted to the desired format.")
 
479
            exitcode = 1
 
480
 
 
481
        except UnoException, e:
 
482
            error(0, "unoconv: UnoException during conversion: %s" % e.Message)
 
483
            error(0, "The provided document cannot be converted to the desired format.")
 
484
            exitcode = 1
 
485
 
 
486
        except IOException, e:
 
487
            error(0, "unoconv: IOException during conversion: %s" % e.Message)
 
488
            error(0, "The provided document cannot be exported to %s." % outputfmt)
 
489
            exitcode = 1
 
490
 
 
491
        except CannotConvertException, e:
 
492
            error(0, "unoconv: CannotConvertException during conversion: %s" % e.Message)
 
493
            exitcode = 1
 
494
 
 
495
class Listener:
 
496
    def __init__(self):
 
497
        error(1, "Start listener on %s:%s" % (op.server, op.port))
 
498
        for bin in ('soffice.bin', 'soffice', ):
 
499
            error(2, "Warning: trying to launch %s." % bin)
 
500
            try:
 
501
                os.execvp(bin, [bin, "-nologo", "-nodefault", "-accept=%s" % op.connection]);
 
502
            except:
 
503
                continue
 
504
        else:
 
505
            die(254, "Failed to start listener on %s:%s" % (op.server, op.port))
 
506
        die(253, "Existing listener found, aborting.")
 
507
 
 
508
def error(level, str):
 
509
    "Output error message"
 
510
    if level <= op.verbose:
 
511
        print >>sys.stderr, str
 
512
 
 
513
def info(level, str):
 
514
    "Output info message"
 
515
    if not op.stdout and level <= op.verbose:
 
516
        print >>sys.stdout, str
 
517
 
 
518
def die(ret, str=None):
 
519
    "Print error and exit with errorcode"
 
520
    global oopid
 
521
    if str:
 
522
        error(0, 'Error: %s' % str)
 
523
    if oopid:
 
524
        error(2, 'Taking down OpenOffice with pid %s.' % oopid)
 
525
#        os.setpgid(oopid, 0)
 
526
#        os.killpg(os.getpgid(oopid), 15)
 
527
        try:
 
528
            os.kill(oopid, 15)
 
529
            error(2, 'Waiting for OpenOffice with pid %s to disappear.' % oopid)
 
530
            os.waitpid(oopid, os.WUNTRACED)
 
531
        except:
 
532
            error(2, 'No OpenOffice with pid %s to take down' % oopid)
 
533
    sys.exit(ret)
 
534
 
 
535
def main():
 
536
    try:
 
537
        if op.listener:
 
538
            listener = Listener()
 
539
        else:
 
540
            convertor = Convertor()
 
541
 
 
542
        for inputfn in op.filenames:
 
543
            convertor.convert(inputfn)
 
544
 
 
545
    except NoConnectException, e:
 
546
        error(0, "unoconv: could not find an existing connection to Open Office at %s:%s." % (op.server, op.port))
 
547
        if op.connection:
 
548
            error(0, "Please start an OpenOffice instance on server '%s' by doing:\n\n    unoconv --listener --server %s --port %s\n\nor alternatively:\n\n    ooffice -nologo -nodefault -accept=\"%s\"" % (op.server, op.server, op.port, op.connection))
 
549
        else:
 
550
            error(0, "Please start an OpenOffice instance on server '%s' by doing:\n\n    unoconv --listener --server %s --port %s\n\nor alternatively:\n\n    ooffice -nologo -nodefault -accept=\"socket,host=%s,port=%s;urp;\"" % (op.server, op.server, op.port, op.server, op.port))
 
551
            error(0, "Please start an ooffice instance on server '%s' by doing:\n\n    ooffice -nologo -nodefault -accept=\"socket,host=localhost,port=%s;urp;\"" % (op.server, op.port))
 
552
        exitcode = 1
 
553
#    except UnboundLocalError:
 
554
#        die(252, "Failed to connect to remote listener.")
 
555
    except OSError:
 
556
        error(0, "Warning: failed to launch OpenOffice. Aborting.")
 
557
 
 
558
### Main entrance
 
559
if __name__ == '__main__':
 
560
    exitcode = 0
 
561
 
 
562
    op = Options(sys.argv[1:])
 
563
    try:
 
564
        main()
 
565
    except KeyboardInterrupt, e:
 
566
        die(6, 'Exiting on user request')
 
567
    die(exitcode)