Merge pull request #3143 from RaiKoHoff/Dev_Release

Fix URL-Decoding of file Hyperlinks ("file://...")
This commit is contained in:
Rainer Kottenhoff 2021-02-26 15:20:55 +01:00 committed by GitHub
commit ecf898b64b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 34 deletions

View File

@ -642,6 +642,40 @@ inline WCHAR* StrEndW(const WCHAR* pStart, size_t siz)
#define StrEnd(s,n) StrEndA((s),(n))
#endif
// ----------------------------------------------------------------------------
#if 0
inline void StrReplChrA(CHAR* pStrg, const CHAR chSearch, const CHAR chReplace)
{
while (pStrg && *pStrg) {
if (*pStrg == chSearch) {
*pStrg = chReplace;
}
++pStrg;
}
}
inline void StrReplChrW(WCHAR* pStrg, const WCHAR chSearch, const WCHAR chReplace)
{
while (pStrg && *pStrg) {
if (*pStrg == chSearch) {
*pStrg = chReplace;
}
++pStrg;
}
}
#if defined(UNICODE) || defined(_UNICODE)
#define StrReplChr(str, cs, cr) StrReplChrW((str), (cs), (cr))
#else
#define StrReplChr(str, cs, cr) StrReplChrA((str), (cs), (cr))
#endif
#endif
// ----------------------------------------------------------------------------
//==== StrSafe lstrcmp(),lstrcmpi() =============================================
// NOTE: !!! differences in AutoCompleteList depending compare functions (CRT vs. Shlwapi)) !!!

View File

@ -7064,6 +7064,7 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio
bool bHandled = false;
if (SciCall_IndicatorValueAt(INDIC_NP3_HYPERLINK, position)) {
DocPos const firstPos = SciCall_IndicatorStart(INDIC_NP3_HYPERLINK, position);
DocPos const lastPos = SciCall_IndicatorEnd(INDIC_NP3_HYPERLINK, position);
DocPos const length = min_p(lastPos - firstPos, INTERNET_MAX_URL_LENGTH);
@ -7072,14 +7073,15 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio
return false;
}
const char* pszText = (const char*)SciCall_GetRangePointer(firstPos, length);
const char *pszText = (const char *)SciCall_GetRangePointer(firstPos, length);
WCHAR szTextW[INTERNET_MAX_URL_LENGTH + 1];
ptrdiff_t const cchTextW = MultiByteToWideChar(Encoding_SciCP, 0, pszText, (int)length, szTextW, COUNTOF(szTextW));
szTextW[cchTextW] = L'\0';
StrTrim(szTextW, L" \r\n\t");
const WCHAR* chkPreFix = L"file://";
const WCHAR *chkPreFix = L"file://";
size_t const lenPfx = StringCchLenW(chkPreFix, 0);
if (operation & SELECT_HYPERLINK) {
SciCall_SetSelection(firstPos, lastPos);
@ -7096,42 +7098,63 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio
bHandled = true;
}
}
} else if ((operation & OPEN_WITH_NOTEPAD3) && (StrStrI(szTextW, chkPreFix) == szTextW)) {
size_t const lenPfx = StringCchLenW(chkPreFix, 0);
WCHAR* szFileName = &(szTextW[lenPfx]);
szTextW[lenPfx + MAX_PATH] = L'\0'; // limit length
StrTrim(szFileName, L"/");
PathCanonicalizeEx(szFileName, (DWORD)(COUNTOF(szTextW) - lenPfx));
if (PathIsDirectory(szFileName)) {
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szFileName)) {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
} else {
bool const isFileUrl = (StrStrI(szTextW, chkPreFix) == szTextW);
WCHAR szUnEscW[INTERNET_MAX_URL_LENGTH + 1];
DWORD dCchUnEsc = COUNTOF(szUnEscW);
UrlUnescapeEx(szTextW, szUnEscW, &dCchUnEsc);
if ((operation & OPEN_WITH_NOTEPAD3) && isFileUrl) {
WCHAR *const szFileName = &(szUnEscW[lenPfx]);
szUnEscW[min_i(MAX_PATH, INTERNET_MAX_URL_LENGTH)] = L'\0'; // limit length
StrTrim(szFileName, L"/");
PathCanonicalizeEx(szFileName, (DWORD)(COUNTOF(szUnEscW) - lenPfx));
if (PathIsDirectory(szFileName)) {
WCHAR tchFile[MAX_PATH] = { L'\0' };
if (OpenFileDlg(Globals.hwndMain, tchFile, COUNTOF(tchFile), szFileName)) {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, tchFile);
}
} else {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szFileName);
}
} else {
FileLoad(false, false, false, Settings.SkipUnicodeDetection, Settings.SkipANSICodePageDetection, false, szFileName);
}
bHandled = true;
} else if (operation & OPEN_WITH_BROWSER) { // open in web browser
WCHAR wchDirectory[MAX_PATH] = { L'\0' };
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(wchDirectory, COUNTOF(wchDirectory), Globals.CurrentFile);
PathCchRemoveFileSpec(wchDirectory, COUNTOF(wchDirectory));
}
bHandled = true;
SHELLEXECUTEINFO sei;
ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOZONECHECKS;
sei.hwnd = NULL;
sei.lpVerb = NULL;
sei.lpFile = szTextW;
sei.lpParameters = NULL;
sei.lpDirectory = wchDirectory;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
} else if (operation & OPEN_WITH_BROWSER) { // open in web browser
bHandled = true;
if (isFileUrl) {
WCHAR *const szFileName = &(szUnEscW[lenPfx]);
dCchUnEsc = COUNTOF(szTextW);
UrlCreateFromPath(szFileName, szTextW, &dCchUnEsc, 0);
//~StringCchCopy(szUnEscW, COUNTOF(szUnEscW), L"http://");
//~StringCchCat(szUnEscW, COUNTOF(szUnEscW), &(szTextW[lenPfx]));
StringCchCopy(szUnEscW, COUNTOF(szUnEscW), szTextW);
}
WCHAR wchDirectory[MAX_PATH] = { L'\0' };
if (StrIsNotEmpty(Globals.CurrentFile)) {
StringCchCopy(wchDirectory, COUNTOF(wchDirectory), Globals.CurrentFile);
PathCchRemoveFileSpec(wchDirectory, COUNTOF(wchDirectory));
}
SHELLEXECUTEINFO sei;
ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOZONECHECKS;
sei.hwnd = NULL;
sei.lpVerb = NULL;
sei.lpFile = szUnEscW;
sei.lpParameters = NULL;
sei.lpDirectory = wchDirectory;
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
bHandled = true;
}
}
}