191 lines
6.9 KiB
Python
Executable File
191 lines
6.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: UTF-8 -*-
|
|
#
|
|
# TabellioOOo - SCGI server providing preview of ODF files
|
|
# Copyright (C) 2007-2010 Parlement de la Communauté française de Belgique
|
|
#
|
|
# 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; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
import sys
|
|
import os
|
|
import resource
|
|
from optparse import OptionParser
|
|
from scgi.scgi_server import SCGIServer, SCGIHandler
|
|
import time
|
|
import syslog
|
|
import socket
|
|
import tempfile
|
|
|
|
class PreviewHandler(SCGIHandler):
|
|
debug = False
|
|
daemon = False
|
|
|
|
def handle_connection(self, conn):
|
|
input = conn.makefile('r')
|
|
output = conn.makefile('w')
|
|
env = self.read_env(input)
|
|
bodysize = int(env.get('CONTENT_LENGTH', 0))
|
|
try:
|
|
self.produce(env, bodysize, input, output)
|
|
finally:
|
|
output.close()
|
|
input.close()
|
|
conn.close()
|
|
|
|
def produce(self, env, bodysize, input, output):
|
|
tmp_work_dir = os.path.join(tempfile.gettempdir(), 'tabellio')
|
|
if not os.path.exists(tmp_work_dir):
|
|
os.makedirs(tmp_work_dir)
|
|
|
|
if self.debug:
|
|
print 'Request received at', time.strftime('[%Y-%m-%d %H:%M]')
|
|
print ' - body size:', bodysize
|
|
|
|
if bodysize == 0:
|
|
return self.error_page(output, 'this server only supports POST')
|
|
|
|
input_file = input.read(bodysize)
|
|
|
|
if not os.path.exists('../legi2pdf/script/db2pdf.py'):
|
|
pdf_file = file('unconfigured.pdf').read()
|
|
print >> output, 'Content-type: application/pdf'
|
|
print >> output, 'Content-length: %s' % len(pdf_file)
|
|
print >> output, ''
|
|
print >> output, pdf_file
|
|
return
|
|
|
|
if env.get('REQUEST_URI').endswith('/odt'):
|
|
# legi file as input, odt file as output
|
|
legi_filename = tempfile.mkstemp(suffix='.legi', prefix='l2o-', dir=tmp_work_dir)[1]
|
|
fd = file(legi_filename, 'w')
|
|
fd.write(input_file)
|
|
fd.close()
|
|
os.system('python ../legi2odf/legi2odf.py %s' % legi_filename)
|
|
|
|
odt_file = file(legi_filename.replace('.legi', '.odt')).read()
|
|
|
|
print >> output, 'Content-type: application/octet-stream'
|
|
print >> output, 'Content-Disposition: attachment'
|
|
print >> output, 'Content-length: %s' % len(odt_file)
|
|
print >> output, ''
|
|
output.write(odt_file)
|
|
return
|
|
|
|
odf_file = input_file
|
|
|
|
odf_filename = tempfile.mkstemp(suffix='.odt', prefix='o2l-', dir=tmp_work_dir)[1]
|
|
if self.debug:
|
|
print ' - storing ODT file as', odf_filename
|
|
|
|
legi_filename = odf_filename.replace('.odt', '.legi')
|
|
pdf_filename = odf_filename.replace('.odt', '.pdf')
|
|
fd = file(odf_filename, 'w')
|
|
fd.write(odf_file)
|
|
fd.close()
|
|
|
|
if os.system('python ../odf2legi/odf2legi.py %s' % odf_filename):
|
|
if self.daemon:
|
|
syslog.syslog(syslog.LOG_ERR, 'error in odf2legi')
|
|
else:
|
|
print ' E: error in odf2legi'
|
|
return self.error_page(output, 'Error in odf2legi')
|
|
else:
|
|
if env.get('REQUEST_URI').endswith('/legi'):
|
|
legi_file = file(legi_filename).read()
|
|
if self.debug:
|
|
print 'Serving result as a legi file (%s)' % legi_filename
|
|
print ' - body size:', len(legi_file)
|
|
print >> output, 'Content-type: application/octet-stream'
|
|
print >> output, 'Content-Disposition: attachment'
|
|
print >> output, 'Content-length: %s' % len(legi_file)
|
|
print >> output, ''
|
|
output.write(legi_file)
|
|
return
|
|
|
|
if os.system('python ../legi2pdf/script/db2pdf.py --debug --latex --input=%s' % legi_filename):
|
|
if self.daemon:
|
|
syslog.syslog(syslog.LOG_ERR, 'error in legi2pdf')
|
|
else:
|
|
print ' E: error in legi2pdf'
|
|
return self.error_page(output, 'Error in legi2pdf')
|
|
|
|
if os.path.exists(pdf_filename):
|
|
pdf_file = file(pdf_filename).read()
|
|
else:
|
|
pdf_file = file('error.pdf').read()
|
|
print >> output, 'Content-type: application/pdf'
|
|
print >> output, 'Content-length: %s' % len(pdf_file)
|
|
print >> output, ''
|
|
output.write(pdf_file)
|
|
|
|
def error_page(self, output, message):
|
|
print >> output, 'Content-type: text/plain'
|
|
print >> output, ''
|
|
print >> output, message
|
|
|
|
|
|
def main():
|
|
parser = OptionParser()
|
|
parser.add_option('-p', '--port', dest = 'port', type='int', default = 2151)
|
|
parser.add_option('--debug', action = 'store_true', dest = 'debug')
|
|
parser.add_option('-f', '--foreground', dest='foreground', action='store_true')
|
|
parser.add_option('--pid', dest='pid')
|
|
options, args = parser.parse_args()
|
|
|
|
# force current directory to match the script, to make sure it finds the
|
|
# various tools (legi2pdf & odf2legi)
|
|
os.chdir(os.path.abspath(os.path.dirname(__file__)))
|
|
|
|
if not os.path.exists('../legi2pdf/script/db2pdf.py'):
|
|
print >> sys.stderr, 'W: legi2pdf not found'
|
|
|
|
if not os.path.exists('/tmp/tabellio'):
|
|
os.mkdir('/tmp/tabellio')
|
|
|
|
if not options.foreground:
|
|
PreviewHandler.daemon = True
|
|
if os.fork():
|
|
os._exit(0)
|
|
os.setsid()
|
|
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
|
if maxfd == resource.RLIM_INFINITY:
|
|
maxfd = 1024
|
|
for fd in range(maxfd):
|
|
try:
|
|
os.close(fd)
|
|
except OSError:
|
|
pass
|
|
os.open('/dev/null', os.O_RDWR)
|
|
os.dup2(0, 1)
|
|
os.dup2(0, 2)
|
|
if os.fork():
|
|
os._exit(0)
|
|
if options.pid:
|
|
file(options.pid, 'w').write(str(os.getpid()))
|
|
syslog.openlog('tabellio-preview')
|
|
|
|
PreviewHandler.debug = options.debug
|
|
try:
|
|
SCGIServer(handler_class = PreviewHandler, port = options.port).serve()
|
|
except socket.error:
|
|
if PreviewHandler.daemon:
|
|
syslog.syslog(syslog.LOG_CRIT, 'socket error (another instance is running?)')
|
|
print >> sys.stderr, 'E: socket error (another instance is running?)'
|
|
sys.exit(1)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|