static const char* mimetype_guess (const char * path) { unsigned int i; const struct { const char * suffix; const char * mime_type; } types[] = { /* these are the ones we need for serving the web client's files... */ { "css", "text/css" }, { "gif", "image/gif" }, { "html", "text/html" }, { "ico", "image/vnd.microsoft.icon" }, { "js", "application/javascript" }, { "png", "image/png" } }; const char * dot = strrchr (path, '.'); for (i = 0; dot && i < TR_N_ELEMENTS (types); ++i) if (strcmp (dot + 1, types[i].suffix) == 0) return types[i].mime_type; return "application/octet-stream"; }
static char const* unix_timestamp_to_str(time_t timestamp) { if (timestamp == 0) { return "Unknown"; } struct tm const* const local_time = localtime(×tamp); if (local_time == NULL) { return "Invalid"; } static char buffer[32]; tr_strlcpy(buffer, asctime(local_time), TR_N_ELEMENTS(buffer)); char* const newline_pos = strchr(buffer, '\n'); if (newline_pos != NULL) { *newline_pos = '\0'; } return buffer; }
static wchar_t* path_to_native_path_ex(char const* path, int extra_chars_after, int* real_result_size) { /* Extending maximum path length limit up to ~32K. See "Naming Files, Paths, and Namespaces" (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx) for more info */ wchar_t const local_prefix[] = { '\\', '\\', '?', '\\' }; wchar_t const unc_prefix[] = { '\\', '\\', '?', '\\', 'U', 'N', 'C', '\\' }; bool const is_relative = tr_sys_path_is_relative(path); bool const is_unc = is_unc_path(path); /* `-2` for UNC since we overwrite existing prefix slashes */ int const extra_chars_before = is_relative ? 0 : (is_unc ? TR_N_ELEMENTS(unc_prefix) - 2 : TR_N_ELEMENTS(local_prefix)); /* TODO (?): TR_ASSERT(!is_relative); */ wchar_t* const wide_path = tr_win32_utf8_to_native_ex(path, -1, extra_chars_before, extra_chars_after, real_result_size); if (wide_path == NULL) { return NULL; } /* Relative paths cannot be used with "\\?\" prefixes. This also means that relative paths are limited to ~260 chars... but we should rarely work with relative paths in the first place */ if (!is_relative) { if (is_unc) { /* UNC path: "\\server\share" -> "\\?\UNC\server\share" */ memcpy(wide_path, unc_prefix, sizeof(unc_prefix)); } else { /* Local path: "C:" -> "\\?\C:" */ memcpy(wide_path, local_prefix, sizeof(local_prefix)); } } /* Automatic '/' to '\' conversion is disabled for "\\?\"-prefixed paths */ wchar_t* p = wide_path + extra_chars_before; while ((p = wcschr(p, L'/')) != NULL) { *p++ = L'\\'; } if (real_result_size != NULL) { *real_result_size += extra_chars_before; } return wide_path; }
int main(void) { char const* comma_locales[] = { "da_DK.UTF-8", "fr_FR.UTF-8", "ru_RU.UTF-8" }; testFunc const tests[] = { test_elements, test_utf8, test1, test2, test3, test_unescape }; /* run the tests in a locale with a decimal point of '.' */ setlocale(LC_NUMERIC, "C"); int ret = runTests(tests, NUM_TESTS(tests)); /* run the tests in a locale with a decimal point of ',' */ bool is_locale_set = false; for (size_t i = 0; !is_locale_set && i < TR_N_ELEMENTS(comma_locales); ++i) { is_locale_set = setlocale(LC_NUMERIC, comma_locales[i]) != NULL; } if (!is_locale_set) { fprintf(stderr, "WARNING: unable to run locale-specific json tests. add a locale like %s or %s\n", comma_locales[0], comma_locales[1]); } else { ret += runTests(tests, NUM_TESTS(tests)); } return ret; }