35 #include "klfbackend_p.h"
36 #include "klfuserscript.h"
110 for (
int k = 0; k < idlist.
size(); ++k) {
116 inline int ref() {
return ++refcount; }
117 inline int deref() {
return --refcount; }
131 void _set_xml_read_error(
const QString& fullerrmsg)
133 scriptInfoError = 999;
134 scriptInfoErrorString = fullerrmsg;
136 void _set_xml_parsing_error(
const QString& xmlfname,
const QString& errmsg)
138 scriptInfoError = 999;
139 scriptInfoErrorString =
QString(
"Error parsing scriptinfo XML contents: %1: %2")
140 .
arg(xmlfname).
arg(errmsg);
143 void read_script_info()
146 scriptInfoErrorString =
QString();
149 QFile fxml(xmlfname);
150 if ( ! fxml.open(QIODevice::ReadOnly) ) {
151 _set_xml_read_error(
QString(
"Can't open XML file %1: %2").arg(xmlfname).arg(fxml.errorString()));
156 QString errMsg;
int errLine, errCol;
157 bool r = doc.setContent(&fxml,
false, &errMsg, &errLine, &errCol);
159 _set_xml_read_error(
QString(
"XML parse error: %1 (file %2 line %3 col %4)")
160 .arg(errMsg).arg(xmlfname).arg(errLine).arg(errCol));
166 if (root.
nodeName() !=
"klfuserscript-info") {
167 _set_xml_parsing_error(xmlfname,
QString(
"expected <klfuserscript-info> as root document element"));
180 if ( n.
nodeType() != QDomNode::ElementNode ) {
198 }
else if (e.
nodeName() ==
"name") {
204 }
else if (e.
nodeName() ==
"author") {
206 }
else if (e.
nodeName() ==
"version") {
212 }
else if (e.
nodeName() ==
"license") {
218 }
else if (e.
nodeName() ==
"klf-min-version") {
220 _set_xml_parsing_error(xmlfname,
QString::fromLatin1(
"duplicate <klf-min-version> element"));
224 }
else if (e.
nodeName() ==
"klf-max-version") {
226 _set_xml_parsing_error(xmlfname,
QString::fromLatin1(
"duplicate <klf-max-version> element"));
230 }
else if (e.
nodeName() ==
"category") {
236 }
else if (e.
nodeName() ==
"settings-form-ui") {
238 _set_xml_parsing_error(xmlfname,
QString::fromLatin1(
"duplicate <settings-form-ui> element"));
242 }
else if (e.
nodeName() ==
"can-provide-default-settings") {
255 e.
save(tstream, 2); }
256 klfDbg(
"Read category-specific XML: " << xmlrepr);
290 QString normalizedfn = normalizedFn(userScriptFileName);
291 Private::userScriptInfoCache.remove(normalizedfn);
295 klfWarning(qPrintable(usinfo.scriptInfoErrorString()));
301 void KLFUserScriptInfo::clearCacheAll()
304 Private::userScriptInfoCache.clear();
309 bool KLFUserScriptInfo::hasScriptInfoInCache(
const QString& userScriptFileName)
311 QString normalizedfn = normalizedFn(userScriptFileName);
312 klfDbg(
"userScriptFileName = " << userScriptFileName <<
"; normalizedfn = " << normalizedfn) ;
313 klfDbg(
"cache: " << Private::userScriptInfoCache) ;
314 return Private::userScriptInfoCache.contains(normalizedfn);
323 if (Private::userScriptInfoCache.contains(normalizedfn)) {
324 d = Private::userScriptInfoCache[normalizedfn];
326 d =
new KLFUserScriptInfo::Private;
328 d()->uspath = normalizedfn;
329 d()->normalizedfname = normalizedfn;
333 d()->read_script_info();
336 Private::userScriptInfoCache[normalizedfn] = d();
348 KLFUserScriptInfo::~KLFUserScriptInfo()
363 return d()->basename;
366 int KLFUserScriptInfo::scriptInfoError()
const
368 return d()->scriptInfoError;
370 QString KLFUserScriptInfo::scriptInfoErrorString()
const
372 return d()->scriptInfoErrorString;
376 void KLFUserScriptInfo::setScriptInfoError(
int code,
const QString & msg)
378 d()->scriptInfoError = code;
379 d()->scriptInfoErrorString = msg;
382 QString KLFUserScriptInfo::relativeFile(
const QString& fname)
const
387 QString KLFUserScriptInfo::exeScript()
const {
return scriptInfo(ExeScript).
toString(); }
388 QString KLFUserScriptInfo::exeScriptFullPath()
const
390 return relativeFile(exeScript());
393 QString KLFUserScriptInfo::category()
const {
return scriptInfo(Category).
toString(); }
394 QString KLFUserScriptInfo::name()
const {
return scriptInfo(Name).
toString(); }
397 QString KLFUserScriptInfo::version()
const {
return scriptInfo(Version).
toString(); }
398 QString KLFUserScriptInfo::license()
const {
return scriptInfo(License).
toString(); }
399 QString KLFUserScriptInfo::klfMinVersion()
const {
return scriptInfo(KLFMinVersion).
toString(); }
400 QString KLFUserScriptInfo::klfMaxVersion()
const {
return scriptInfo(KLFMaxVersion).
toString(); }
403 bool KLFUserScriptInfo::canProvideDefaultSettings()
const {
return scriptInfo(CanProvideDefaultSettings).
toBool(); }
413 proc.setProcessAppEvents(
false);
420 proc.collectStdoutTo(&stdoutdata);
421 proc.collectStderrTo(&stderrdata);
423 bool ok = proc.run();
426 << qPrintable(proc.resultErrorString())) ;
430 klfDbg(
"stdoutdata = " << stdoutdata) ;
431 klfDbg(
"stderrdata = " << stderrdata) ;
445 QString errMsg;
int errLine, errCol;
446 bool r = doc.setContent(trimmedstdoutdata,
false, &errMsg, &errLine, &errCol);
448 klfWarning(
"XML parse error: "<<qPrintable(errMsg)
450 <<errLine<<
" col "<<errCol<<
")") ;
451 return QVariantMap();
455 if (root.
nodeName() !=
"klfuserscript-default-settings") {
456 klfWarning(
"expected <klfuserscript-default-settings> as root document element");
457 return QVariantMap();
474 klfWarning(
"Invalid line in reported userscript default config: " << line) ;
491 bool KLFUserScriptInfo::hasNotices()
const
493 return d->notices.size();
495 bool KLFUserScriptInfo::hasWarnings()
const
497 return d->warnings.size();
499 bool KLFUserScriptInfo::hasErrors()
const
501 return d->errors.size();
512 QVariant KLFUserScriptInfo::scriptInfo(
int propId)
const
514 return d()->property(propId);
527 int id = d()->propertyIdForName(x);
530 <<field<<
" ("<<x<<
")") ;
533 return scriptInfo(
id);
538 return d()->propertyNameList();
541 QString KLFUserScriptInfo::objectKind()
const {
return d()->objectKind(); }
545 void KLFUserScriptInfo::internalSetProperty(
const QString& key,
const QVariant &val)
547 d()->setProperty(key, val);
568 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
569 "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
570 "p, li { white-space: pre-wrap; }\n"
571 "p.msgnotice { color: blue; font-weight: bold; margin: 2px 0px; }\n"
572 "p.msgwarning { color: #a06000; font-weight: bold; margin: 2px 0px; }\n"
573 "p.msgerror { color: #a00000; font-weight: bold; margin: 2px 0px; }\n"
574 ".scriptinfokey { }\n"
575 ".scriptinfovalue { font-weight: bold; }\n"
582 txt += escapeListIntoTags(notices(),
"<p class=\"msgnotice\">",
"</p>\n");
585 txt += escapeListIntoTags(warnings(),
"<p class=\"msgwarning\">",
"</p>\n");
588 txt += escapeListIntoTags(errors(),
"<p class=\"msgerror\">",
"</p>\n");
593 "<p style=\"-qt-block-indent: 0; text-indent: 0px; margin-top: 8px; margin-bottom: 0px\">\n"
594 "<span class=\"scriptinfokey\">" +
QObject::tr(
"Script Name:",
"[[user script info text]]")
595 +
"</span> "
599 txt +=
"<span class=\"scriptinfokey\">" +
QObject::tr(
"Category:",
"[[user script info text]]")
600 +
"</span> "
601 "<span class=\"scriptinfovalue\">" + category().
toHtmlEscaped() +
"</span><br />\n";
603 if (!version().isEmpty()) {
605 txt +=
"<span class=\"scriptinfokey\">" +
QObject::tr(
"Version:",
"[[user script info text]]")
606 +
"</span> "
607 "<span class=\"scriptinfovalue\">" + version().
toHtmlEscaped() +
"</span><br />\n";
609 if (!author().isEmpty()) {
611 txt +=
"<span class=\"scriptinfokey\">" +
QObject::tr(
"Author:",
"[[user script info text]]")
612 +
"</span> "
613 "<span class=\"scriptinfovalue\">" + author().
toHtmlEscaped() +
"</span><br />\n";
616 if (!license().isEmpty()) {
618 txt +=
"<span class=\"scriptinfokey\">" +
QObject::tr(
"License:",
"[[user script info text]]")
619 +
"</span> "
620 "<span class=\"scriptinfovalue\">" + license().
toHtmlEscaped() +
"</span><br />\n";
632 for (QVariantMap::const_iterator it = usconfig.begin(); it != usconfig.end(); ++it)
638 QStringList KLFUserScriptInfo::usConfigToEnvList(
const QVariantMap& usconfig)
646 return val.
split(
QRegExp(
"\\s+"), QString::SkipEmptyParts);
666 for (
int k = 0; k < idlist.
size(); ++k) {
671 void _set_xml_parsing_error(
const QString& errmsg)
673 K->setScriptInfoError(1001,
QString(
"Error parsing klf-backend-engine XML config: %1: %2")
674 .arg(K->userScriptBaseName()).
arg(errmsg));
676 void parse_category_config(
const QByteArray & ba)
679 QString errMsg;
int errLine, errCol;
680 bool r = doc.setContent(ba,
false, &errMsg, &errLine, &errCol);
682 K->setScriptInfoError(
684 QString(
"XML parse error: %1 (klf-backend-engine in %2, relative line %3 col %4)")
685 .arg(errMsg).arg(K->userScriptBaseName()).
arg(errLine).
arg(errCol));
690 if (root.
nodeName() !=
"klf-backend-engine") {
691 _set_xml_parsing_error(
QString(
"expected <klf-backend-engine> element"));
702 if ( n.
nodeType() != QDomNode::ElementNode ) {
715 if (!
property(KLFBackendEngineUserScriptInfo::SpitsOut).toStringList().isEmpty()) {
716 _set_xml_parsing_error(
QString(
"duplicate <spits-out> element"));
719 setProperty(KLFBackendEngineUserScriptInfo::SpitsOut, space_sep_values(val));
720 }
else if (e.
nodeName() ==
"skip-formats") {
721 if (!
property(KLFBackendEngineUserScriptInfo::SkipFormats).
toString().isEmpty()) {
722 _set_xml_parsing_error(
QString(
"duplicate <skip-formats> element"));
729 lst << space_sep_values(s.
replace(
'-',
'_'));
731 lst << space_sep_values(val);
732 setProperty(KLFBackendEngineUserScriptInfo::SkipFormats, lst);
733 }
else if (e.
nodeName() ==
"disable-inputs") {
734 if (!
property(KLFBackendEngineUserScriptInfo::DisableInputs).toStringList().isEmpty()) {
735 _set_xml_parsing_error(
QString(
"duplicate <disable-inputs> element"));
742 lst << space_sep_values(s.
replace(
'-',
'_'));
744 lst << space_sep_values(val);
745 setProperty(KLFBackendEngineUserScriptInfo::DisableInputs, lst);
746 }
else if (e.
nodeName() ==
"input-form-ui") {
747 if (!
property(KLFBackendEngineUserScriptInfo::InputFormUI).toStringList().isEmpty()) {
748 _set_xml_parsing_error(
QString(
"duplicate <input-form-ui> element"));
751 setProperty(KLFBackendEngineUserScriptInfo::InputFormUI, val);
753 _set_xml_parsing_error(
QString(
"Found unexpected element: %1").arg(e.
nodeName()));
758 klfDbg(
"Read all klfbackend-engine properties:\n" << qPrintable(
toString()));
764 KLFBackendEngineUserScriptInfo::KLFBackendEngineUserScriptInfo(
const QString& uspath)
769 if (category() !=
"klf-backend-engine") {
770 klfWarning(
"KLFBackendEngineUserScriptInfo instantiated for user script "
771 << uspath <<
", which is of category " << category()) ;
777 KLFBackendEngineUserScriptInfo::~KLFBackendEngineUserScriptInfo()
790 return klfBackendEngineInfo(SkipFormats).
toStringList();
794 return klfBackendEngineInfo(DisableInputs).
toStringList();
798 return klfBackendEngineInfo(InputFormUI).
toString();
802 QVariant KLFBackendEngineUserScriptInfo::klfBackendEngineInfo(
int propId)
const
804 return d->property(propId);
807 QVariant KLFBackendEngineUserScriptInfo::klfBackendEngineInfo(
const QString& field)
const
813 int id = d->propertyIdForName(x);
815 klfDbg(
"KLFBackendEngineUserScriptInfo for "<<
userScriptName()<<
" does not have any information about "
816 <<field<<
" ("<<x<<
")") ;
819 return scriptInfo(
id);
822 QStringList KLFBackendEngineUserScriptInfo::klfBackendEngineInfosList()
const
824 return d->propertyNameList();
838 struct KLFUserScriptFilterProcessPrivate
859 klfDbg(
"userScriptFileName= "<<userScriptFileName) ;
865 QString exescript = d->usinfo->exeScriptFullPath();
866 klfDbg(
"exescript = " << exescript) ;
871 KLFUserScriptFilterProcess::~KLFUserScriptFilterProcess()
877 void KLFUserScriptFilterProcess::addUserScriptConfig(
const QVariantMap& usconfig)
879 QStringList envlist = KLFUserScriptInfo::usConfigToEnvList(usconfig);
880 addExecEnviron(envlist);
891 +d->usinfo->userScriptBaseName().toHtmlEscaped()
905 "<pre class=\"output\">%2</pre></p>\n") ;
908 if (bstdout.
size()) {
912 if (bstderr.
size()) {
917 if (KLFUserScriptFilterProcessPrivate::log.size() > 255) {
918 KLFUserScriptFilterProcessPrivate::log.
erase(KLFUserScriptFilterProcessPrivate::log.begin());
921 KLFUserScriptFilterProcessPrivate::log << thislog;
931 while (it != KLFUserScriptFilterProcessPrivate::log.cbegin()) {
939 "<meta charset=\"utf-8\">"
940 "<title>User Script Log</title>"
941 "<style type=\"text/css\">"
942 ".userscript-run { font-weight: bold; font-size: 2em; } "
943 ".userscriptname { font: monospace; } "
944 ".output-type { font-weight: bold; } "