Here comes my long promised fix for bug 2637 (graphics files with ' in the
name can't be previewed).

My first idea was to copy the graphics file to the buffer temp dir, using
the same mangled name that will be used when running latex, and then
running the conversion chain on that file.
The advantage of that would be that we can reuse the conversion results (png
format in the common case) for pdflatex.
I did not do that in the end, because the preview conversion runs in the
background, and so we could easily get a race condition when view->pdflatex
is started before the conversion is complete.
Therefore I simply added one additional copy step to the conversion chain,
and did not use the original file name for the temp file name anymore.

This will go in tomorrow unless I get objections.


Georg

Log:
Fix bug 2637
        * src/graphics/GraphicsCacheItem.C
        (CacheItem::Impl::convertToDisplayFormat): Don't derive the temp
        file name from the original file name. This ensures that it is
        composed of valid characters only.

        * src/graphics/GraphicsConverter.C: remove example script, since it
        will get out of date.
        (build_script): Copy the original file to a temp file before the
        conversion chain starts. This avoids problems with converters that
        can't handle ' in filenames.
Index: src/graphics/GraphicsCacheItem.C
===================================================================
--- src/graphics/GraphicsCacheItem.C	(Revision 14417)
+++ src/graphics/GraphicsCacheItem.C	(Arbeitskopie)
@@ -426,12 +426,10 @@ void CacheItem::Impl::convertToDisplayFo
 	}
 
 	lyxerr[Debug::GRAPHICS] << "\tConverting it to " << to << " format." << endl;
-	// Take only the filename part of the file, without path or extension.
-	string const temp = changeExtension(onlyFilename(filename), string());
 
 	// Add some stuff to create a uniquely named temporary file.
 	// This file is deleted in loadImage after it is loaded into memory.
-	string const to_file_base = tempName(string(), temp);
+	string const to_file_base = tempName(string(), "CacheItem");
 	remove_loaded_file_ = true;
 
 	// Remove the temp file, we only want the name...
Index: src/graphics/GraphicsConverter.C
===================================================================
--- src/graphics/GraphicsConverter.C	(Revision 14417)
+++ src/graphics/GraphicsConverter.C	(Arbeitskopie)
@@ -33,6 +33,7 @@ namespace support = lyx::support;
 using support::changeExtension;
 using support::Forkedcall;
 using support::ForkedCallQueue;
+using support::getExtension;
 using support::libFileSearch;
 using support::libScriptSearch;
 using support::onlyPath;
@@ -265,7 +266,6 @@ string const move_file(string const & fr
 		<< "try:\n"
 		<< "  os.rename(fromfile, tofile)\n"
 		<< "except:\n"
-		<< "  import shutil\n"
 		<< "  try:\n"
 		<< "    shutil.copy(fromfile, tofile)\n"
 		<< "  except:\n"
@@ -276,50 +276,6 @@ string const move_file(string const & fr
 }
 
 
-/*
-A typical script looks like:
-
-#!/usr/bin/env python -tt
-import os, sys
-
-def unlinkNoThrow(file):
-  ''' remove a file, do not throw if error occurs '''
-  try:
-    os.unlink(file)
-  except:
-    pass
-
-infile = '/home/username/Figure3a.eps'
-infile_base = '/home/username/Figure3a'
-outfile = '/tmp/lyx_tmpdir12992hUwBqt/gconvert0129929eUBPm.pdf'
-
-if os.system(r'epstopdf ' + '"' + infile + '"' + ' --output ' + '"' + outfile + '"' + '') != 0:
-  unlinkNoThrow(outfile)
-  sys.exit(1)
-
-if not os.path.isfile(outfile):
-  if os.path.isfile(outfile + '.0'):
-    os.rename(outfile + '.0', outfile)
-    import glob
-    for file in glob.glob(outfile + '.?'):
-      unlinkNoThrow(file)
-  else:
-    sys.exit(1)
-
-fromfile = outfile
-tofile = '/tmp/lyx_tmpdir12992hUwBqt/Figure3a129927ByaCl.ppm'
-
-try:
-  os.rename(fromfile, tofile)
-except:
-  import shutil
-  try:
-    shutil.copy(fromfile, tofile)
-  except:
-    sys.exit(1)
-  unlinkNoThrow(fromfile)
-
-*/
 bool build_script(string const & from_file,
 		  string const & to_file_base,
 		  string const & from_format,
@@ -334,7 +290,7 @@ bool build_script(string const & from_fi
 		return false;
 
 	script << "#!/usr/bin/env python -tt\n"
-	          "import os, sys\n\n"
+	          "import os, shutil, sys\n\n"
 	          "def unlinkNoThrow(file):\n"
 	          "  ''' remove a file, do not throw if an error occurs '''\n"
 	          "  try:\n"
@@ -361,7 +317,15 @@ bool build_script(string const & from_fi
 	string const to_base = tempName(string(), tmp);
 	unlink(to_base);
 
-	string outfile = from_file;
+	// Create a copy of the file in case the original name contains
+	// problematic characters like ' or ". We can work around that problem
+	// in python, but the converters might be shell scripts and have more
+	// troubles with it.
+	string outfile = changeExtension(to_base, getExtension(from_file));
+	script << "infile = '"
+	       << subst(subst(from_file, "\\", "\\\\"), "'", "\\'") << "'\n"
+	          "outfile = " << quoteName(outfile) << "\n"
+	          "shutil.copy(infile, outfile)\n";
 
 	// The conversion commands may contain these tokens that need to be
 	// changed to infile, infile_base, outfile respectively.
@@ -413,9 +377,8 @@ bool build_script(string const & from_fi
 		          "  else:\n"
 		          "    sys.exit(1)\n\n";
 
-		// Delete the infile, if it isn't the original, from_file.
-		if (infile != from_file)
-			script << "unlinkNoThrow(infile)\n\n";
+		// Delete the infile
+		script << "unlinkNoThrow(infile)\n\n";
 	}
 
 	// Move the final outfile to to_file

Reply via email to