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