Coverage Report

Created: 2025-12-14 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wt/src/Wt/Utils.C
Line
Count
Source
1
/*
2
 * Copyright (C) 2012 Emweb bv, Herent, Belgium.
3
 *
4
 * See the LICENSE file for terms of use.
5
 */
6
7
#include <vector>
8
#include <iterator>
9
10
#include <string.h>
11
12
#include "Wt/WConfig.h" // WT_WIN32
13
// for htonl():
14
#ifndef WT_WIN32
15
#include <arpa/inet.h>
16
#else
17
#include <winsock2.h>
18
#endif
19
20
#include "Wt/WLogger.h"
21
#include "Wt/Utils.h"
22
#include "DomElement.h"
23
#include "md5.h"
24
#include "base32.h"
25
#include "base64.h"
26
#include "ImageUtils.h"
27
#include "StringUtils.h"
28
29
30
#include <cstring>
31
32
extern "C" {
33
  #include "sha1.h"
34
}
35
36
namespace Wt {
37
38
LOGGER("Utils");
39
40
  namespace Utils {
41
42
    namespace {
43
44
unsigned char fromHex(char b)
45
0
{
46
0
  if (b <= '9')
47
0
    return b - '0';
48
0
  else if (b <= 'F')
49
0
    return (b - 'A') + 0x0A;
50
0
  else
51
0
    return (b - 'a') + 0x0A;
52
0
}
53
54
unsigned char fromHex(char msb, char lsb)
55
0
{
56
0
  return (fromHex(msb) << 4) + fromHex(lsb);
57
0
}
58
59
char toHex(unsigned char b)
60
0
{
61
0
  if (b < 0xA)
62
0
    return '0' + b;
63
0
  else
64
0
    return 'a' + (b - 0xA);
65
0
}
66
67
void toHex(unsigned char b, char& msb, char& lsb)
68
0
{
69
0
  lsb = toHex(b & 0x0F);
70
0
  msb = toHex(b >> 4);
71
0
}
72
73
    }
74
75
std::string md5(const std::string& text)
76
0
{
77
0
  md5_state_t c;
78
0
  wt_md5_init(&c);
79
80
0
  wt_md5_append(&c, (const md5_byte_t *)text.c_str(), text.length());
81
82
0
  unsigned char buf[16];
83
0
  wt_md5_finish(&c, buf);
84
85
0
  return std::string((const char *)buf, 16);
86
0
}
87
88
std::string sha1(const std::string& text)
89
0
{
90
0
  SHA1Context sha;
91
92
0
  wt_SHA1Reset(&sha);
93
0
  wt_SHA1Input(&sha, (unsigned char *)text.c_str(), text.length());
94
95
0
  if (!wt_SHA1Result(&sha)) {
96
0
    LOG_ERROR("Error computing sha1 hash");
97
0
    return std::string();
98
0
  } else {
99
0
    const unsigned SHA1_LENGTH = 20;
100
0
    unsigned char hash[SHA1_LENGTH];
101
102
0
    for (unsigned i = 0; i < 5; ++i) {
103
0
      unsigned v = htonl(sha.Message_Digest[i]);
104
0
      memcpy(hash + (i*4), &v, 4);
105
0
    }
106
107
0
    return std::string(hash, hash + SHA1_LENGTH);
108
0
  }
109
0
}
110
111
std::string base32Encode(const std::string& data, bool crlf)
112
0
{
113
0
  std::vector<char> v;
114
115
  // base32 encoded value will be 8/5 larger than original value
116
0
  v.reserve(static_cast<std::size_t>(data.size() * 1.6));
117
118
0
  base32::encode(data.begin(), data.end(), std::back_inserter(v), crlf);
119
120
0
  return std::string(v.begin(), v.end());
121
0
}
122
123
std::string base32Decode(const std::string& data)
124
0
{
125
0
  std::vector<char> v;
126
127
  // decoded value will be 5/8 smaller than encoded value
128
0
  v.reserve((std::size_t)(data.size() * 0.625));
129
130
0
  base32::decode(data.begin(), data.end(), std::back_inserter(v));
131
132
0
  return std::string(v.begin(), v.end());
133
0
}
134
135
std::string base64Encode(const std::string& data, bool crlf)
136
0
{
137
0
  std::vector<char> v;
138
139
  // base64 encoded value will be 4/3 larger than original value
140
0
  v.reserve((std::size_t)(data.size() * 1.35));
141
142
0
  base64::encode(data.begin(), data.end(), std::back_inserter(v), crlf);
143
144
0
  return std::string(v.begin(), v.end());
145
0
}
146
147
std::string base64Decode(const std::string& data)
148
0
{
149
0
  std::vector<char> v;
150
151
  // decoded value will be 3/4 smaller than encoded value
152
0
  v.reserve((std::size_t)(data.size() * 0.8));
153
154
0
  base64::decode(data.begin(), data.end(), std::back_inserter(v));
155
156
0
  return std::string(v.begin(), v.end());
157
0
}
158
159
std::string hexEncode(const std::string& data)
160
0
{
161
0
  std::string result(data.length() * 2, '-');
162
163
0
  for (unsigned i = 0; i < data.length(); ++i)
164
0
    toHex(data[i], result[2 * i], result[2 * i + 1]);
165
166
0
  return result;
167
0
}
168
169
std::string hexDecode(const std::string& data)
170
0
{
171
0
  std::string result(data.length() / 2, '-');
172
173
0
  for (unsigned i = 0; i < result.length(); ++i)
174
0
    result[i] = fromHex(data[2 * i], data[2 * i + 1]);
175
176
0
  return result;
177
0
}
178
179
std::string htmlEncode(const std::string& text, WFlags<HtmlEncodingFlag> flags)
180
0
{
181
0
  std::string result = text;
182
0
  WWebWidget::escapeText(result,
183
0
                         (flags.test(HtmlEncodingFlag::EncodeNewLines)) ?
184
0
                         true : false);
185
0
  return result;
186
0
}
187
188
WString htmlEncode(const WString& text, WFlags<HtmlEncodingFlag> flags)
189
0
{
190
0
  return WString::fromUTF8(htmlEncode(text.toUTF8(), flags));
191
0
}
192
193
std::string htmlAttributeValue(const std::string& text)
194
0
{
195
0
  Wt::WStringStream ss;
196
0
  DomElement::htmlAttributeValue(ss, text);
197
0
  return ss.str();
198
0
}
199
200
std::string urlEncode(const std::string& text)
201
0
{
202
0
  return DomElement::urlEncodeS(text);
203
0
}
204
205
std::string urlDecode(const std::string &text)
206
179
{
207
179
  WStringStream result;
208
209
86.4k
  for (unsigned i = 0; i < text.length(); ++i) {
210
86.3k
    char c = text[i];
211
212
86.3k
    if (c == '+') {
213
2.40k
      result << ' ';
214
83.9k
    } else if (c == '%' && i + 2 < text.length()) {
215
2.44k
      std::string h = text.substr(i + 1, 2);
216
2.44k
      char *e = nullptr;
217
2.44k
      int hval = std::strtol(h.c_str(), &e, 16);
218
219
2.44k
      if (*e == 0) {
220
661
        result << (char)hval;
221
661
        i += 2;
222
661
      } else
223
        // not a proper %XX with XX hexadecimal format
224
1.78k
        result << c;
225
2.44k
    } else
226
81.4k
      result << c;
227
86.3k
  }
228
229
179
  return result.str();
230
179
}
231
232
bool removeScript(WString& text)
233
0
{
234
0
  return WWebWidget::removeScript(text);
235
0
}
236
237
std::string guessImageMimeTypeData(const std::vector<unsigned char>& header)
238
0
{
239
0
  return Wt::ImageUtils::identifyMimeType(header);
240
0
}
241
std::string guessImageMimeType(const std::string& file)
242
0
{
243
0
  return Wt::ImageUtils::identifyMimeType(file);
244
0
}
245
246
247
0
std::string createDataUrl(std::vector<unsigned char>& data, std::string mimeType){
248
0
  std::string url = "data:"+mimeType+";"+"base64,";
249
0
  std::string datab64 = base64Encode(std::string(data.begin(), data.end()));
250
0
  return url+datab64;
251
0
}
252
253
std::string hmac(const std::string& text,
254
                 const std::string& key,
255
                 std::string (*hashfunction)(const std::string&),
256
                 size_t blocksize,
257
                 size_t keysize)
258
0
{
259
0
  unsigned char ipad[256];
260
0
  unsigned char opad[256];
261
262
0
  std::memset(ipad, 0, sizeof(unsigned char) * blocksize);
263
264
0
  if (key.size() > blocksize) {
265
0
    std::memcpy(ipad, (unsigned char*) hashfunction(key).c_str(), keysize);
266
0
  }
267
0
  else {
268
0
    keysize = key.size();
269
0
    std::memcpy(ipad, (unsigned char*) key.c_str(), keysize);
270
0
  }
271
0
  std::memcpy(opad, ipad, blocksize);
272
273
0
  for (size_t i=0; i<blocksize; ++i) {
274
0
    ipad[i] ^= 0x36;
275
0
    opad[i] ^= 0x5c;
276
0
  }
277
278
0
  return hashfunction(std::string((char*) opad,blocksize)
279
0
       + hashfunction(std::string((char*) ipad,blocksize) + text));
280
0
}
281
282
std::string hmac_md5(const std::string& text, const std::string& key)
283
0
{
284
0
  return hmac(text,
285
0
              key,
286
0
              &md5,
287
0
              64,
288
0
              16);
289
0
}
290
291
std::string hmac_sha1(const std::string& text, const std::string& key)
292
0
{
293
0
  return hmac(text,
294
0
              key,
295
0
              &sha1,
296
0
              64,
297
0
              20);
298
0
}
299
300
std::vector<std::string> getWidgetStyleClasses(WWidget* widget)
301
0
{
302
0
  std::string styleClass = widget->styleClass().toUTF8();
303
0
  std::vector<std::string> styleClassVec;
304
0
  SplitSet styleClassSet;
305
306
0
  split(styleClassSet, styleClass, " ", false);
307
308
0
  for (const auto& entry : styleClassSet) {
309
0
    styleClassVec.push_back(splitEntryToString(entry));
310
0
  }
311
0
  return styleClassVec;
312
0
}
313
314
315
}
316
317
}