From e004b5893e21cbd251553a3de06955b95baf2728 Mon Sep 17 00:00:00 2001 From: anders_k Date: Tue, 25 Apr 2017 13:58:43 +0000 Subject: [PATCH] Use a internal command to detect the CHM header because the !searchparse hack fails with a encoding error if the ACP codepage is 936. git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6853 212acab6-be3b-0410-9dea-997c60f758d6 --- Examples/makensis.nsi | 2 +- Source/build.cpp | 26 ++++++++++++++++++++------ Source/script.cpp | 3 +-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Examples/makensis.nsi b/Examples/makensis.nsi index 3a47f449..904fdfe2 100644 --- a/Examples/makensis.nsi +++ b/Examples/makensis.nsi @@ -161,7 +161,7 @@ ${MementoSection} "NSIS Core Files (required)" SecCore File ..\makensisw.exe File ..\COPYING File ..\NSIS.chm - !searchparse /file "..\NSIS.chm" "ITSF" VALIDATE_CHM + !pragma verifychm "..\NSIS.chm" File ..\NSIS.exe !if /FileExists "..\NSIS.exe.manifest" File "..\NSIS.exe.manifest" diff --git a/Source/build.cpp b/Source/build.cpp index 0855d5a7..5ca55213 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -30,6 +30,7 @@ #include "crc32.h" #include "manifest.h" #include "icon.h" +#include "utf.h" // For NStream #include "exehead/api.h" #include "exehead/resource.h" @@ -3408,18 +3409,31 @@ void CEXEBuild::set_verbosity(int lvl) int CEXEBuild::parse_pragma(LineParser &line) { - if (line.gettoken_enum(1, _T("warning\0")) == -1) - return (warning_fl(DW_PP_PRAGMA_UNKNOWN, _T("Unknown pragma")), PS_ERROR); + const int rvSucc = PS_OK, rvWarn = PS_WARNING, rvErr = PS_WARNING; // rvErr is not PS_ERROR because we want !pragma parsing to be very forgiving. - int warnOp = line.gettoken_enum(2, _T("disable\0enable\0default\0push\0pop\0")), ret = PS_OK; + // 2.47 shipped with a corrupted CHM file (bug #1129). This minimal verification command exists because the !searchparse hack we added does not work with codepage 936! + if (line.gettoken_enum(1, _T("verifychm\0")) == 0) + { + struct { UINT32 Sig, Ver, cbH; } chm; + NIStream f; + bool valid = f.OpenFileForReading(line.gettoken_str(2)); + valid = valid && 12 == f.ReadOctets(&chm, 12); + valid = valid && FIX_ENDIAN_INT32(chm.Sig) == 0x46535449 && (FIX_ENDIAN_INT32(chm.Ver)|1) == 3; // 'ITSF' v2..3 + return valid ? rvSucc : (ERROR_MSG(_T("Invalid format\n")), PS_ERROR); + } + + if (line.gettoken_enum(1, _T("warning\0")) == -1) + return (warning_fl(DW_PP_PRAGMA_UNKNOWN, _T("Unknown pragma")), rvErr); + + int warnOp = line.gettoken_enum(2, _T("disable\0enable\0default\0push\0pop\0")), ret = rvSucc; if (warnOp < 0) - ret = PS_ERROR, warning_fl(DW_PP_PRAGMA_UNKNOWN, _T("Unknown pragma")); // Unknown warning pragma action + ret = rvErr, warning_fl(DW_PP_PRAGMA_UNKNOWN, _T("Unknown pragma")); // Unknown warning pragma action else if (warnOp == 3) diagstate.Push(); else if (warnOp == 4) { if (!diagstate.Pop()) - ret = PS_WARNING, warning_fl(DW_PP_PRAGMA_INVALID, _T("Unexpected")); + ret = rvWarn, warning_fl(DW_PP_PRAGMA_INVALID, _T("Unexpected")); } else // warning: disable/enable/default { @@ -3427,7 +3441,7 @@ int CEXEBuild::parse_pragma(LineParser &line) { DIAGCODE code = static_cast(line.gettoken_int(ti)); if (!diagstate.IsValidCode(code)) - ret = PS_WARNING, warning_fl(DW_PP_PRAGMA_INVALID, _T("Invalid number: \"%") NPRIs _T("\""), line.gettoken_str(ti)); + ret = rvWarn, warning_fl(DW_PP_PRAGMA_INVALID, _T("Invalid number: \"%") NPRIs _T("\""), line.gettoken_str(ti)); else if (warnOp == 0) diagstate.Disable(code); else // if ((warnOp == 1) | (warnOp == 2)) All warnings currently default to enabled diff --git a/Source/script.cpp b/Source/script.cpp index d361afa8..e524f4c0 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -3367,8 +3367,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) } return PS_OK; case TOK_P_PRAGMA: - parse_pragma(line); // Never abort with ERROR_MSG, even if the pragma is unknown/invalid - return PS_OK; + return parse_pragma(line) == PS_ERROR ? PS_ERROR : PS_OK; case TOK_P_ERROR: ERROR_MSG(_T("!error: %") NPRIs _T("\n"),line.gettoken_str(1)); return PS_ERROR;