diff --git a/src/common/latex.py b/src/common/latex.py index 9a90fe861..cedf2f19b 100644 --- a/src/common/latex.py +++ b/src/common/latex.py @@ -29,7 +29,7 @@ import os import random -from tempfile import gettempdir +from tempfile import mkstemp, mkdtemp from subprocess import Popen, PIPE import logging @@ -57,24 +57,6 @@ def check_blacklist(str_): return True return False -def get_tmpfile_name(): - random.seed() - nb = 0 - while(nb < 100): - int_ = random.randint(0, 10000) - filename = os.path.join(gettempdir(), 'gajimtex_' + int_.__str__()) - # Check if a file to not overwrite it - ok = True - extensions = ['.tex', '.log', '.aux', '.dvi'] - for ext in extensions: - if os.path.exists(filename + ext): - ok = False - break - if ok: - return filename - nb += 1 - return filename - def write_latex(filename, str_): texstr = '\\documentclass[12pt]{article}\\usepackage[dvips]{graphicx}' texstr += '\\usepackage{amsmath}\\usepackage{amssymb}' @@ -91,12 +73,13 @@ def write_latex(filename, str_): # a wrapper for Popen so that no window gets opened on Windows # (i think this is the reason we're using Popen rather than just system()) # stdout goes to a pipe so that it can be read -def popen_nt_friendly(command): +def popen_nt_friendly(command, directory): if os.name == 'nt': # CREATE_NO_WINDOW - return Popen(command, creationflags=0x08000000, cwd=gettempdir(), stdout=PIPE) + return Popen(command, creationflags=0x08000000, cwd=directory, + stdout=PIPE) else: - return Popen(command, cwd=gettempdir(), stdout=PIPE) + return Popen(command, cwd=directory, stdout=PIPE) def check_for_latex_support(): """ @@ -112,16 +95,16 @@ def check_for_latex_support(): except LatexError: return False -def try_run(argv): +def try_run(argv, directory): try: - p = popen_nt_friendly(argv) + p = popen_nt_friendly(argv, directory) out = p.communicate()[0] log.info(out) return p.wait() except Exception, e: return _('Error executing "%(command)s": %(error)s') % { - 'command': " ".join(argv), - 'error': helpers.decode_string(str(e))} + 'command': " ".join(argv), + 'error': helpers.decode_string(str(e))} def latex_to_image(str_): @@ -137,32 +120,41 @@ def latex_to_image(str_): return [] except AttributeError: # interface may not be available when we test latext at startup - return ['-fg', 'rgb 0.0 0.0 0.0'] + return {'hex': ['+level-colors', '0x000000'], + 'tex': ['-fg', 'rgb 0.0 0.0 0.0']}[fmt] # filter latex code with bad commands if check_blacklist(str_): # we triggered the blacklist, immediately return None return None - tmpfile = get_tmpfile_name() + try: + tmpdir = mkdtemp(prefix='gajimtex') + tmppng = mkstemp(prefix='gajim_tex', suffix='.png')[1] + except Exception: + raise LatexError('could not securely create one or more temporary files' + ' for LaTeX conversion') + + tmpfile = os.path.join(tmpdir, 'gajim_tex') # build latex string - write_latex(os.path.join(tmpfile + '.tex'), str_) + write_latex(tmpfile + '.tex', str_) # convert TeX to dvi - exitcode = try_run(['latex', '--interaction=nonstopmode', - tmpfile + '.tex']) + exitcode = try_run(['latex', '--interaction=nonstopmode', tmpfile + '.tex'], + tmpdir) if exitcode == 0: # convert dvi to png latex_png_dpi = gajim.config.get('latex_png_dpi') exitcode = try_run(['dvipng'] + fg_str('tex') + ['-T', 'tight', '-D', - latex_png_dpi, tmpfile + '.dvi', '-o', tmpfile + '.png']) + latex_png_dpi, tmpfile + '.dvi', '-o', tmpfile + '.png'], tmpdir) if exitcode: # dvipng failed, try convert exitcode = try_run(['convert'] + fg_str('hex') + ['-trim', - '-density', latex_png_dpi, tmpfile + '.dvi', tmpfile + '.png']) + '-density', latex_png_dpi, tmpfile + '.dvi', tmpfile + '.png'], + tmpdir) # remove temp files created by us and TeX extensions = ['.tex', '.log', '.aux', '.dvi'] @@ -172,10 +164,15 @@ def latex_to_image(str_): except Exception: pass + if exitcode == 0: + os.rename(tmpfile + '.png', tmppng) + + os.rmdir(tmpdir) + if isinstance(exitcode, (unicode, str)): raise LatexError(exitcode) if exitcode == 0: - result = tmpfile + '.png' + result = tmppng return result