20#include <winpr/config.h>
21#include <winpr/assert.h>
31#include <winpr/endian.h>
33#if defined(WITH_URIPARSER)
34#include <uriparser/Uri.h>
40#define TAG WINPR_TAG("crt")
42#if defined(WITH_URIPARSER)
43char* winpr_str_url_decode(
const char* str,
size_t len)
45 char* dst = strndup(str, len);
49 if (!uriUnescapeInPlaceExA(dst, URI_FALSE, URI_BR_DONT_TOUCH))
58char* winpr_str_url_encode(
const char* str,
size_t len)
60 char* dst = calloc(len + 1,
sizeof(
char) * 3);
64 if (!uriEscapeA(str, dst, URI_FALSE, URI_FALSE))
73static const char rfc3986[] = {
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2e, 0x00,
77 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
79 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
80 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
81 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x7e, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92static char hex2bin(
char what)
103static char unescape(
const char* what,
size_t* px)
105 if ((*what ==
'%') && (isxdigit(what[1]) && isxdigit(what[2])))
108 return 16 * hex2bin(what[1]) + hex2bin(what[2]);
114char* winpr_str_url_decode(
const char* str,
size_t len)
116 char* dst = calloc(len + 1,
sizeof(
char));
121 for (
size_t x = 0; x < strnlen(str, len); x++)
123 const char* cur = &str[x];
124 dst[pos++] = unescape(cur, &x);
129static char* escape(
char* dst,
char what)
131 if (rfc3986[what & 0xff])
137 sprintf(dst,
"%%%02" PRIX8, (BYTE)(what & 0xff));
141char* winpr_str_url_encode(
const char* str,
size_t len)
143 char* dst = calloc(len + 1,
sizeof(
char) * 3);
148 for (
size_t x = 0; x < strnlen(str, len); x++)
150 const char cur = str[x];
151 ptr = escape(ptr, cur);
157BOOL winpr_str_append(
const char* what,
char* buffer,
size_t size,
const char* separator)
159 const size_t used = strnlen(buffer, size);
160 const size_t add = strnlen(what, size);
161 const size_t sep_len = separator ? strnlen(separator, size) : 0;
162 const size_t sep = (used > 0) ? sep_len : 0;
164 if (used + add + sep >= size)
167 if ((used > 0) && (sep_len > 0))
168 strncat(buffer, separator, sep_len);
170 strncat(buffer, what, add);
174WINPR_ATTR_FORMAT_ARG(3, 4)
175int winpr_asprintf(
char** s,
size_t* slen, WINPR_FORMAT_ARG const
char* templ, ...)
177 va_list ap = WINPR_C_ARRAY_INIT;
180 int rc = winpr_vasprintf(s, slen, templ, ap);
185WINPR_ATTR_FORMAT_ARG(3, 0)
186int winpr_vasprintf(
char** s,
size_t* slen, WINPR_FORMAT_ARG const
char* templ, va_list oap)
188 va_list ap = WINPR_C_ARRAY_INIT;
194 const int length = vsnprintf(
nullptr, 0, templ, ap);
199 char* str = calloc((
size_t)length + 1UL,
sizeof(
char));
204 const int plen = vsnprintf(str, (
size_t)length + 1UL, templ, ap);
213 *slen = (size_t)length;
219char* _strdup(
const char* strSource)
221 if (strSource ==
nullptr)
224 char* strDestination = strdup(strSource);
226 if (strDestination ==
nullptr)
227 WLog_ERR(TAG,
"strdup");
229 return strDestination;
232WCHAR* _wcsdup(
const WCHAR* strSource)
237 size_t len = _wcslen(strSource);
238 WCHAR* strDestination = calloc(len + 1,
sizeof(WCHAR));
240 if (strDestination !=
nullptr)
241 memcpy(strDestination, strSource, len *
sizeof(WCHAR));
243 if (strDestination ==
nullptr)
244 WLog_ERR(TAG,
"wcsdup");
246 return strDestination;
249WCHAR* _wcsncat(WCHAR* dst,
const WCHAR* src,
size_t sz)
252 WINPR_ASSERT(src || (sz == 0));
254 const size_t dlen = _wcslen(dst);
255 const size_t slen = _wcsnlen(src, sz);
256 for (
size_t x = 0; x < slen; x++)
257 dst[dlen + x] = src[x];
258 dst[dlen + slen] =
'\0';
262int _stricmp(
const char* string1,
const char* string2)
264 return strcasecmp(string1, string2);
267int _strnicmp(
const char* string1,
const char* string2,
size_t count)
269 return strncasecmp(string1, string2, count);
274int _wcscmp(
const WCHAR* string1,
const WCHAR* string2)
276 WINPR_ASSERT(string1);
277 WINPR_ASSERT(string2);
281 const WCHAR w1 = *string1++;
282 const WCHAR w2 = *string2++;
286 else if ((w1 ==
'\0') || (w2 ==
'\0'))
291int _wcsncmp(
const WCHAR* string1,
const WCHAR* string2,
size_t count)
293 WINPR_ASSERT(string1);
294 WINPR_ASSERT(string2);
296 for (
size_t x = 0; x < count; x++)
298 const WCHAR a = string1[x];
299 const WCHAR b = string2[x];
303 else if ((a ==
'\0') || (b ==
'\0'))
311size_t _wcslen(
const WCHAR* str)
313 const WCHAR* p = str;
320 return (
size_t)(p - str);
325size_t _wcsnlen(
const WCHAR* str,
size_t max)
341WCHAR* _wcsstr(
const WCHAR* str,
const WCHAR* strSearch)
344 WINPR_ASSERT(strSearch);
346 if (strSearch[0] ==
'\0')
347 return WINPR_CAST_CONST_PTR_AWAY(str, WCHAR*);
349 const size_t searchLen = _wcslen(strSearch);
352 if (_wcsncmp(str, strSearch, searchLen) == 0)
353 return WINPR_CAST_CONST_PTR_AWAY(str, WCHAR*);
361WCHAR* _wcschr(
const WCHAR* str, WCHAR c)
368 const WCHAR* p = str;
370 while (*p && (*p != c))
373 cnv.cc = (*p == c) ? p : nullptr;
379WCHAR* _wcsrchr(
const WCHAR* str, WCHAR c)
386 const WCHAR* p =
nullptr;
391 for (; *str !=
'\0'; str++)
393 const WCHAR ch = *str;
402char* strtok_s(
char* strToken,
const char* strDelimit,
char** context)
404 return strtok_r(strToken, strDelimit, context);
407WCHAR* wcstok_s(WCHAR* strToken,
const WCHAR* strDelimit, WCHAR** context)
409 WCHAR* nextToken =
nullptr;
417 while (*strToken && _wcschr(strDelimit, value))
426 nextToken = strToken++;
429 while (*strToken && !(_wcschr(strDelimit, value)))
444#if !defined(_WIN32) || defined(_UWP)
452LPSTR CharUpperA(LPSTR lpsz)
459 length = strlen(lpsz);
462 return (LPSTR)
nullptr;
468 if ((c >=
'a') && (c <=
'z'))
469 c = (char)(c -
'a' +
'A');
475 for (
size_t i = 0; i < length; i++)
477 if ((lpsz[i] >=
'a') && (lpsz[i] <=
'z'))
478 lpsz[i] = (char)(lpsz[i] -
'a' +
'A');
484LPWSTR CharUpperW(LPWSTR lpsz)
491 length = _wcslen(lpsz);
494 return (LPWSTR)
nullptr;
500 if ((c >= L
'a') && (c <= L
'z'))
507 for (
size_t i = 0; i < length; i++)
509 if ((lpsz[i] >= L
'a') && (lpsz[i] <= L
'z'))
510 lpsz[i] = lpsz[i] - L
'a' + L
'A';
516DWORD CharUpperBuffA(LPSTR lpsz, DWORD cchLength)
521 for (DWORD i = 0; i < cchLength; i++)
523 if ((lpsz[i] >=
'a') && (lpsz[i] <=
'z'))
524 lpsz[i] = (char)(lpsz[i] -
'a' +
'A');
530DWORD CharUpperBuffW(LPWSTR lpsz, DWORD cchLength)
532 for (DWORD i = 0; i < cchLength; i++)
534 WCHAR value = winpr_Data_Get_UINT16(&lpsz[i]);
535 value = WINPR_TOUPPERW(value);
536 winpr_Data_Write_UINT16(&lpsz[i], value);
542LPSTR CharLowerA(LPSTR lpsz)
547 return (LPSTR)
nullptr;
549 length = strlen(lpsz);
552 return (LPSTR)
nullptr;
558 if ((c >=
'A') && (c <=
'Z'))
559 c = (char)(c -
'A' +
'a');
565 for (
size_t i = 0; i < length; i++)
567 if ((lpsz[i] >=
'A') && (lpsz[i] <=
'Z'))
568 lpsz[i] = (char)(lpsz[i] -
'A' +
'a');
574LPWSTR CharLowerW(LPWSTR lpsz)
576 const size_t len = _wcsnlen(lpsz, UINT32_MAX + 1);
577 if (len > UINT32_MAX)
579 CharLowerBuffW(lpsz, (UINT32)len);
583DWORD CharLowerBuffA(LPSTR lpsz, DWORD cchLength)
588 for (DWORD i = 0; i < cchLength; i++)
590 if ((lpsz[i] >=
'A') && (lpsz[i] <=
'Z'))
591 lpsz[i] = (char)(lpsz[i] -
'A' +
'a');
597DWORD CharLowerBuffW(LPWSTR lpsz, DWORD cchLength)
599 for (DWORD i = 0; i < cchLength; i++)
601 WCHAR value = winpr_Data_Get_UINT16(&lpsz[i]);
602 value = WINPR_TOLOWERW(value);
603 winpr_Data_Write_UINT16(&lpsz[i], value);
609BOOL IsCharAlphaA(CHAR ch)
611 if (((ch >=
'a') && (ch <=
'z')) || ((ch >=
'A') && (ch <=
'Z')))
617BOOL IsCharAlphaW(WCHAR ch)
619 if (((ch >= L
'a') && (ch <= L
'z')) || ((ch >= L
'A') && (ch <= L
'Z')))
625BOOL IsCharAlphaNumericA(CHAR ch)
627 if (((ch >=
'a') && (ch <=
'z')) || ((ch >=
'A') && (ch <=
'Z')) ||
628 ((ch >=
'0') && (ch <=
'9')))
634BOOL IsCharAlphaNumericW(WCHAR ch)
636 if (((ch >= L
'a') && (ch <= L
'z')) || ((ch >= L
'A') && (ch <= L
'Z')) ||
637 ((ch >= L
'0') && (ch <= L
'9')))
643BOOL IsCharUpperA(CHAR ch)
645 if ((ch >=
'A') && (ch <=
'Z'))
651BOOL IsCharUpperW(WCHAR ch)
653 if ((ch >= L
'A') && (ch <= L
'Z'))
659BOOL IsCharLowerA(CHAR ch)
661 if ((ch >=
'a') && (ch <=
'z'))
667BOOL IsCharLowerW(WCHAR ch)
669 if ((ch >= L
'a') && (ch <= L
'z'))
677size_t ConvertLineEndingToLF(
char* str,
size_t size)
681 WINPR_ASSERT(str || (size == 0));
682 for (
size_t x = 0; x < size; x++)
688 str[x - skip] =
'\n';
689 if ((x + 1 < size) && (str[x + 1] ==
'\n'))
700char* ConvertLineEndingToCRLF(
const char* str,
size_t* size)
703 const size_t s = *size;
704 WINPR_ASSERT(str || (s == 0));
710 size_t linebreaks = 0;
711 for (
size_t x = 0; x < s - 1; x++)
724 char* cnv = calloc(s + linebreaks * 2ull + 1ull,
sizeof(
char));
729 for (
size_t x = 0; x < s; x++)
731 const char c = str[x];
740 if ((x > 0) && (str[x - 1] !=
'\r'))
755char* StrSep(
char** stringp,
const char* delim)
757 char* start = *stringp;
759 p = (start !=
nullptr) ? strpbrk(start, delim) :
nullptr;
772INT64 GetLine(
char** lineptr,
size_t* size, FILE* stream)
780 if (!lineptr || !size)
788 if (used + 2 >= *size)
791 n = realloc(*lineptr, *size);
804 (*lineptr)[used++] = c;
805 }
while ((c !=
'\n') && (c !=
'\r') && (c != EOF));
807 (*lineptr)[used] =
'\0';
809#elif !defined(ANDROID) && !defined(IOS)
810 return getline(lineptr, size, stream);
816#if !defined(WINPR_HAVE_STRNDUP)
817char* strndup(
const char* src,
size_t n)
819 char* dst = calloc(n + 1,
sizeof(
char));
821 strncpy(dst, src, n);
826const WCHAR* InitializeConstWCharFromUtf8(
const char* str, WCHAR* buffer,
size_t len)
829 WINPR_ASSERT(buffer || (len == 0));
830 (void)ConvertUtf8ToWChar(str, buffer, len);
834WCHAR* wcsndup(
const WCHAR* s,
size_t n)
839 WCHAR* copy = calloc(n + 1,
sizeof(WCHAR));
842 memcpy(copy, s, n *
sizeof(WCHAR));
846char* winpr_strnstr(
char* haystack,
const char* needle,
size_t hlen)
848 WINPR_ASSERT(haystack || (hlen == 0));
849 WINPR_ASSERT(needle);
851#if defined(WINPR_HAVE_STRNSTR)
852 return strnstr(haystack, needle, hlen);
856 const size_t needle_len = strlen(needle);
861 for (; (*haystack !=
'\0') && (hlen >= needle_len); haystack++, hlen--)
863 if ((haystack[0] == needle[0]) && (0 == strncmp(haystack, needle, needle_len)))