Use std::queue for HTTPFetchRequest and std::vector for log_output instead of std...
[oweals/minetest.git] / src / util / string.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "string.h"
21 #include "pointer.h"
22 #include "numeric.h"
23 #include "log.h"
24
25 #include "base64.h"
26 #include "hex.h"
27 #include "sha1.h"
28 #include "../porting.h"
29
30 #include <algorithm>
31 #include <sstream>
32 #include <iomanip>
33 #include <map>
34
35 #if defined(_WIN32)
36 #include <windows.h>  // MultiByteToWideChar
37 #endif
38
39 static bool parseHexColorString(const std::string &value, video::SColor &color);
40 static bool parseNamedColorString(const std::string &value, video::SColor &color);
41
42 #ifdef __ANDROID__
43
44 const wchar_t* wide_chars =
45         L" !\"#$%&'()*+,-./0123456789:;<=>?@"
46         L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"
47         L"abcdefghijklmnopqrstuvwxyz{|}~";
48
49 int wctomb(char *s, wchar_t wc)
50 {
51         for (unsigned int j = 0; j < (sizeof(wide_chars)/sizeof(wchar_t));j++) {
52                 if (wc == wide_chars[j]) {
53                         *s = (char) (j+32);
54                         return 1;
55                 }
56                 else if (wc == L'\n') {
57                         *s = '\n';
58                         return 1;
59                 }
60         }
61         return -1;
62 }
63
64 int mbtowc(wchar_t *pwc, const char *s, size_t n)
65 {
66         if (s == NULL || *s == '\0')
67                 return -1;
68
69         const wchar_t *tmp = narrow_to_wide_c(s);
70         bool success = tmp[0] != '\0';
71
72         if (success)
73                 *pwc = tmp[0];
74
75         delete tmp;
76
77         return success ? 1 : -1;
78 }
79
80 // You must free the returned string!
81 const wchar_t *narrow_to_wide_c(const char *mbs)
82 {
83         size_t mbl = strlen(mbs);
84         wchar_t *wcs = new wchar_t[mbl + 1];
85
86         size_t i, dest_i = 0;
87         for (i = 0; i < mbl; i++) {
88                 if (((unsigned char) mbs[i] > 31) &&
89                                 ((unsigned char) mbs[i] < 127)) {
90                         wcs[dest_i++] = wide_chars[(unsigned char) mbs[i] - 32];
91                 }
92                 //handle newline
93                 else if (mbs[i] == '\n') {
94                         wcs[dest_i++] = L'\n';
95                 }
96         }
97         wcs[dest_i] = '\0';
98
99         return wcs;
100 }
101
102 #else
103
104 // You must free the returned string!
105 const wchar_t *narrow_to_wide_c(const char *mbs)
106 {
107         wchar_t *wcs = NULL;
108 #if defined(_WIN32)
109         int nResult = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, 0, 0);
110         if (nResult == 0) {
111                 errorstream << "gettext: MultiByteToWideChar returned null" << std::endl;
112         } else {
113                 wcs = new wchar_t[nResult];
114                 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, (WCHAR *) wcs, nResult);
115         }
116 #else
117         size_t wcl = mbstowcs(NULL, mbs, 0);
118         if (wcl == (size_t) -1)
119                 return NULL;
120         wcs = new wchar_t[wcl + 1];
121         size_t l = mbstowcs(wcs, mbs, wcl);
122         assert(l != (size_t) -1); // Should never happen if the last call worked
123         wcs[l] = '\0';
124 #endif
125
126         return wcs;
127 }
128
129 #endif
130
131 std::wstring narrow_to_wide(const std::string& mbs)
132 {
133         size_t wcl = mbs.size();
134         Buffer<wchar_t> wcs(wcl + 1);
135         size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
136         if (l == (size_t)(-1))
137                 return L"<invalid multibyte string>";
138         wcs[l] = 0;
139         return *wcs;
140 }
141
142 #ifdef __ANDROID__
143 std::string wide_to_narrow(const std::wstring& wcs) {
144         size_t mbl = wcs.size()*4;
145
146         std::string retval = "";
147         for (unsigned int i = 0; i < wcs.size(); i++) {
148                 wchar_t char1 = (wchar_t) wcs[i];
149
150                 if (char1 == L'\n') {
151                         retval += '\n';
152                         continue;
153                 }
154
155                 for (unsigned int j = 0; j < wcslen(wide_chars);j++) {
156                         wchar_t char2 = (wchar_t) wide_chars[j];
157
158                         if (char1 == char2) {
159                                 char toadd = (j+32);
160                                 retval += toadd;
161                                 break;
162                         }
163                 }
164         }
165
166         return retval;
167 }
168 #else
169 std::string wide_to_narrow(const std::wstring& wcs)
170 {
171         size_t mbl = wcs.size()*4;
172         SharedBuffer<char> mbs(mbl+1);
173         size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
174         if(l == (size_t)(-1)) {
175                 return "Character conversion failed!";
176         }
177         else
178                 mbs[l] = 0;
179         return *mbs;
180 }
181
182 #endif
183
184 // Get an sha-1 hash of the player's name combined with
185 // the password entered. That's what the server uses as
186 // their password. (Exception : if the password field is
187 // blank, we send a blank password - this is for backwards
188 // compatibility with password-less players).
189 std::string translatePassword(std::string playername, std::wstring password)
190 {
191         if(password.length() == 0)
192                 return "";
193
194         std::string slt = playername + wide_to_narrow(password);
195         SHA1 sha1;
196         sha1.addBytes(slt.c_str(), slt.length());
197         unsigned char *digest = sha1.getDigest();
198         std::string pwd = base64_encode(digest, 20);
199         free(digest);
200         return pwd;
201 }
202
203 std::string urlencode(std::string str)
204 {
205         // Encodes non-unreserved URI characters by a percent sign
206         // followed by two hex digits. See RFC 3986, section 2.3.
207         static const char url_hex_chars[] = "0123456789ABCDEF";
208         std::ostringstream oss(std::ios::binary);
209         for (u32 i = 0; i < str.size(); i++) {
210                 unsigned char c = str[i];
211                 if (isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~')
212                         oss << c;
213                 else
214                         oss << "%"
215                                 << url_hex_chars[(c & 0xf0) >> 4]
216                                 << url_hex_chars[c & 0x0f];
217         }
218         return oss.str();
219 }
220
221 std::string urldecode(std::string str)
222 {
223         // Inverse of urlencode
224         std::ostringstream oss(std::ios::binary);
225         for (u32 i = 0; i < str.size(); i++) {
226                 unsigned char highvalue, lowvalue;
227                 if (str[i] == '%' &&
228                                 hex_digit_decode(str[i+1], highvalue) &&
229                                 hex_digit_decode(str[i+2], lowvalue)) {
230                         oss << (char) ((highvalue << 4) | lowvalue);
231                         i += 2;
232                 }
233                 else
234                         oss << str[i];
235         }
236         return oss.str();
237 }
238
239 u32 readFlagString(std::string str, const FlagDesc *flagdesc, u32 *flagmask)
240 {
241         u32 result = 0, mask = 0;
242         char *s = &str[0];
243         char *flagstr, *strpos = NULL;
244
245         while ((flagstr = strtok_r(s, ",", &strpos))) {
246                 s = NULL;
247
248                 while (*flagstr == ' ' || *flagstr == '\t')
249                         flagstr++;
250
251                 bool flagset = true;
252                 if (!strncasecmp(flagstr, "no", 2)) {
253                         flagset = false;
254                         flagstr += 2;
255                 }
256
257                 for (int i = 0; flagdesc[i].name; i++) {
258                         if (!strcasecmp(flagstr, flagdesc[i].name)) {
259                                 mask |= flagdesc[i].flag;
260                                 if (flagset)
261                                         result |= flagdesc[i].flag;
262                                 break;
263                         }
264                 }
265         }
266
267         if (flagmask)
268                 *flagmask = mask;
269
270         return result;
271 }
272
273 std::string writeFlagString(u32 flags, const FlagDesc *flagdesc, u32 flagmask)
274 {
275         std::string result;
276
277         for (int i = 0; flagdesc[i].name; i++) {
278                 if (flagmask & flagdesc[i].flag) {
279                         if (!(flags & flagdesc[i].flag))
280                                 result += "no";
281
282                         result += flagdesc[i].name;
283                         result += ", ";
284                 }
285         }
286
287         size_t len = result.length();
288         if (len >= 2)
289                 result.erase(len - 2, 2);
290
291         return result;
292 }
293
294 size_t mystrlcpy(char *dst, const char *src, size_t size)
295 {
296         size_t srclen  = strlen(src) + 1;
297         size_t copylen = MYMIN(srclen, size);
298
299         if (copylen > 0) {
300                 memcpy(dst, src, copylen);
301                 dst[copylen - 1] = '\0';
302         }
303
304         return srclen;
305 }
306
307 char *mystrtok_r(char *s, const char *sep, char **lasts)
308 {
309         char *t;
310
311         if (!s)
312                 s = *lasts;
313
314         while (*s && strchr(sep, *s))
315                 s++;
316
317         if (!*s)
318                 return NULL;
319
320         t = s;
321         while (*t) {
322                 if (strchr(sep, *t)) {
323                         *t++ = '\0';
324                         break;
325                 }
326                 t++;
327         }
328         
329         *lasts = t;
330         return s;
331 }
332
333 u64 read_seed(const char *str)
334 {
335         char *endptr;
336         u64 num;
337         
338         if (str[0] == '0' && str[1] == 'x')
339                 num = strtoull(str, &endptr, 16);
340         else
341                 num = strtoull(str, &endptr, 10);
342                 
343         if (*endptr)
344                 num = murmur_hash_64_ua(str, (int)strlen(str), 0x1337);
345                 
346         return num;
347 }
348
349 bool parseColorString(const std::string &value, video::SColor &color, bool quiet)
350 {
351         bool success;
352
353         if (value[0] == '#')
354                 success = parseHexColorString(value, color);
355         else
356                 success = parseNamedColorString(value, color);
357
358         if (!success && !quiet)
359                 errorstream << "Invalid color: \"" << value << "\"" << std::endl;
360
361         return success;
362 }
363
364 static bool parseHexColorString(const std::string &value, video::SColor &color)
365 {
366         unsigned char components[] = { 0x00, 0x00, 0x00, 0xff }; // R,G,B,A
367
368         if (value[0] != '#')
369                 return false;
370
371         size_t len = value.size();
372         bool short_form;
373
374         if (len == 9 || len == 7) // #RRGGBBAA or #RRGGBB
375                 short_form = false;
376         else if (len == 5 || len == 4) // #RGBA or #RGB
377                 short_form = true;
378         else
379                 return false;
380
381         bool success = true;
382
383         for (size_t pos = 1, cc = 0; pos < len; pos++, cc++) {
384                 assert(cc < sizeof components / sizeof components[0]);
385                 if (short_form) {
386                         unsigned char d;
387                         if (!hex_digit_decode(value[pos], d)) {
388                                 success = false;
389                                 break;
390                         }
391                         components[cc] = (d & 0xf) << 4 | (d & 0xf);
392                 } else {
393                         unsigned char d1, d2;
394                         if (!hex_digit_decode(value[pos], d1) ||
395                                         !hex_digit_decode(value[pos+1], d2)) {
396                                 success = false;
397                                 break;
398                         }
399                         components[cc] = (d1 & 0xf) << 4 | (d2 & 0xf);
400                         pos++;  // skip the second digit -- it's already used
401                 }
402         }
403
404         if (success) {
405                 color.setRed(components[0]);
406                 color.setGreen(components[1]);
407                 color.setBlue(components[2]);
408                 color.setAlpha(components[3]);
409         }
410
411         return success;
412 }
413
414 struct ColorContainer {
415         ColorContainer();
416         std::map<const std::string, u32> colors;
417 };
418
419 ColorContainer::ColorContainer()
420 {
421         colors["aliceblue"]              = 0xf0f8ff;
422         colors["antiquewhite"]           = 0xfaebd7;
423         colors["aqua"]                   = 0x00ffff;
424         colors["aquamarine"]             = 0x7fffd4;
425         colors["azure"]                  = 0xf0ffff;
426         colors["beige"]                  = 0xf5f5dc;
427         colors["bisque"]                 = 0xffe4c4;
428         colors["black"]                  = 00000000;
429         colors["blanchedalmond"]         = 0xffebcd;
430         colors["blue"]                   = 0x0000ff;
431         colors["blueviolet"]             = 0x8a2be2;
432         colors["brown"]                  = 0xa52a2a;
433         colors["burlywood"]              = 0xdeb887;
434         colors["cadetblue"]              = 0x5f9ea0;
435         colors["chartreuse"]             = 0x7fff00;
436         colors["chocolate"]              = 0xd2691e;
437         colors["coral"]                  = 0xff7f50;
438         colors["cornflowerblue"]         = 0x6495ed;
439         colors["cornsilk"]               = 0xfff8dc;
440         colors["crimson"]                = 0xdc143c;
441         colors["cyan"]                   = 0x00ffff;
442         colors["darkblue"]               = 0x00008b;
443         colors["darkcyan"]               = 0x008b8b;
444         colors["darkgoldenrod"]          = 0xb8860b;
445         colors["darkgray"]               = 0xa9a9a9;
446         colors["darkgreen"]              = 0x006400;
447         colors["darkkhaki"]              = 0xbdb76b;
448         colors["darkmagenta"]            = 0x8b008b;
449         colors["darkolivegreen"]         = 0x556b2f;
450         colors["darkorange"]             = 0xff8c00;
451         colors["darkorchid"]             = 0x9932cc;
452         colors["darkred"]                = 0x8b0000;
453         colors["darksalmon"]             = 0xe9967a;
454         colors["darkseagreen"]           = 0x8fbc8f;
455         colors["darkslateblue"]          = 0x483d8b;
456         colors["darkslategray"]          = 0x2f4f4f;
457         colors["darkturquoise"]          = 0x00ced1;
458         colors["darkviolet"]             = 0x9400d3;
459         colors["deeppink"]               = 0xff1493;
460         colors["deepskyblue"]            = 0x00bfff;
461         colors["dimgray"]                = 0x696969;
462         colors["dodgerblue"]             = 0x1e90ff;
463         colors["firebrick"]              = 0xb22222;
464         colors["floralwhite"]            = 0xfffaf0;
465         colors["forestgreen"]            = 0x228b22;
466         colors["fuchsia"]                = 0xff00ff;
467         colors["gainsboro"]              = 0xdcdcdc;
468         colors["ghostwhite"]             = 0xf8f8ff;
469         colors["gold"]                   = 0xffd700;
470         colors["goldenrod"]              = 0xdaa520;
471         colors["gray"]                   = 0x808080;
472         colors["green"]                  = 0x008000;
473         colors["greenyellow"]            = 0xadff2f;
474         colors["honeydew"]               = 0xf0fff0;
475         colors["hotpink"]                = 0xff69b4;
476         colors["indianred "]             = 0xcd5c5c;
477         colors["indigo "]                = 0x4b0082;
478         colors["ivory"]                  = 0xfffff0;
479         colors["khaki"]                  = 0xf0e68c;
480         colors["lavender"]               = 0xe6e6fa;
481         colors["lavenderblush"]          = 0xfff0f5;
482         colors["lawngreen"]              = 0x7cfc00;
483         colors["lemonchiffon"]           = 0xfffacd;
484         colors["lightblue"]              = 0xadd8e6;
485         colors["lightcoral"]             = 0xf08080;
486         colors["lightcyan"]              = 0xe0ffff;
487         colors["lightgoldenrodyellow"]   = 0xfafad2;
488         colors["lightgray"]              = 0xd3d3d3;
489         colors["lightgreen"]             = 0x90ee90;
490         colors["lightpink"]              = 0xffb6c1;
491         colors["lightsalmon"]            = 0xffa07a;
492         colors["lightseagreen"]          = 0x20b2aa;
493         colors["lightskyblue"]           = 0x87cefa;
494         colors["lightslategray"]         = 0x778899;
495         colors["lightsteelblue"]         = 0xb0c4de;
496         colors["lightyellow"]            = 0xffffe0;
497         colors["lime"]                   = 0x00ff00;
498         colors["limegreen"]              = 0x32cd32;
499         colors["linen"]                  = 0xfaf0e6;
500         colors["magenta"]                = 0xff00ff;
501         colors["maroon"]                 = 0x800000;
502         colors["mediumaquamarine"]       = 0x66cdaa;
503         colors["mediumblue"]             = 0x0000cd;
504         colors["mediumorchid"]           = 0xba55d3;
505         colors["mediumpurple"]           = 0x9370db;
506         colors["mediumseagreen"]         = 0x3cb371;
507         colors["mediumslateblue"]        = 0x7b68ee;
508         colors["mediumspringgreen"]      = 0x00fa9a;
509         colors["mediumturquoise"]        = 0x48d1cc;
510         colors["mediumvioletred"]        = 0xc71585;
511         colors["midnightblue"]           = 0x191970;
512         colors["mintcream"]              = 0xf5fffa;
513         colors["mistyrose"]              = 0xffe4e1;
514         colors["moccasin"]               = 0xffe4b5;
515         colors["navajowhite"]            = 0xffdead;
516         colors["navy"]                   = 0x000080;
517         colors["oldlace"]                = 0xfdf5e6;
518         colors["olive"]                  = 0x808000;
519         colors["olivedrab"]              = 0x6b8e23;
520         colors["orange"]                 = 0xffa500;
521         colors["orangered"]              = 0xff4500;
522         colors["orchid"]                 = 0xda70d6;
523         colors["palegoldenrod"]          = 0xeee8aa;
524         colors["palegreen"]              = 0x98fb98;
525         colors["paleturquoise"]          = 0xafeeee;
526         colors["palevioletred"]          = 0xdb7093;
527         colors["papayawhip"]             = 0xffefd5;
528         colors["peachpuff"]              = 0xffdab9;
529         colors["peru"]                   = 0xcd853f;
530         colors["pink"]                   = 0xffc0cb;
531         colors["plum"]                   = 0xdda0dd;
532         colors["powderblue"]             = 0xb0e0e6;
533         colors["purple"]                 = 0x800080;
534         colors["red"]                    = 0xff0000;
535         colors["rosybrown"]              = 0xbc8f8f;
536         colors["royalblue"]              = 0x4169e1;
537         colors["saddlebrown"]            = 0x8b4513;
538         colors["salmon"]                 = 0xfa8072;
539         colors["sandybrown"]             = 0xf4a460;
540         colors["seagreen"]               = 0x2e8b57;
541         colors["seashell"]               = 0xfff5ee;
542         colors["sienna"]                 = 0xa0522d;
543         colors["silver"]                 = 0xc0c0c0;
544         colors["skyblue"]                = 0x87ceeb;
545         colors["slateblue"]              = 0x6a5acd;
546         colors["slategray"]              = 0x708090;
547         colors["snow"]                   = 0xfffafa;
548         colors["springgreen"]            = 0x00ff7f;
549         colors["steelblue"]              = 0x4682b4;
550         colors["tan"]                    = 0xd2b48c;
551         colors["teal"]                   = 0x008080;
552         colors["thistle"]                = 0xd8bfd8;
553         colors["tomato"]                 = 0xff6347;
554         colors["turquoise"]              = 0x40e0d0;
555         colors["violet"]                 = 0xee82ee;
556         colors["wheat"]                  = 0xf5deb3;
557         colors["white"]                  = 0xffffff;
558         colors["whitesmoke"]             = 0xf5f5f5;
559         colors["yellow"]                 = 0xffff00;
560         colors["yellowgreen"]            = 0x9acd32;
561
562 }
563
564 static const ColorContainer named_colors;
565
566 static bool parseNamedColorString(const std::string &value, video::SColor &color)
567 {
568         std::string color_name;
569         std::string alpha_string;
570
571         /* If the string has a # in it, assume this is the start of a specified
572          * alpha value (if it isn't the string is invalid and the error will be
573          * caught later on, either because the color name won't be found or the
574          * alpha value will fail conversion)
575          */
576         size_t alpha_pos = value.find('#');
577         if (alpha_pos != std::string::npos) {
578                 color_name = value.substr(0, alpha_pos);
579                 alpha_string = value.substr(alpha_pos + 1);
580         } else {
581                 color_name = value;
582         }
583
584         color_name = lowercase(value);
585
586         std::map<const std::string, unsigned>::const_iterator it;
587         it = named_colors.colors.find(color_name);
588         if (it == named_colors.colors.end())
589                 return false;
590
591         u32 color_temp = it->second;
592
593         /* An empty string for alpha is ok (none of the color table entries
594          * have an alpha value either). Color strings without an alpha specified
595          * are interpreted as fully opaque
596          *
597          * For named colors the supplied alpha string (representing a hex value)
598          * must be exactly two digits. For example:  colorname#08
599          */
600         if (!alpha_string.empty()) {
601                 if (alpha_string.length() != 2)
602                         return false;
603
604                 unsigned char d1, d2;
605                 if (!hex_digit_decode(alpha_string.at(0), d1)
606                                 || !hex_digit_decode(alpha_string.at(1), d2))
607                         return false;
608                 color_temp |= ((d1 & 0xf) << 4 | (d2 & 0xf)) << 24;
609         } else {
610                 color_temp |= 0xff << 24;  // Fully opaque
611         }
612
613         color = video::SColor(color_temp);
614
615         return true;
616 }
617
618 void str_replace(std::string &str, char from, char to)
619 {
620         std::replace(str.begin(), str.end(), from, to);
621 }
622