19#include <winpr/config.h>
21#include <winpr/atexit.h>
22#include <winpr/assert.h>
23#include <winpr/string.h>
24#include <winpr/synch.h>
25#include <winpr/json.h>
26#include <winpr/path.h>
27#include <winpr/file.h>
33#define TAG WINPR_TAG("timezone.aliases")
35#include "TimeZoneNameMap.h"
36#include "TimeZoneIanaAliases.h"
38#if defined(WITH_TIMEZONE_COMPILED)
39#include "TimeZoneIanaAliases_static.h"
47} TimeZoneIanaAliasContext;
49static TimeZoneIanaAliasContext alias_context = WINPR_C_ARRAY_INIT;
51static void alias_context_free(
void)
53 for (
size_t x = 0; x < alias_context.count; x++)
55 free(alias_context.entries[x].Current);
56 free(alias_context.entries[x].Legacy);
58 free(alias_context.entries);
60 const TimeZoneIanaAliasContext empty = WINPR_C_ARRAY_INIT;
61 alias_context = empty;
65static BOOL alias_reserve(TimeZoneIanaAliasContext* context,
size_t size_to_add)
67 WINPR_ASSERT(context);
74 "Failed to reallocate TimeZoneIanaAliasEntry::entries to %" PRIuz
" elements",
75 context->size + size_to_add);
78 context->entries = tmp;
79 context->size += size_to_add;
85static BOOL alias_add(TimeZoneIanaAliasContext* context,
const char* source,
size_t pos,
86 char* current,
char* legacy)
88 WINPR_ASSERT(context);
90 WINPR_ASSERT(context->count < context->size);
92 if (!current || !legacy)
94 WLog_WARN(TAG,
"Invalid timezone alias at entry %" PRIuz
" of %s", pos, source);
100 context->entries[context->count].Current = current;
101 context->entries[context->count].Legacy = legacy;
106#if defined(WITH_TIMEZONE_FROM_FILE) && defined(WITH_WINPR_JSON)
107static void load_aliases_from_file(TimeZoneIanaAliasContext* context)
109 WINPR_JSON* json =
nullptr;
110 char* filename = GetCombinedPath(WINPR_RESOURCE_ROOT,
"TimeZoneIanaAliases.json");
113 WLog_WARN(TAG,
"Could not create WinPR timezone alias resource filename");
117 json = TimeZoneJsonParseFile(filename);
126 WLog_WARN(TAG,
"Invalid top level JSON type in file %s, expected an array", filename);
131 if (!alias_reserve(context, count))
133 for (
size_t x = 0; x < count; x++)
136 if (!alias_add(context, filename, x, TimeZoneJsonGetString(entry, x,
"Current"),
137 TimeZoneJsonGetString(entry, x,
"Legacy")))
147static BOOL CALLBACK load_aliases(
PINIT_ONCE once, PVOID param, PVOID* pvcontext)
149 TimeZoneIanaAliasContext* context = param;
150 WINPR_ASSERT(context);
151 WINPR_UNUSED(pvcontext);
154#if defined(WITH_TIMEZONE_FROM_FILE) && defined(WITH_WINPR_JSON)
155 load_aliases_from_file(context);
158#if defined(WITH_TIMEZONE_COMPILED)
159 if (!alias_reserve(context, TimeZoneIanaAliasesSize))
161 alias_context_free();
164 for (
size_t x = 0; x < TimeZoneIanaAliasesSize; x++)
166 if (!alias_add(context,
"the compiled in table", x, _strdup(TimeZoneIanaAliases[x].Current),
167 _strdup(TimeZoneIanaAliases[x].Legacy)))
169 alias_context_free();
175 (void)winpr_atexit(alias_context_free);
179const char* TimeZoneIanaAlias(
const char* iana)
181 static INIT_ONCE init_guard = INIT_ONCE_STATIC_INIT;
185 if (!InitOnceExecuteOnce(&init_guard, load_aliases, &alias_context,
nullptr))
188 for (
size_t x = 0; x < alias_context.count; x++)
191 if (strcmp(iana, alias->Current) == 0)
192 return alias->Legacy;
193 if (strcmp(iana, alias->Legacy) == 0)
194 return alias->Current;
WINPR_ATTR_NODISCARD WINPR_API size_t WINPR_JSON_GetArraySize(const WINPR_JSON *array)
Get the number of arrayitems from an array.
WINPR_ATTR_NODISCARD WINPR_API WINPR_JSON * WINPR_JSON_GetObjectItemCaseSensitive(const WINPR_JSON *object, const char *string)
Same as WINPR_JSON_GetObjectItem but with case sensitive matching.
WINPR_ATTR_NODISCARD WINPR_API WINPR_JSON * WINPR_JSON_GetArrayItem(const WINPR_JSON *array, size_t index)
Return a pointer to an item in the array.
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsArray(const WINPR_JSON *item)
Check if JSON item is of type Array.
WINPR_ATTR_NODISCARD WINPR_API BOOL WINPR_JSON_IsObject(const WINPR_JSON *item)
Check if JSON item is of type Object.
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.