X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FConverter.cpp;h=6057ccd78c9fce6312754ef64b8142c288236543;hb=2de30c62f8d671a8c8d4d52a6a7310e2c5ca84de;hp=307eb23e21f62ebd743162bb102290e55dcc51a1;hpb=c86f299a50e33eddf0b013547bc48cfc62c8a715;p=lyx.git
diff --git a/src/Converter.cpp b/src/Converter.cpp
index 307eb23e21..6057ccd78c 100644
--- a/src/Converter.cpp
+++ b/src/Converter.cpp
@@ -21,7 +21,9 @@
#include "Format.h"
#include "Language.h"
#include "LaTeX.h"
+#include "LyXRC.h"
#include "Mover.h"
+#include "Session.h"
#include "frontends/alert.h"
@@ -29,6 +31,7 @@
#include "support/FileNameList.h"
#include "support/filetools.h"
#include "support/gettext.h"
+#include "support/lassert.h"
#include "support/lstrings.h"
#include "support/os.h"
#include "support/Package.h"
@@ -99,7 +102,7 @@ Converter::Converter(string const & f, string const & t,
string const & c, string const & l)
: from_(f), to_(t), command_(c), flags_(l),
From_(0), To_(0), latex_(false), xml_(false),
- need_aux_(false), nice_(false)
+ need_aux_(false), nice_(false), need_auth_(false)
{}
@@ -127,6 +130,8 @@ void Converter::readFlags()
parselog_ = flag_value;
else if (flag_name == "nice")
nice_ = true;
+ else if (flag_name == "needauth")
+ need_auth_ = true;
}
if (!result_dir_.empty() && result_file_.empty())
result_file_ = "index." + formats.extension(to_);
@@ -274,6 +279,57 @@ OutputParams::FLAVOR Converters::getFlavor(Graph::EdgePath const & path,
}
+bool Converters::checkAuth(Converter const & conv, string const & doc_fname)
+{
+ if (!conv.need_auth())
+ return true;
+ const docstring security_warning = bformat(
+ _("
The requested operation requires the use of a converter from "
+ "%2$s to %3$s:
"
+ "%1$s
"
+ "This external program can execute arbitrary commands on your "
+ "system, including dangerous ones, if instructed to do so by a "
+ "maliciously crafted .lyx document.
"),
+ from_utf8(conv.command()), from_utf8(conv.from()),
+ from_utf8(conv.to()));
+ if (lyxrc.use_converter_needauth_forbidden) {
+ frontend::Alert::warning(
+ _("An external converter is disabled for security reasons"),
+ security_warning + _(
+ "Your current settings forbid its execution.
"
+ "(To change this setting, go to Preferences ▹ File "
+ "Handling ▹ Converters and uncheck Security ▹ "
+ "Forbid needauth converters.)"), false);
+ return false;
+ }
+ if (!lyxrc.use_converter_needauth)
+ return true;
+ static const docstring security_title =
+ _("An external converter requires your authorization");
+ int choice;
+ const docstring security_warning2 = security_warning +
+ _("
Would you like to run this converter?
"
+ "Only run if you trust the origin/sender of the LyX "
+ "document!
");
+ if (!doc_fname.empty()) {
+ LYXERR(Debug::FILES, "looking up: " << doc_fname);
+ std::set & auth_files = theSession().authFiles().authFiles();
+ if (auth_files.find(doc_fname) == auth_files.end()) {
+ choice = frontend::Alert::prompt(security_title, security_warning2,
+ 0, 0, _("Do ¬ run"), _("&Run"), _("&Always run for this document"));
+ if (choice == 2)
+ auth_files.insert(doc_fname);
+ } else {
+ choice = 1;
+ }
+ } else {
+ choice = frontend::Alert::prompt(security_title, security_warning2,
+ 0, 0, _("Do ¬ run"), _("&Run"));
+ }
+ return choice != 0;
+}
+
+
bool Converters::convert(Buffer const * buffer,
FileName const & from_file, FileName const & to_file,
FileName const & orig_from,
@@ -299,15 +355,16 @@ bool Converters::convert(Buffer const * buffer,
string const command =
os::python() + ' ' +
quoteName(libFileSearch("scripts", "convertDefault.py").toFilesystemEncoding()) +
- ' ' +
- quoteName(from_ext + ':' + from_file.toFilesystemEncoding()) +
- ' ' +
- quoteName(to_ext + ':' + to_file.toFilesystemEncoding());
+ ' ' + from_ext + ' ' +
+ quoteName(from_file.toFilesystemEncoding()) +
+ ' ' + to_ext + ' ' +
+ quoteName(to_file.toFilesystemEncoding());
LYXERR(Debug::FILES, "No converter defined! "
"I use convertDefault.py:\n\t" << command);
Systemcall one;
- one.startscript(Systemcall::Wait, command, buffer ?
- buffer->filePath() : string());
+ one.startscript(Systemcall::Wait, command,
+ buffer ? buffer->filePath() : string(),
+ buffer ? buffer->layoutPos() : string());
if (to_file.isReadableFile()) {
if (conversionflags & try_cache)
ConverterCache::get().add(orig_from,
@@ -337,7 +394,9 @@ bool Converters::convert(Buffer const * buffer,
runparams.flavor = getFlavor(edgepath, buffer);
if (buffer) {
- runparams.use_japanese = buffer->params().bufferFormat() == "platex";
+ runparams.use_japanese =
+ buffer->params().bufferFormat() == "latex"
+ && buffer->params().encoding().package() == Encoding::japanese;
runparams.use_indices = buffer->params().use_indices;
runparams.bibtex_command = (buffer->params().bibtex_command == "default") ?
string() : buffer->params().bibtex_command;
@@ -398,6 +457,9 @@ bool Converters::convert(Buffer const * buffer,
"tmpfile.out"));
}
+ if (!checkAuth(conv, buffer ? buffer->absFileName() : string()))
+ return false;
+
if (conv.latex()) {
run_latex = true;
string command = conv.command();
@@ -455,10 +517,12 @@ bool Converters::convert(Buffer const * buffer,
if (!conv.parselog().empty())
command += " 2> " + quoteName(infile2 + ".out");
- if (conv.from() == "dvi" && conv.to() == "ps")
+ // it is not actually not necessary to test for buffer here,
+ // but it pleases coverity.
+ if (buffer && conv.from() == "dvi" && conv.to() == "ps")
command = add_options(command,
buffer->params().dvips_options());
- else if (conv.from() == "dvi" && prefixIs(conv.to(), "pdf"))
+ else if (buffer && conv.from() == "dvi" && prefixIs(conv.to(), "pdf"))
command = add_options(command,
dvipdfm_options(buffer->params()));
@@ -472,13 +536,16 @@ bool Converters::convert(Buffer const * buffer,
if (dummy) {
res = one.startscript(Systemcall::DontWait,
to_filesystem8bit(from_utf8(command)),
- buffer ? buffer->filePath() : string());
+ buffer ? buffer->filePath() : string(),
+ buffer ? buffer->layoutPos() : string());
// We're not waiting for the result, so we can't do anything
// else here.
} else {
res = one.startscript(Systemcall::Wait,
to_filesystem8bit(from_utf8(command)),
buffer ? buffer->filePath()
+ : string(),
+ buffer ? buffer->layoutPos()
: string());
if (!real_outfile.empty()) {
Mover const & mover = getMover(conv.to());
@@ -499,7 +566,8 @@ bool Converters::convert(Buffer const * buffer,
" > " + quoteName(logfile);
one.startscript(Systemcall::Wait,
to_filesystem8bit(from_utf8(command2)),
- buffer->filePath());
+ buffer->filePath(),
+ buffer->layoutPos());
if (!scanLog(*buffer, command, makeAbsPath(logfile, path), errorList))
return false;
}
@@ -622,7 +690,7 @@ bool Converters::scanLog(Buffer const & buffer, string const & /*command*/,
namespace {
class ShowMessage
- : public boost::signals::trackable {
+ : public boost::signals2::trackable {
public:
ShowMessage(Buffer const & b) : buffer_(b) {}
void operator()(docstring const & msg) const { buffer_.message(msg); }
@@ -642,7 +710,8 @@ bool Converters::runLaTeX(Buffer const & buffer, string const & command,
// do the LaTeX run(s)
string const name = buffer.latexName();
LaTeX latex(command, runparams, FileName(makeAbsPath(name)),
- buffer.filePath());
+ buffer.filePath(), buffer.layoutPos(),
+ buffer.lastPreviewError());
TeXErrors terr;
ShowMessage show(buffer);
latex.message.connect(show);
@@ -651,16 +720,27 @@ bool Converters::runLaTeX(Buffer const & buffer, string const & command,
if (result & LaTeX::ERRORS)
buffer.bufferErrors(terr, errorList);
- // check return value from latex.run().
- if ((result & LaTeX::NO_LOGFILE) && !buffer.isClone()) {
+ if (!errorList.empty()) {
+ // We will show the LaTeX Errors GUI later which contains
+ // specific error messages so it would be repetitive to give
+ // e.g. the "finished with an error" dialog in addition.
+ }
+ else if (result & LaTeX::NO_LOGFILE) {
docstring const str =
bformat(_("LaTeX did not run successfully. "
"Additionally, LyX could not locate "
"the LaTeX log %1$s."), from_utf8(name));
Alert::error(_("LaTeX failed"), str);
- } else if ((result & LaTeX::NO_OUTPUT) && !buffer.isClone()) {
+ } else if (result & LaTeX::NONZERO_ERROR) {
+ docstring const str =
+ bformat(_( "The external program\n%1$s\n"
+ "finished with an error. "
+ "It is recommended you fix the cause of the external "
+ "program's error (check the logs). "), from_utf8(command));
+ Alert::error(_("LaTeX failed"), str);
+ } else if (result & LaTeX::NO_OUTPUT) {
Alert::warning(_("Output is empty"),
- _("An empty output file was generated."));
+ _("No output file was generated."));
}
@@ -672,7 +752,6 @@ bool Converters::runLaTeX(Buffer const & buffer, string const & command,
LaTeX::NO_OUTPUT;
return (result & ERROR_MASK) == 0;
-
}
@@ -689,19 +768,20 @@ void Converters::buildGraph()
for (; it != end ; ++it) {
int const from = formats.getNumber(it->from());
int const to = formats.getNumber(it->to());
+ LASSERT(from >= 0, continue);
+ LASSERT(to >= 0, continue);
G_.addEdge(from, to);
}
}
-vector const
-Converters::intToFormat(vector const & input)
+FormatList const Converters::intToFormat(vector const & input)
{
- vector result(input.size());
+ FormatList result(input.size());
vector::const_iterator it = input.begin();
vector::const_iterator const end = input.end();
- vector::iterator rit = result.begin();
+ FormatList::iterator rit = result.begin();
for ( ; it != end; ++it, ++rit) {
*rit = &formats.get(*it);
}
@@ -709,8 +789,8 @@ Converters::intToFormat(vector const & input)
}
-vector const
-Converters::getReachableTo(string const & target, bool const clear_visited)
+FormatList const Converters::getReachableTo(string const & target,
+ bool const clear_visited)
{
vector const & reachablesto =
G_.getReachableTo(formats.getNumber(target), clear_visited);
@@ -719,9 +799,9 @@ Converters::getReachableTo(string const & target, bool const clear_visited)
}
-vector const
-Converters::getReachable(string const & from, bool const only_viewable,
- bool const clear_visited, set const & excludes)
+FormatList const Converters::getReachable(string const & from,
+ bool const only_viewable, bool const clear_visited,
+ set const & excludes)
{
set excluded_numbers;
@@ -754,29 +834,28 @@ Graph::EdgePath Converters::getPath(string const & from, string const & to)
}
-vector Converters::importableFormats()
+FormatList Converters::importableFormats()
{
vector l = loaders();
- vector result = getReachableTo(l[0], true);
+ FormatList result = getReachableTo(l[0], true);
vector::const_iterator it = l.begin() + 1;
vector::const_iterator en = l.end();
for (; it != en; ++it) {
- vector r = getReachableTo(*it, false);
+ FormatList r = getReachableTo(*it, false);
result.insert(result.end(), r.begin(), r.end());
}
return result;
}
-vector Converters::exportableFormats(bool only_viewable)
+FormatList Converters::exportableFormats(bool only_viewable)
{
vector s = savers();
- vector result = getReachable(s[0], only_viewable, true);
+ FormatList result = getReachable(s[0], only_viewable, true);
vector::const_iterator it = s.begin() + 1;
vector::const_iterator en = s.end();
for (; it != en; ++it) {
- vector r =
- getReachable(*it, only_viewable, false);
+ FormatList r = getReachable(*it, only_viewable, false);
result.insert(result.end(), r.begin(), r.end());
}
return result;