This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
tabellioOOo/server/preview_server.py

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()