diff --git a/src/Edit.c b/src/Edit.c index 23b3e91c8..626986220 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -1467,7 +1467,7 @@ void EditURLEncode(HWND hwnd) } cchEscapedW = (int)LocalSize(pszEscapedW) / sizeof(WCHAR); - UrlEscape(pszTextW,pszEscapedW,&cchEscapedW,URL_ESCAPE_SEGMENT_ONLY); + UrlEscape(pszTextW, pszEscapedW, &cchEscapedW, URL_ESCAPE_SEGMENT_ONLY | URL_ESCAPE_AS_UTF8); cchEscaped = WideCharToMultiByte(cpEdit,0,pszEscapedW,cchEscapedW,pszEscaped,(int)LocalSize(pszEscaped),NULL,NULL); @@ -1551,7 +1551,8 @@ void EditURLDecode(HWND hwnd) } cchUnescapedW = (int)LocalSize(pszUnescapedW) / sizeof(WCHAR); - UrlUnescape(pszTextW,pszUnescapedW,&cchUnescapedW,0); + + UrlUnescapeEx(pszTextW, pszUnescapedW, &cchUnescapedW); cchUnescaped = WideCharToMultiByte(cpEdit,0,pszUnescapedW,cchUnescapedW,pszUnescaped,(int)LocalSize(pszUnescaped),NULL,NULL); diff --git a/src/Helpers.c b/src/Helpers.c index 7034ccc44..39b710474 100644 --- a/src/Helpers.c +++ b/src/Helpers.c @@ -3580,6 +3580,87 @@ INT UTF8_mbslen(LPCSTR source,INT byte_length) return wchar_length; } + + +/** +* Is the character an octal digit? +*/ +static BOOL IsDigit(WCHAR wch) +{ + return ((wch >= L'0') && (wch <= L'9')); +} + + + +//============================================================================= +// +// UrlUnescapeEx() +// +void UrlUnescapeEx(LPWSTR lpURL, LPWSTR lpUnescaped, DWORD* pcchUnescaped) +{ +#if defined(URL_UNESCAPE_AS_UTF8) + UrlUnescape(lpURL, lpUnescaped, pcchUnescaped, URL_UNESCAPE_AS_UTF8); +#else + int posOut = 0; + char* outBuffer = LocalAlloc(LPTR, *pcchUnescaped + 1); + if (outBuffer == NULL) { + return; + } + int outLen = (int)LocalSize(outBuffer) - 1; + + int posIn = 0; + WCHAR buf[5] = { L'\0' }; + int lastEsc = lstrlen(lpURL) - 2; + int code; + + while ((posIn < lastEsc) && (posOut < outLen)) + { + BOOL bOk = FALSE; + if (lpURL[posIn] == L'%') { + buf[0] = lpURL[posIn + 1]; + buf[1] = lpURL[posIn + 2]; + buf[2] = L'\0'; + if (swscanf_s(buf, L"%x", &code) == 1) { + outBuffer[posOut++] = (char)code; + posIn += 3; + bOk = TRUE; + } + else if (lpURL[posIn + 1] == L'#') { + int n = 0; + while (IsDigit(lpURL[posIn + 2 + n]) && (n < 4)) { + buf[n] = lpURL[posIn + 2 + n]; + ++n; + } + buf[n] = L'\0'; + if (swscanf_s(buf, L"%i", &code) == 1) { + outBuffer[posOut++] = (char)code; + posIn += (2 + n); + if (lpURL[posIn] == L';') ++posIn; + bOk = TRUE; + } + } + } + if (!bOk) { + posOut += WideCharToMultiByte(CP_UTF8, 0, &(lpURL[posIn++]), 1, &(outBuffer[posOut]), (int)(outLen - posOut), NULL, NULL); + } + } + + // copy rest + while ((lpURL[posIn] != L'\0') && (posOut < outLen)) + { + posOut += WideCharToMultiByte(CP_UTF8, 0, &(lpURL[posIn++]), 1, &(outBuffer[posOut]), (int)(outLen - posOut), NULL, NULL); + } + outBuffer[posOut] = '\0'; + + int iOut = MultiByteToWideChar(CP_UTF8, 0, outBuffer, -1, lpUnescaped, (int)*pcchUnescaped); + LocalFree(outBuffer); + + *pcchUnescaped = ((iOut > 0) ? (iOut - 1) : 0); +#endif +} + + + /////////////////////////////////////////////////////////////////////////////// // // Drag N Drop helpers diff --git a/src/Helpers.h b/src/Helpers.h index 15ae6c687..651a5ad8c 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -106,6 +106,7 @@ enum BufferSizes { MIDSZ_BUFFER = 256, LARGE_BUFFER = 512, HUGE_BUFFER = 1024, + XHUGE_BUFFER = 2048, FILE_ARG_BUF = MAX_PATH+4 }; @@ -425,6 +426,9 @@ BOOL IsUTF7(const char*,int); INT UTF8_mbslen_bytes(LPCSTR utf8_string); INT UTF8_mbslen(LPCSTR source,INT byte_length); + +void UrlUnescapeEx(LPWSTR, LPWSTR, DWORD*); + // -------------------------------------------------------------------------------------------------------------------------------- // including and linking against pathcch.lib