using support::onlyPath;
using support::onlyFilename;
using support::quoteName;
+using support::quote_python;
using support::subst;
using support::tempName;
using support::unlink;
// 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"
+ script << "infile = " << quoteName(from_file, quote_python) << "\n"
+ "outfile = " << quoteName(outfile, quote_python) << "\n"
"shutil.copy(infile, outfile)\n";
if (edgepath.empty()) {
// converter path from from_format to to_format, so we use
// the default converter.
script << "infile = outfile\n"
- << "outfile = " << quoteName(to_file) << '\n';
+ << "outfile = " << quoteName(to_file, quote_python)
+ << '\n';
ostringstream os;
- os << support::os::python() << " \""
- << libFileSearch("scripts", "convertDefault.py") << "\" ";
+ os << support::os::python() << ' '
+ << libScriptSearch("$$s/scripts/convertDefault.py",
+ quote_python) << ' ';
if (!from_format.empty())
os << from_format << ':';
+ // The extra " quotes around infile and outfile are needed
+ // because the filename may contain spaces and it is used
+ // as argument of os.system().
os << "' + '\"' + infile + '\"' + ' "
<< to_format << ":' + '\"' + outfile + '\"' + '";
string const command = os.str();
outfile = changeExtension(to_base, conv.To->extension());
// Store these names in the python script
- script << "infile = " << quoteName(infile) << '\n'
- << "infile_base = " << quoteName(infile_base) << '\n'
- << "outfile = " << quoteName(outfile) << '\n';
+ script << "infile = " << quoteName(infile, quote_python) << "\n"
+ "infile_base = " << quoteName(infile_base, quote_python) << "\n"
+ "outfile = " << quoteName(outfile, quote_python) << '\n';
+ // See comment about extra " quotes above (although that
+ // applies only for the first loop run here).
string command = conv.command;
command = subst(command, token_from, "' + '\"' + infile + '\"' + '");
command = subst(command, token_base, "' + '\"' + infile_base + '\"' + '");
command = subst(command, token_to, "' + '\"' + outfile + '\"' + '");
- command = libScriptSearch(command);
+ command = libScriptSearch(command, quote_python);
build_conversion_command(command, script);
}
// Move the final outfile to to_file
- script << move_file("outfile", quoteName(to_file));
+ script << move_file("outfile", quoteName(to_file, quote_python));
lyxerr[Debug::GRAPHICS] << "ready!" << endl;
}
}
-string const quoteName(string const & name)
+string const quoteName(string const & name, quote_style style)
{
- return (os::shell() == os::UNIX) ?
- '\'' + name + '\'':
- '"' + name + '"';
+ switch(style) {
+ case quote_shell:
+ // This does not work for filenames containing " (windows)
+ // or ' (all other OSes). This can't be changed easily, since
+ // we would need to adapt the command line parser in
+ // Forkedcall::generateChild. Therefore we don't pass user
+ // filenames to child processes if possible. We store them in
+ // a python script instead, where we don't have these
+ // limitations.
+ return (os::shell() == os::UNIX) ?
+ '\'' + name + '\'':
+ '"' + name + '"';
+ case quote_python:
+ return "\"" + subst(subst(name, "\\", "\\\\"), "\"", "\\\"")
+ + "\"";
+ }
+ // shut up stupid compiler
+ return string();
}
}
-string const libScriptSearch(string const & command_in)
+string const libScriptSearch(string const & command_in, quote_style style)
{
static string const token_scriptpath = "$$s/";
} else {
// Replace "$$s/foo/some_script" with "<path to>/some_script".
string::size_type const size_replace = size_script + 4;
- command.replace(pos1, size_replace, quoteName(script));
+ command.replace(pos1, size_replace, quoteName(script, style));
}
return command;
std::string const & name,
std::string const & ext = std::string());
+/// How to quote a filename
+enum quote_style {
+ /** Quote for the (OS dependant) shell. This is needed for command
+ line arguments of subprocesses. */
+ quote_shell,
+ /** Quote for python. Use this if you want to store a filename in a
+ python script. Example: \code
+ os << "infile = " << quoteName(filename) << '\\n';
+ \endcode This uses double quotes, so that you can also use this
+ to quote filenames as part of a string if the string is quoted
+ with single quotes. */
+ quote_python
+};
+
/** Takes a command such as "python $$s/scripts/convertDefault.py file.in file.out"
* and replaces "$$s/" with the path to the LyX support directory containing
* this script. If the script is not found, "$$s/" is removed. Executing the
* command will still fail, but the error message will make some sort of
* sense ;-)
*/
-std::string const libScriptSearch(std::string const & command);
+std::string const libScriptSearch(std::string const & command,
+ quote_style style = quote_shell);
enum latex_path_extension {
PROTECT_EXTENSION,
/// Substitutes active latex characters with underscores in filename
std::string const makeLatexName(std::string const & file);
-/// Put the name in quotes suitable for the current shell
-std::string const quoteName(std::string const & file);
+/** Put the name in quotes suitable for the current shell or python,
+ depending on \p style. */
+std::string const quoteName(std::string const & file, quote_style style = quote_shell);
/// Add a filename to a path. Any path from filename is stripped first.
std::string const addName(std::string const & path, std::string const & fname);