diff --git a/Source/script.cpp b/Source/script.cpp index fe5174d1..b70a0e39 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -4128,33 +4128,32 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) return add_entry(&ent); case TOK_SETOUTPATH: { - const TCHAR *op=line.gettoken_str(1); + const TCHAR *op=line.gettoken_str(1), *cmdname=_T("SetOutPath"); if (!_tcscmp(op,_T("-"))) op=_T("$INSTDIR"); - - SCRIPT_MSG(_T("SetOutPath: \"%") NPRIs _T("\"\n"),op); + SCRIPT_MSG(_T("%") NPRIs _T(": \"%") NPRIs _T("\"\n"),cmdname,op); ent.which=EW_CREATEDIR; ent.offsets[0]=add_string(op); ent.offsets[1]=1; - DefineInnerLangString(NLF_OUTPUT_DIR); } return add_entry(&ent); case TOK_CREATEDIR: { + const TCHAR *cmdname=_T("CreateDirectory"); TCHAR out_path[NSIS_MAX_STRLEN], *p=line.gettoken_str(1); - if (*p == _T('-')) out_path[0]=0; + bool badpath=IsWindowsPathRelative(p) && _T('$') != *p; // ExeHead will have to deal with expanded $variables... + if (badpath) + ERROR_MSG(_T("%") NPRIs _T(": Relative paths not supported\n"),cmdname); else { - if (p[0] == _T('\\') && p[1] != _T('\\')) p++; my_strncpy(out_path,p,COUNTOF(out_path)); p=CharPrev(out_path,out_path+_tcslen(out_path)); - if (_T('\\') == *p || _T('/') == *p) *p=0; // remove trailing slash + if (IsAgnosticPathSeparator(*p)) *p=0; // remove trailing slash } - if (!*out_path) PRINTHELP() - SCRIPT_MSG(_T("CreateDirectory: \"%") NPRIs _T("\"\n"),out_path); + if (badpath || !*out_path) PRINTHELP() + SCRIPT_MSG(_T("%") NPRIs _T(": \"%") NPRIs _T("\"\n"),cmdname,out_path); ent.which=EW_CREATEDIR; ent.offsets[0]=add_string(out_path); - DefineInnerLangString(NLF_CREATE_DIR); } return add_entry(&ent); diff --git a/Source/util.cpp b/Source/util.cpp index 270a883b..e8f976e6 100644 --- a/Source/util.cpp +++ b/Source/util.cpp @@ -718,6 +718,22 @@ tstring remove_file_extension(const tstring& path) { return get_string_prefix(path, _T(".")); } +static int PathGetDosDriveNumber(const TCHAR *p) +{ + // Note: Unlike PathGetDriveNumber(), we require a path separator after the colon. + if (p[0] && _T(':') == p[1] && IsAgnosticPathSeparator(p[2])) + { + const TCHAR loch = p[0]|32; + if (loch >= _T('a') && loch <= _T('z')) return loch - _T('a'); + } + return -1; +} +bool IsWindowsPathRelative(const TCHAR *p) +{ + if (_T('\\') == p[0]) return _T('\\') != p[1]; // Current drive relative, not (unverified) UNC + return PathGetDosDriveNumber(p) < 0; +} + struct ToLower { TCHAR operator() (TCHAR c) const { return _totlower(c); } diff --git a/Source/util.h b/Source/util.h index d0cd9bce..a990334d 100644 --- a/Source/util.h +++ b/Source/util.h @@ -47,11 +47,12 @@ tstring get_dir_name(const tstring& path); tstring get_file_name(const tstring& path); tstring get_executable_dir(const TCHAR *argv0); tstring remove_file_extension(const tstring& path); -tstring lowercase(const tstring&); +inline bool IsAgnosticPathSeparator(const TCHAR c) { return _T('\\') == c || _T('/') == c; } +bool IsWindowsPathRelative(const TCHAR *p); +tstring lowercase(const tstring&); tstring get_string_prefix(const tstring& str, const tstring& separator); tstring get_string_suffix(const tstring& str, const tstring& separator); - void RawTStrToASCII(const TCHAR*in,char*out,UINT maxcch); size_t ExpandoStrFmtVaList(wchar_t*Stack, size_t cchStack, wchar_t**ppMalloc, const wchar_t*FmtStr, va_list Args);