20 #include <winpr/config.h>
21 #include <winpr/assert.h>
29 #include <winpr/crt.h>
30 #include <winpr/endian.h>
32 #if defined(WITH_URIPARSER)
33 #include <uriparser/Uri.h>
39 #define TAG WINPR_TAG("crt")
42 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
45 #if defined(WITH_URIPARSER)
46 char* winpr_str_url_decode(
const char* str,
size_t len)
48 char* dst = strndup(str, len);
52 if (!uriUnescapeInPlaceExA(dst, URI_FALSE, URI_FALSE))
61 char* winpr_str_url_encode(
const char* str,
size_t len)
63 char* dst = calloc(len + 1,
sizeof(
char) * 3);
67 if (!uriEscapeA(str, dst, URI_FALSE, URI_FALSE))
76 static const char rfc3986[] = {
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2e, 0x00,
80 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
82 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
83 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
84 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x7e, 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,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 static char hex2bin(
char what)
106 static char unescape(
const char* what,
size_t* px)
108 if ((*what ==
'%') && (isxdigit(what[1]) && isxdigit(what[2])))
111 return 16 * hex2bin(what[1]) + hex2bin(what[2]);
117 char* winpr_str_url_decode(
const char* str,
size_t len)
119 char* dst = calloc(len + 1,
sizeof(
char));
124 for (
size_t x = 0; x < strnlen(str, len); x++)
126 const char* cur = &str[x];
127 dst[pos++] = unescape(cur, &x);
132 static char* escape(
char* dst,
char what)
134 if (rfc3986[what & 0xff])
140 sprintf(dst,
"%%%02" PRIX8, (BYTE)(what & 0xff));
144 char* winpr_str_url_encode(
const char* str,
size_t len)
146 char* dst = calloc(len + 1,
sizeof(
char) * 3);
151 for (
size_t x = 0; x < strnlen(str, len); x++)
153 const char cur = str[x];
154 ptr = escape(ptr, cur);
160 BOOL winpr_str_append(
const char* what,
char* buffer,
size_t size,
const char* separator)
162 const size_t used = strnlen(buffer, size);
163 const size_t add = strnlen(what, size);
164 const size_t sep_len = separator ? strnlen(separator, size) : 0;
165 const size_t sep = (used > 0) ? sep_len : 0;
167 if (used + add + sep >= size)
170 if ((used > 0) && (sep_len > 0))
171 strncat(buffer, separator, sep_len);
173 strncat(buffer, what, add);
177 WINPR_ATTR_FORMAT_ARG(3, 4)
178 int winpr_asprintf(
char** s,
size_t* slen, WINPR_FORMAT_ARG const
char* templ, ...)
183 int rc = winpr_vasprintf(s, slen, templ, ap);
188 WINPR_ATTR_FORMAT_ARG(3, 0)
189 int winpr_vasprintf(
char** s,
size_t* slen, WINPR_FORMAT_ARG const
char* templ, va_list oap)
197 const int length = vsnprintf(NULL, 0, templ, ap);
202 char* str = calloc((
size_t)length + 1UL,
sizeof(
char));
207 const int plen = vsnprintf(str, (
size_t)length + 1UL, templ, ap);
216 *slen = (size_t)length;
222 char* _strdup(
const char* strSource)
224 if (strSource == NULL)
227 char* strDestination = strdup(strSource);
229 if (strDestination == NULL)
230 WLog_ERR(TAG,
"strdup");
232 return strDestination;
235 WCHAR* _wcsdup(
const WCHAR* strSource)
240 size_t len = _wcslen(strSource);
241 WCHAR* strDestination = calloc(len + 1,
sizeof(WCHAR));
243 if (strDestination != NULL)
244 memcpy(strDestination, strSource, len *
sizeof(WCHAR));
246 if (strDestination == NULL)
247 WLog_ERR(TAG,
"wcsdup");
249 return strDestination;
252 WCHAR* _wcsncat(WCHAR* dst,
const WCHAR* src,
size_t sz)
255 WINPR_ASSERT(src || (sz == 0));
257 const size_t dlen = _wcslen(dst);
258 const size_t slen = _wcsnlen(src, sz);
259 for (
size_t x = 0; x < slen; x++)
260 dst[dlen + x] = src[x];
261 dst[dlen + slen] =
'\0';
265 int _stricmp(
const char* string1,
const char* string2)
267 return strcasecmp(string1, string2);
270 int _strnicmp(
const char* string1,
const char* string2,
size_t count)
272 return strncasecmp(string1, string2, count);
277 int _wcscmp(
const WCHAR* string1,
const WCHAR* string2)
279 WINPR_ASSERT(string1);
280 WINPR_ASSERT(string2);
284 const WCHAR w1 = *string1++;
285 const WCHAR w2 = *string2++;
289 else if ((w1 ==
'\0') || (w2 ==
'\0'))
294 int _wcsncmp(
const WCHAR* string1,
const WCHAR* string2,
size_t count)
296 WINPR_ASSERT(string1);
297 WINPR_ASSERT(string2);
299 for (
size_t x = 0; x < count; x++)
301 const WCHAR a = string1[x];
302 const WCHAR b = string2[x];
306 else if ((a ==
'\0') || (b ==
'\0'))
314 size_t _wcslen(
const WCHAR* str)
316 const WCHAR* p = str;
323 return (
size_t)(p - str);
328 size_t _wcsnlen(
const WCHAR* str,
size_t max)
344 WCHAR* _wcsstr(
const WCHAR* str,
const WCHAR* strSearch)
347 WINPR_ASSERT(strSearch);
349 if (strSearch[0] ==
'\0')
350 return WINPR_CAST_CONST_PTR_AWAY(str, WCHAR*);
352 const size_t searchLen = _wcslen(strSearch);
355 if (_wcsncmp(str, strSearch, searchLen) == 0)
356 return WINPR_CAST_CONST_PTR_AWAY(str, WCHAR*);
364 WCHAR* _wcschr(
const WCHAR* str, WCHAR value)
371 const WCHAR* p = str;
373 while (*p && (*p != value))
376 cnv.cc = (*p == value) ? p : NULL;
382 WCHAR* _wcsrchr(
const WCHAR* str, WCHAR c)
389 const WCHAR* p = NULL;
394 for (; *str !=
'\0'; str++)
396 const WCHAR ch = *str;
405 char* strtok_s(
char* strToken,
const char* strDelimit,
char** context)
407 return strtok_r(strToken, strDelimit, context);
410 WCHAR* wcstok_s(WCHAR* strToken,
const WCHAR* strDelimit, WCHAR** context)
412 WCHAR* nextToken = NULL;
420 while (*strToken && _wcschr(strDelimit, value))
429 nextToken = strToken++;
432 while (*strToken && !(_wcschr(strDelimit, value)))
447 #if !defined(_WIN32) || defined(_UWP)
455 LPSTR CharUpperA(LPSTR lpsz)
462 length = strlen(lpsz);
471 if ((c >=
'a') && (c <=
'z'))
472 c = (char)(c -
'a' +
'A');
478 for (
size_t i = 0; i < length; i++)
480 if ((lpsz[i] >=
'a') && (lpsz[i] <=
'z'))
481 lpsz[i] = (char)(lpsz[i] -
'a' +
'A');
487 LPWSTR CharUpperW(LPWSTR lpsz)
494 length = _wcslen(lpsz);
503 if ((c >= L
'a') && (c <= L
'z'))
510 for (
size_t i = 0; i < length; i++)
512 if ((lpsz[i] >= L
'a') && (lpsz[i] <= L
'z'))
513 lpsz[i] = lpsz[i] - L
'a' + L
'A';
519 DWORD CharUpperBuffA(LPSTR lpsz, DWORD cchLength)
524 for (DWORD i = 0; i < cchLength; i++)
526 if ((lpsz[i] >=
'a') && (lpsz[i] <=
'z'))
527 lpsz[i] = (char)(lpsz[i] -
'a' +
'A');
533 DWORD CharUpperBuffW(LPWSTR lpsz, DWORD cchLength)
537 for (DWORD i = 0; i < cchLength; i++)
539 Data_Read_UINT16(&lpsz[i], value);
540 value = WINPR_TOUPPERW(value);
541 Data_Write_UINT16(&lpsz[i], value);
547 LPSTR CharLowerA(LPSTR lpsz)
554 length = strlen(lpsz);
563 if ((c >=
'A') && (c <=
'Z'))
564 c = (char)(c -
'A' +
'a');
570 for (
size_t i = 0; i < length; i++)
572 if ((lpsz[i] >=
'A') && (lpsz[i] <=
'Z'))
573 lpsz[i] = (char)(lpsz[i] -
'A' +
'a');
579 LPWSTR CharLowerW(LPWSTR lpsz)
581 const size_t len = _wcsnlen(lpsz, UINT32_MAX + 1);
582 if (len > UINT32_MAX)
584 CharLowerBuffW(lpsz, (UINT32)len);
588 DWORD CharLowerBuffA(LPSTR lpsz, DWORD cchLength)
593 for (DWORD i = 0; i < cchLength; i++)
595 if ((lpsz[i] >=
'A') && (lpsz[i] <=
'Z'))
596 lpsz[i] = (char)(lpsz[i] -
'A' +
'a');
602 DWORD CharLowerBuffW(LPWSTR lpsz, DWORD cchLength)
606 for (DWORD i = 0; i < cchLength; i++)
608 Data_Read_UINT16(&lpsz[i], value);
609 value = WINPR_TOLOWERW(value);
610 Data_Write_UINT16(&lpsz[i], value);
616 BOOL IsCharAlphaA(CHAR ch)
618 if (((ch >=
'a') && (ch <=
'z')) || ((ch >=
'A') && (ch <=
'Z')))
624 BOOL IsCharAlphaW(WCHAR ch)
626 if (((ch >= L
'a') && (ch <= L
'z')) || ((ch >= L
'A') && (ch <= L
'Z')))
632 BOOL IsCharAlphaNumericA(CHAR ch)
634 if (((ch >=
'a') && (ch <=
'z')) || ((ch >=
'A') && (ch <=
'Z')) ||
635 ((ch >=
'0') && (ch <=
'9')))
641 BOOL IsCharAlphaNumericW(WCHAR ch)
643 if (((ch >= L
'a') && (ch <= L
'z')) || ((ch >= L
'A') && (ch <= L
'Z')) ||
644 ((ch >= L
'0') && (ch <= L
'9')))
650 BOOL IsCharUpperA(CHAR ch)
652 if ((ch >=
'A') && (ch <=
'Z'))
658 BOOL IsCharUpperW(WCHAR ch)
660 if ((ch >= L
'A') && (ch <= L
'Z'))
666 BOOL IsCharLowerA(CHAR ch)
668 if ((ch >=
'a') && (ch <=
'z'))
674 BOOL IsCharLowerW(WCHAR ch)
676 if ((ch >= L
'a') && (ch <= L
'z'))
684 size_t ConvertLineEndingToLF(
char* str,
size_t size)
688 WINPR_ASSERT(str || (size == 0));
689 for (
size_t x = 0; x < size; x++)
695 str[x - skip] =
'\n';
696 if ((x + 1 < size) && (str[x + 1] ==
'\n'))
707 char* ConvertLineEndingToCRLF(
const char* str,
size_t* size)
710 const size_t s = *size;
711 WINPR_ASSERT(str || (s == 0));
717 size_t linebreaks = 0;
718 for (
size_t x = 0; x < s - 1; x++)
731 char* cnv = calloc(s + linebreaks * 2ull + 1ull,
sizeof(
char));
736 for (
size_t x = 0; x < s; x++)
738 const char c = str[x];
747 if ((x > 0) && (str[x - 1] !=
'\r'))
762 char* StrSep(
char** stringp,
const char* delim)
764 char* start = *stringp;
766 p = (start != NULL) ? strpbrk(start, delim) : NULL;
779 INT64 GetLine(
char** lineptr,
size_t* size, FILE* stream)
787 if (!lineptr || !size)
795 if (used + 2 >= *size)
798 n = realloc(*lineptr, *size);
811 (*lineptr)[used++] = c;
812 }
while ((c !=
'\n') && (c !=
'\r') && (c != EOF));
814 (*lineptr)[used] =
'\0';
816 #elif !defined(ANDROID) && !defined(IOS)
817 return getline(lineptr, size, stream);
823 #if !defined(WINPR_HAVE_STRNDUP)
824 char* strndup(
const char* src,
size_t n)
826 char* dst = calloc(n + 1,
sizeof(
char));
828 strncpy(dst, src, n);
833 const WCHAR* InitializeConstWCharFromUtf8(
const char* str, WCHAR* buffer,
size_t len)
836 WINPR_ASSERT(buffer || (len == 0));
837 (void)ConvertUtf8ToWChar(str, buffer, len);
841 WCHAR* wcsndup(
const WCHAR* s,
size_t n)
846 WCHAR* copy = calloc(n + 1,
sizeof(WCHAR));
849 memcpy(copy, s, n *
sizeof(WCHAR));