Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/winpr/libwinpr/timezone/TimeZoneNameMapUtils.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Time Zone Name Map Utils
4
 *
5
 * Copyright 2024 Armin Novak <anovak@thincast.com>
6
 * Copyright 2024 Thincast Technologies GmbH
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
#include <winpr/config.h>
21
#include <winpr/assert.h>
22
#include <winpr/string.h>
23
24
#include <string.h>
25
26
#if defined(WITH_TIMEZONE_ICU)
27
#include <unicode/ucal.h>
28
#else
29
#include "WindowsZones.h"
30
#endif
31
32
#include "TimeZoneNameMap.h"
33
34
static const char* return_type(const TimeZoneNameMapEntry* entry, TimeZoneNameType type)
35
269k
{
36
269k
  WINPR_ASSERT(entry);
37
269k
  switch (type)
38
269k
  {
39
0
    case TIME_ZONE_NAME_IANA:
40
0
      return entry->Iana;
41
89.8k
    case TIME_ZONE_NAME_ID:
42
89.8k
      return entry->Id;
43
89.8k
    case TIME_ZONE_NAME_STANDARD:
44
89.8k
      return entry->StandardName;
45
0
    case TIME_ZONE_NAME_DISPLAY:
46
0
      return entry->DisplayName;
47
89.8k
    case TIME_ZONE_NAME_DAYLIGHT:
48
89.8k
      return entry->DaylightName;
49
0
    default:
50
0
      return NULL;
51
269k
  }
52
269k
}
53
54
#if defined(WITH_TIMEZONE_ICU)
55
static char* get_wzid_icu(const UChar* utzid, size_t utzid_len)
56
{
57
  char* res = NULL;
58
  UErrorCode error = U_ZERO_ERROR;
59
60
  int32_t rc = ucal_getWindowsTimeZoneID(utzid, utzid_len, NULL, 0, &error);
61
  if ((error == U_BUFFER_OVERFLOW_ERROR) && (rc > 0))
62
  {
63
    rc++; // make space for '\0'
64
    UChar* wzid = calloc((size_t)rc + 1, sizeof(UChar));
65
    if (wzid)
66
    {
67
      UErrorCode error2 = U_ZERO_ERROR;
68
      int32_t rc2 = ucal_getWindowsTimeZoneID(utzid, utzid_len, wzid, rc, &error2);
69
      if (U_SUCCESS(error2) && (rc2 > 0))
70
        res = ConvertWCharNToUtf8Alloc(wzid, (size_t)rc, NULL);
71
      free(wzid);
72
    }
73
  }
74
  return res;
75
}
76
77
static char* get(const char* iana)
78
{
79
  size_t utzid_len = 0;
80
  UChar* utzid = ConvertUtf8ToWCharAlloc(iana, &utzid_len);
81
  if (!utzid)
82
    return NULL;
83
84
  char* wzid = get_wzid_icu(utzid, utzid_len);
85
  free(utzid);
86
  return wzid;
87
}
88
89
static const char* map_fallback(const char* iana, TimeZoneNameType type)
90
{
91
  const char* res = NULL;
92
  char* wzid = get(iana);
93
  if (!wzid)
94
    return NULL;
95
96
  for (size_t x = 0; x < TimeZoneNameMapSize; x++)
97
  {
98
    const TimeZoneNameMapEntry* entry = &TimeZoneNameMap[x];
99
    if (strcmp(wzid, entry->Id) == 0)
100
    {
101
      res = return_type(entry, type);
102
      break;
103
    }
104
  }
105
106
  free(wzid);
107
  return res;
108
}
109
#else
110
static const char* map_fallback(const char* iana, TimeZoneNameType type)
111
0
{
112
0
  if (!iana)
113
0
    return NULL;
114
115
0
  for (size_t x = 0; x < WindowsZonesNrElements; x++)
116
0
  {
117
0
    const WINDOWS_TZID_ENTRY* const entry = &WindowsZones[x];
118
0
    if (strcmp(entry->tzid, iana) == 0)
119
0
      return entry->windows;
120
0
  }
121
122
0
  return NULL;
123
0
}
124
#endif
125
126
const char* TimeZoneIanaToWindows(const char* iana, TimeZoneNameType type)
127
269k
{
128
269k
  if (!iana)
129
0
    return NULL;
130
131
12.6M
  for (size_t x = 0; x < TimeZoneNameMapSize; x++)
132
12.6M
  {
133
12.6M
    const TimeZoneNameMapEntry* entry = &TimeZoneNameMap[x];
134
12.6M
    if (strcmp(iana, entry->Iana) == 0)
135
269k
      return return_type(entry, type);
136
12.6M
  }
137
138
0
  const char* wzid = map_fallback(iana, type);
139
0
  if (!wzid)
140
0
    return NULL;
141
142
0
  for (size_t x = 0; x < TimeZoneNameMapSize; x++)
143
0
  {
144
0
    const TimeZoneNameMapEntry* entry = &TimeZoneNameMap[x];
145
0
    if (strcmp(wzid, entry->Id) == 0)
146
0
      return return_type(entry, type);
147
0
  }
148
0
  return NULL;
149
0
}