123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518 |
- #include "main.h"
- #include "./addressEncoder.h"
- #include <wininet.h>
- #include <strsafe.h>
- typedef struct __ENCODEBUFFER
- {
- LPWSTR buffer;
- size_t bufferMax;
- LPWSTR cursor;
- size_t remaining;
- } ENCODEBUFFER;
- HRESULT AddressEncoder_ReAllocBuffer(ENCODEBUFFER *decoder, size_t cchBufferSize)
- {
- if (NULL == decoder)
- return E_INVALIDARG;
- if (cchBufferSize == decoder->bufferMax)
- return S_FALSE;
- if (cchBufferSize < decoder->bufferMax)
- return E_FAIL;
- LPWSTR test = Plugin_ReAllocString(decoder->buffer, cchBufferSize);
- if (NULL == test)
- return E_OUTOFMEMORY;
-
- decoder->cursor = test + (decoder->cursor - decoder->buffer);
- decoder->remaining += (cchBufferSize - decoder->bufferMax);
- decoder->buffer = test;
- decoder->bufferMax = cchBufferSize;
-
- return S_OK;
- }
- HRESULT AddressEncoder_AppendAnsiString(ENCODEBUFFER *decoder, LPCSTR pszString, size_t cchString)
- {
- if (NULL == decoder)
- return E_INVALIDARG;
- INT cchConverted;
- while(0 ==(cchConverted = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, pszString, (int)cchString, decoder->cursor, (int)decoder->remaining)))
- {
- DWORD errorCode = GetLastError();
- if (ERROR_INSUFFICIENT_BUFFER == errorCode)
- {
- INT cchNeed = MultiByteToWideChar(CP_UTF8, 0, pszString, (int)cchString, NULL, 0) - (INT)decoder->remaining;
- if (cchNeed < 32) cchNeed = 32;
- HRESULT hr = AddressEncoder_ReAllocBuffer(decoder, decoder->bufferMax + cchNeed);
- if (FAILED(hr))
- return hr;
- }
- else
- {
- return HRESULT_FROM_WIN32(errorCode);
- }
- }
- if (0 != cchConverted)
- {
- decoder->cursor += cchConverted;
- decoder->remaining -= cchConverted;
- }
- return S_OK;
- }
- HRESULT AddressEncoder_AppendString(ENCODEBUFFER *decoder, LPCWSTR pszString, size_t cchString)
- {
- if (NULL == decoder)
- return E_INVALIDARG;
- LPWSTR cursor;
- size_t remaining;
- HRESULT hr;
- if (cchString >= decoder->remaining)
- {
- hr = AddressEncoder_ReAllocBuffer(decoder, decoder->bufferMax + (cchString - decoder->remaining) + 1);
- if (FAILED(hr)) return hr;
- }
- hr = StringCchCopyNEx(decoder->cursor, decoder->remaining, pszString, cchString, &cursor, &remaining, 0);
- if (SUCCEEDED(hr))
- {
- decoder->cursor = cursor;
- decoder->remaining = remaining;
- }
- return hr;
- }
- HRESULT AddressEncoder_GetEscapeBlock(LPCWSTR pszEscape, LPCWSTR *ppszEnd, size_t *pcchEscapeLen, LPSTR pszBuffer, UINT *pcbBufferMax)
- {
- if (NULL == pszEscape || (NULL != pszBuffer && NULL == pcbBufferMax))
- return E_INVALIDARG;
- UINT cbBinary = 0;
- WORD charInfo;
- WCHAR szDigit[3] = {0};
- HRESULT hr = S_OK;
- LPCWSTR cursor = pszEscape;
- while (L'%' == *cursor)
- {
- LPCWSTR testChar = CharNext(cursor);
- if (L'\0' == *testChar ||
- FALSE == GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, testChar, 1, &charInfo) ||
- 0 == (C1_XDIGIT & charInfo))
- {
- break;
- }
- szDigit[0] = *testChar;
- testChar = CharNext(testChar);
- if (L'\0' == *testChar ||
- FALSE == GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, testChar, 1, &charInfo) ||
- 0 == (C1_XDIGIT & charInfo))
- {
- break;
- }
- szDigit[1] = *testChar;
- CharUpperBuff(szDigit, 2);
- BYTE binaryData = ((szDigit[0] - ((szDigit[0] <= L'9' ? L'0' : L'A' - 10))) << 4) & 0xf0;
- binaryData += (szDigit[1] - ((szDigit[1] <= L'9' ? L'0' : L'A' - 10))) & 0x0f;
- if (NULL != pszBuffer)
- {
- if (cbBinary < *pcbBufferMax)
- pszBuffer[cbBinary] = binaryData;
- else
- hr = E_OUTOFMEMORY;
- }
- cbBinary++;
- cursor = CharNext(testChar);
- }
- if (cursor == pszEscape)
- hr = HRESULT_FROM_WIN32(ERROR_INVALID_BLOCK_LENGTH);
- if (NULL != ppszEnd)
- *ppszEnd = cursor;
-
- if (NULL != pcchEscapeLen)
- *pcchEscapeLen = (size_t)(cursor - pszEscape);
- if (NULL != pcbBufferMax)
- *pcbBufferMax = cbBinary;
-
- return hr;
- }
- HRESULT AddressEncoder_DecodeString(LPCWSTR pszUrl, LPWSTR *ppResult)
- {
- if (NULL == pszUrl)
- {
- *ppResult = NULL;
- return S_FALSE;
- }
- UINT cchUrl = 0;
- UINT escapeSize = 0;
- UINT escapeBlockSize,escapeBlockMaxSize = 0;
- LPCWSTR escapeBlockEnd;
- for (LPCWSTR cursor = pszUrl; L'\0' != *cursor;)
- {
- if (L'%' == *cursor && SUCCEEDED(AddressEncoder_GetEscapeBlock(cursor, &escapeBlockEnd, NULL, NULL, &escapeBlockSize)))
- {
- escapeSize += escapeBlockSize;
- if (escapeBlockSize > escapeBlockMaxSize)
- escapeBlockMaxSize = escapeBlockSize;
- cursor = escapeBlockEnd;
- }
- else
- {
- cchUrl++;
- cursor = CharNext(cursor);
- }
- }
- if (0 == escapeSize)
- {
- *ppResult = Plugin_CopyString(pszUrl);
- if (NULL == *ppResult) return E_OUTOFMEMORY;
- return S_FALSE;
- }
- HRESULT hr = S_OK;
-
- ENCODEBUFFER decoder;
- ZeroMemory(&decoder, sizeof(decoder));
-
- LPSTR escapeBuffer = Plugin_MallocAnsiString(escapeBlockMaxSize);
- if (NULL == escapeBuffer)
- {
- hr = E_OUTOFMEMORY;
- }
- else
- {
- hr = AddressEncoder_ReAllocBuffer(&decoder, cchUrl + (escapeSize + 1)* sizeof(WCHAR));
- if (SUCCEEDED(hr))
- {
- LPCWSTR cursor = pszUrl;
- LPCWSTR copyBlock = cursor;
-
- for (;;)
- {
- escapeBlockSize = escapeBlockMaxSize;
- if (L'%' == *cursor && SUCCEEDED(AddressEncoder_GetEscapeBlock(cursor, &escapeBlockEnd, NULL, escapeBuffer, &escapeBlockSize)))
- {
- if (copyBlock != cursor)
- {
- hr = AddressEncoder_AppendString(&decoder, copyBlock, cursor - copyBlock);
- if (FAILED(hr))
- break;
- copyBlock = cursor;
- }
- HRESULT convertResult = AddressEncoder_AppendAnsiString(&decoder, escapeBuffer, escapeBlockSize);
- if (L'\0' == *cursor)
- break;
-
- cursor = escapeBlockEnd;
- if (SUCCEEDED(convertResult))
- {
- copyBlock = cursor;
- }
-
-
-
- continue;
- }
-
- if (L'\0' == *cursor)
- {
- if (copyBlock != cursor)
- hr = AddressEncoder_AppendString(&decoder, copyBlock, cursor - copyBlock);
- break;
- }
- else
- cursor = CharNext(cursor);
- }
- }
- }
- if (NULL != escapeBuffer)
- Plugin_FreeAnsiString(escapeBuffer);
- if (FAILED(hr))
- {
- Plugin_FreeString(decoder.buffer);
- decoder.buffer = NULL;
- }
- else
- {
- *decoder.cursor = L'\0';
- }
- *ppResult = decoder.buffer;
-
- return hr;
- }
- HRESULT AddressEncoder_GetWideBlock(LPCWSTR pszWide, LPCWSTR *pszEnd, LPWSTR pszBuffer, size_t *pcchBufferMax)
- {
- LPCWSTR cursor = pszWide;
- if (NULL == pszWide)
- return E_INVALIDARG;
-
- if (NULL != pszBuffer && NULL == pcchBufferMax)
- return E_INVALIDARG;
-
- while (L'\0' == *cursor || *cursor > 0xFF)
- {
- if (L'\0' == *cursor)
- break;
- cursor = CharNext(cursor);
- }
- if (NULL != pszEnd)
- *pszEnd = cursor;
- HRESULT hr = S_OK;
- size_t cchBuffer = 0;
- if (cursor == pszWide)
- {
- hr = S_FALSE;
- }
- else
- {
- size_t bytesCount = WideCharToMultiByte(CP_UTF8, 0, pszWide, (int)(cursor - pszWide), NULL, 0, NULL, NULL);
- if (0 == bytesCount)
- {
- DWORD errorCode = GetLastError();
- if (ERROR_SUCCESS != errorCode)
- hr = HRESULT_FROM_WIN32(errorCode);
- }
- else
- {
- cchBuffer = 3 * bytesCount;
- if (NULL != pszBuffer)
- {
- if (*pcchBufferMax >= cchBuffer)
- {
- LPWSTR p = pszBuffer;
- BYTE *bytes = ((BYTE*)(pszBuffer + *pcchBufferMax)) - bytesCount;
- WideCharToMultiByte(CP_UTF8, 0, pszWide, (int)(cursor - pszWide), (LPSTR)bytes, (int)bytesCount, NULL, NULL);
- for (size_t i = 0; i < bytesCount; i++)
- {
- BYTE b = bytes[i];
- *p++ = L'%';
- BYTE c = (b >> 4) & 0x0F;
- *p++ = (c < 10) ? (L'0' + c) : (L'A' + (c -10));
- c = b & 0x0F;
- *p++ = (c < 10) ? (L'0' + c) : (L'A' + (c -10));
- }
- }
- else
- {
- hr = E_OUTOFMEMORY;
- }
- }
- }
- }
- if (NULL != pcchBufferMax)
- {
- *pcchBufferMax = cchBuffer;
- }
- return hr;
- }
- HRESULT AddressEncoder_EncodeWideChars(LPCWSTR pszAddress, size_t cchAddress, LPWSTR *ppResult)
- {
- if (NULL == ppResult)
- return E_POINTER;
-
- if (NULL == pszAddress)
- {
- *ppResult = NULL;
- return S_FALSE;
- }
- LPCWSTR blockEnd;
- size_t blockSize;
- size_t cchResultMax = 0;
- BOOL needEncode = FALSE;
- for (LPCWSTR cursor = pszAddress; L'\0' != *cursor;)
- {
- if (*cursor > 0xFF && SUCCEEDED(AddressEncoder_GetWideBlock(cursor, &blockEnd, NULL, &blockSize)))
- {
- cursor = blockEnd;
- cchResultMax += blockSize;
- needEncode = TRUE;
- }
- else
- {
- cursor = CharNext(cursor);
- cchResultMax++;
- }
- }
- if (FALSE == needEncode)
- {
- *ppResult = NULL;
- return S_FALSE;
- }
- HRESULT hr;
- cchResultMax++;
- LPWSTR result = Plugin_MallocString(cchResultMax);
- if (NULL == result)
- hr = E_OUTOFMEMORY;
- else
- {
- LPWSTR cursor = result;
- size_t remaining = cchResultMax;
- LPCWSTR address = pszAddress;
- LPCWSTR addressBlock = address;
- for (;;)
- {
- if (*address > 0xFF)
- {
- if (addressBlock != address)
- {
- hr = StringCchCopyNEx(cursor, remaining, addressBlock, (size_t)(address - addressBlock), &cursor, &remaining, 0);
- if (FAILED(hr)) break;
- }
- blockSize = remaining;
- hr = AddressEncoder_GetWideBlock(address, &address, cursor, &blockSize);
- if (FAILED(hr)) break;
- cursor += blockSize;
- remaining -= blockSize;
- addressBlock = address;
- continue;
- }
-
- if (L'\0' == *address)
- {
- if (addressBlock != address)
- {
- hr = StringCchCopyNEx(cursor, remaining, addressBlock, (size_t)(address - addressBlock), &cursor, &remaining, 0);
- }
- break;
- }
- else
- address = CharNext(address);
- }
- *cursor = L'\0';
- }
-
- if (FAILED(hr))
- {
- Plugin_FreeString(result);
- result = NULL;
- }
- *ppResult = result;
- return hr;
- }
- HRESULT AddressEncoder_EncodeString(LPCWSTR pszAddress, LPWSTR pszBuffer, size_t *pcchBufferMax, UINT flags)
- {
- if (NULL == pszBuffer || NULL == pcchBufferMax)
- return E_INVALIDARG;
-
- if (NULL == pszAddress || L'\0' == *pszAddress)
- {
- *pszBuffer = L'\0';
- *pcchBufferMax = 0;
- return S_OK;
- }
- INT cchAddress = lstrlen(pszAddress);
- LPCWSTR begin, end;
- begin = pszAddress;
- end = pszAddress + cchAddress;
- WORD charType;
- while (L'\0' != *begin &&
- FALSE != GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, begin, 1, &charType) && 0 != (C1_SPACE & charType))
- {
- begin = CharNext(begin);
- }
- while (begin != end &&
- FALSE != GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE1, begin, 1, &charType) && 0 != (C1_SPACE & charType))
- {
- end = CharPrev(begin, end);
- }
- if (end <= begin)
- {
- *pszBuffer = L'\0';
- *pcchBufferMax = 0;
- return S_OK;
- }
- LPWSTR encoded;
- HRESULT hr = AddressEncoder_EncodeWideChars(begin, (end - begin), &encoded);
- if (FAILED(hr)) return hr;
- if (S_OK == hr)
- {
- begin = encoded;
- end = begin + lstrlen(begin);
- }
-
- DWORD bufferLen = (DWORD)(*pcchBufferMax);
- if (FALSE == InternetCanonicalizeUrl(begin, pszBuffer, &bufferLen, flags))
- {
- DWORD errorCode = GetLastError();
- if (ERROR_INSUFFICIENT_BUFFER == errorCode)
- {
- *pcchBufferMax = bufferLen;
- hr = ENC_E_INSUFFICIENT_BUFFER;
- }
- else
- {
- size_t cchNeeded = (end - begin);
- if (cchNeeded < *pcchBufferMax)
- {
- hr = StringCchCopyN(pszBuffer, *pcchBufferMax, begin, cchNeeded);
- if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
- {
- hr = ENC_E_INSUFFICIENT_BUFFER;
- }
- }
- else
- {
- hr = ENC_E_INSUFFICIENT_BUFFER;
- }
- *pcchBufferMax = cchNeeded + 1;
- }
- }
- else
- hr = S_OK;
-
-
- Plugin_FreeString(encoded);
- return hr;
- }
|