1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "nel/gui/libwww.h"
24 #include "nel/gui/group_html.h"
26 #include <curl/curl.h>
28 using namespace NLMISC
;
36 struct CNameToHtmlElement
40 CNameToHtmlElement(HTMLElement id
, const char*name
)
41 : ID(id
), Name(name
) {}
44 // sorted list of HTML_ELEMENT enum to TAG name
45 static CNameToHtmlElement htmlElementToName
[] =
47 CNameToHtmlElement(HTML_A
, "a"),
48 CNameToHtmlElement(HTML_ABBR
, "abbr"),
49 CNameToHtmlElement(HTML_ADDRESS
, "address"),
50 CNameToHtmlElement(HTML_APPLET
, "applet"),
51 CNameToHtmlElement(HTML_AREA
, "area"),
52 CNameToHtmlElement(HTML_ARTICLE
, "article"),
53 CNameToHtmlElement(HTML_ASIDE
, "aside"),
54 CNameToHtmlElement(HTML_AUDIO
, "audio"),
55 CNameToHtmlElement(HTML_B
, "b"),
56 CNameToHtmlElement(HTML_BASE
, "base"),
57 CNameToHtmlElement(HTML_BDI
, "bdi"),
58 CNameToHtmlElement(HTML_BDO
, "bdo"),
59 CNameToHtmlElement(HTML_BLOCKQUOTE
, "blockquote"),
60 CNameToHtmlElement(HTML_BODY
, "body"),
61 CNameToHtmlElement(HTML_BR
, "br"),
62 CNameToHtmlElement(HTML_BUTTON
, "button"),
63 CNameToHtmlElement(HTML_CANVAS
, "canvas"),
64 CNameToHtmlElement(HTML_CAPTION
, "caption"),
65 CNameToHtmlElement(HTML_CITE
, "cite"),
66 CNameToHtmlElement(HTML_CODE
, "code"),
67 CNameToHtmlElement(HTML_COL
, "col"),
68 CNameToHtmlElement(HTML_COLGROUP
, "colgroup"),
69 CNameToHtmlElement(HTML_DATA
, "data"),
70 CNameToHtmlElement(HTML_DATALIST
, "datalist"),
71 CNameToHtmlElement(HTML_DD
, "dd"),
72 CNameToHtmlElement(HTML_DEL
, "del"),
73 CNameToHtmlElement(HTML_DETAILS
, "details"),
74 CNameToHtmlElement(HTML_DFN
, "dfn"),
75 CNameToHtmlElement(HTML_DIALOG
, "dialog"),
76 CNameToHtmlElement(HTML_DIR
, "dir"),
77 CNameToHtmlElement(HTML_DIV
, "div"),
78 CNameToHtmlElement(HTML_DL
, "dl"),
79 CNameToHtmlElement(HTML_DT
, "dt"),
80 CNameToHtmlElement(HTML_EM
, "em"),
81 CNameToHtmlElement(HTML_EMBED
, "embed"),
82 CNameToHtmlElement(HTML_FIELDSET
, "fieldset"),
83 CNameToHtmlElement(HTML_FIGCAPTION
, "figcaption"),
84 CNameToHtmlElement(HTML_FIGURE
, "figure"),
85 CNameToHtmlElement(HTML_FONT
, "font"),
86 CNameToHtmlElement(HTML_FOOTER
, "footer"),
87 CNameToHtmlElement(HTML_FORM
, "form"),
88 CNameToHtmlElement(HTML_H1
, "h1"),
89 CNameToHtmlElement(HTML_H2
, "h2"),
90 CNameToHtmlElement(HTML_H3
, "h3"),
91 CNameToHtmlElement(HTML_H4
, "h4"),
92 CNameToHtmlElement(HTML_H5
, "h5"),
93 CNameToHtmlElement(HTML_H6
, "h6"),
94 CNameToHtmlElement(HTML_HEAD
, "head"),
95 CNameToHtmlElement(HTML_HEADER
, "header"),
96 CNameToHtmlElement(HTML_HGROUP
, "hgroup"),
97 CNameToHtmlElement(HTML_HR
, "hr"),
98 CNameToHtmlElement(HTML_HTML
, "html"),
99 CNameToHtmlElement(HTML_I
, "i"),
100 CNameToHtmlElement(HTML_IFRAME
, "iframe"),
101 CNameToHtmlElement(HTML_IMG
, "img"),
102 CNameToHtmlElement(HTML_INPUT
, "input"),
103 CNameToHtmlElement(HTML_INS
, "ins"),
104 CNameToHtmlElement(HTML_KBD
, "kbd"),
105 CNameToHtmlElement(HTML_LABEL
, "label"),
106 CNameToHtmlElement(HTML_LEGEND
, "legend"),
107 CNameToHtmlElement(HTML_LI
, "li"),
108 CNameToHtmlElement(HTML_LINK
, "link"),
109 CNameToHtmlElement(HTML_LUA
, "lua"),
110 CNameToHtmlElement(HTML_MAIN
, "main"),
111 CNameToHtmlElement(HTML_MAP
, "map"),
112 CNameToHtmlElement(HTML_MARK
, "mark"),
113 CNameToHtmlElement(HTML_MENU
, "menu"),
114 CNameToHtmlElement(HTML_MENUITEM
, "menuitem"),
115 CNameToHtmlElement(HTML_META
, "meta"),
116 CNameToHtmlElement(HTML_METER
, "meter"),
117 CNameToHtmlElement(HTML_NAV
, "nav"),
118 CNameToHtmlElement(HTML_NOEMBED
, "noembed"),
119 CNameToHtmlElement(HTML_NOSCRIPT
, "noscript"),
120 CNameToHtmlElement(HTML_OBJECT
, "object"),
121 CNameToHtmlElement(HTML_OL
, "ol"),
122 CNameToHtmlElement(HTML_OPTGROUP
, "optgroup"),
123 CNameToHtmlElement(HTML_OPTION
, "option"),
124 CNameToHtmlElement(HTML_OUTPUT
, "output"),
125 CNameToHtmlElement(HTML_P
, "p"),
126 CNameToHtmlElement(HTML_PARAM
, "param"),
127 CNameToHtmlElement(HTML_PICTURE
, "picture"),
128 CNameToHtmlElement(HTML_PRE
, "pre"),
129 CNameToHtmlElement(HTML_PROGRESS
, "progress"),
130 CNameToHtmlElement(HTML_Q
, "q"),
131 CNameToHtmlElement(HTML_RB
, "rb"),
132 CNameToHtmlElement(HTML_RP
, "rp"),
133 CNameToHtmlElement(HTML_RT
, "rt"),
134 CNameToHtmlElement(HTML_RTC
, "rtc"),
135 CNameToHtmlElement(HTML_RUBY
, "ruby"),
136 CNameToHtmlElement(HTML_S
, "s"),
137 CNameToHtmlElement(HTML_SAMP
, "samp"),
138 CNameToHtmlElement(HTML_SCRIPT
, "script"),
139 CNameToHtmlElement(HTML_SECTION
, "section"),
140 CNameToHtmlElement(HTML_SELECT
, "select"),
141 CNameToHtmlElement(HTML_SMALL
, "small"),
142 CNameToHtmlElement(HTML_SOURCE
, "source"),
143 CNameToHtmlElement(HTML_SPAN
, "span"),
144 CNameToHtmlElement(HTML_STRONG
, "strong"),
145 CNameToHtmlElement(HTML_STYLE
, "style"),
146 CNameToHtmlElement(HTML_SUB
, "sub"),
147 CNameToHtmlElement(HTML_SUMMARY
, "summary"),
148 CNameToHtmlElement(HTML_SUP
, "sup"),
149 CNameToHtmlElement(HTML_TABLE
, "table"),
150 CNameToHtmlElement(HTML_TBODY
, "tbody"),
151 CNameToHtmlElement(HTML_TD
, "td"),
152 CNameToHtmlElement(HTML_TEXTAREA
, "textarea"),
153 CNameToHtmlElement(HTML_TFOOT
, "tfoot"),
154 CNameToHtmlElement(HTML_TH
, "th"),
155 CNameToHtmlElement(HTML_THEAD
, "thead"),
156 CNameToHtmlElement(HTML_TIME
, "time"),
157 CNameToHtmlElement(HTML_TITLE
, "title"),
158 CNameToHtmlElement(HTML_TR
, "tr"),
159 CNameToHtmlElement(HTML_TRACK
, "track"),
160 CNameToHtmlElement(HTML_TT
, "tt"),
161 CNameToHtmlElement(HTML_U
, "u"),
162 CNameToHtmlElement(HTML_UL
, "ul"),
163 CNameToHtmlElement(HTML_VAR
, "var"),
164 CNameToHtmlElement(HTML_VIDEO
, "video"),
165 CNameToHtmlElement(HTML_WBR
, "wbr")
168 HTMLElement
htmlElementLookup(const char* name
)
170 uint end
= sizeofarray(htmlElementToName
);
175 sint ret
= nlstricmp(name
, htmlElementToName
[mid
].Name
);
178 return htmlElementToName
[mid
].ID
;
190 mid
+= (end
- mid
) >> 1;
195 return HTML_NB_ELEMENTS
;
198 // ***************************************************************************
200 /// the cookie value for session identification (nel cookie)
201 std::string CurrentCookie
;
203 /// store all cookies we receive and resent them depending of the domain
204 static std::map
<std::string
, std::map
<std::string
, std::string
> > HTTPCookies
;
206 // ***************************************************************************
208 // ***************************************************************************
209 bool getCssLength (float &value
, std::string
&unit
, const std::string
&str
, bool neg
)
211 static const std::set
<std::string
> knownUnits
= {
212 "%", "rem", "em", "px", "pt", "vw", "vh", "vi", "vb", "vmin", "vmax"
215 std::string::size_type pos
= 0;
216 std::string::size_type len
= str
.size();
222 if (len
== 1 && str
[0] == '0')
232 else if (neg
&& str
[0] == '-')
237 bool isNumeric
= (str
[pos
] >= '0' && str
[pos
] <= '9')
238 || (pos
== 0 && str
[pos
] == '.')
239 || (pos
> 0 && str
[pos
] == '.' && str
[pos
-1] >= '0' && str
[pos
-1] <= '9');
248 unit
= toLowerAscii(str
.substr(pos
));
249 if (knownUnits
.count(unit
))
251 std::string tmpstr
= str
.substr(0, pos
);
252 return fromString(tmpstr
, value
);
258 // Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false
259 bool getPercentage (sint32
&width
, float &percent
, const char *str
)
262 const char *percentChar
;
263 if ((percentChar
= strchr (str
, '%')) != NULL
)
265 std::string toto
= str
;
266 toto
= toto
.substr (0, percentChar
- str
);
267 fromString(toto
, percent
);
273 fromString(str
, width
);
278 static bool isHexa(char c
)
280 return isdigit(c
) || (tolower(c
) >= 'a' && tolower(c
) <= 'f');
283 static uint8
convertHexa(char c
)
285 return (uint8
) (tolower(c
) - (isdigit(c
) ? '0' : ('a' - 10)));
288 // scan a color component, and return pointer to next position
289 static const char *scanColorComponent(const char *src
, uint8
&intensity
)
291 if (!src
) return NULL
;
292 if (!isHexa(*src
)) return NULL
;
293 uint8 value
= convertHexa(*src
++) << 4;
294 if (!isHexa(*src
)) return NULL
;
295 value
+= convertHexa(*src
++);
300 static float hueToRgb(float m1
, float m2
, float h
)
302 if (h
< 0) h
+= 1.0f
;
303 if (h
> 1) h
-= 1.0f
;
304 if (h
*6 < 1.0f
) return m1
+ (m2
- m1
)*h
*6;
305 if (h
*2 < 1.0f
) return m2
;
306 if (h
*3 < 2.0f
) return m1
+ (m2
- m1
) * (2.0f
/3.0f
- h
)*6;
310 static void hslToRgb(float h
, float s
, float l
, CRGBA
&result
)
319 result
.R
= 255 * hueToRgb(m1
, m2
, h
+ 1.0f
/3.0f
);
320 result
.G
= 255 * hueToRgb(m1
, m2
, h
);
321 result
.B
= 255 * hueToRgb(m1
, m2
, h
- 1.0f
/3.0f
);
330 CNameToCol(const char *name
, CRGBA color
) : Name(name
), Color(color
) {}
333 static CNameToCol htmlColorNameToRGBA
[] =
335 CNameToCol("AliceBlue", CRGBA(0xF0, 0xF8, 0xFF)),
336 CNameToCol("AntiqueWhite", CRGBA(0xFA, 0xEB, 0xD7)),
337 CNameToCol("Aqua", CRGBA(0x00, 0xFF, 0xFF)),
338 CNameToCol("Aquamarine", CRGBA(0x7F, 0xFF, 0xD4)),
339 CNameToCol("Azure", CRGBA(0xF0, 0xFF, 0xFF)),
340 CNameToCol("Beige", CRGBA(0xF5, 0xF5, 0xDC)),
341 CNameToCol("Bisque", CRGBA(0xFF, 0xE4, 0xC4)),
342 CNameToCol("Black", CRGBA(0x00, 0x00, 0x00)),
343 CNameToCol("BlanchedAlmond", CRGBA(0xFF, 0xEB, 0xCD)),
344 CNameToCol("Blue", CRGBA(0x00, 0x00, 0xFF)),
345 CNameToCol("BlueViolet", CRGBA(0x8A, 0x2B, 0xE2)),
346 CNameToCol("Brown", CRGBA(0xA5, 0x2A, 0x2A)),
347 CNameToCol("BurlyWood", CRGBA(0xDE, 0xB8, 0x87)),
348 CNameToCol("CadetBlue", CRGBA(0x5F, 0x9E, 0xA0)),
349 CNameToCol("Chartreuse", CRGBA(0x7F, 0xFF, 0x00)),
350 CNameToCol("Chocolate", CRGBA(0xD2, 0x69, 0x1E)),
351 CNameToCol("Coral", CRGBA(0xFF, 0x7F, 0x50)),
352 CNameToCol("CornflowerBlue", CRGBA(0x64, 0x95, 0xED)),
353 CNameToCol("Cornsilk", CRGBA(0xFF, 0xF8, 0xDC)),
354 CNameToCol("Crimson", CRGBA(0xDC, 0x14, 0x3C)),
355 CNameToCol("Cyan", CRGBA(0x00, 0xFF, 0xFF)),
356 CNameToCol("DarkBlue", CRGBA(0x00, 0x00, 0x8B)),
357 CNameToCol("DarkCyan", CRGBA(0x00, 0x8B, 0x8B)),
358 CNameToCol("DarkGoldenRod", CRGBA(0xB8, 0x86, 0x0B)),
359 CNameToCol("DarkGray", CRGBA(0xA9, 0xA9, 0xA9)),
360 CNameToCol("DarkGreen", CRGBA(0x00, 0x64, 0x00)),
361 CNameToCol("DarkKhaki", CRGBA(0xBD, 0xB7, 0x6B)),
362 CNameToCol("DarkMagenta", CRGBA(0x8B, 0x00, 0x8B)),
363 CNameToCol("DarkOliveGreen", CRGBA(0x55, 0x6B, 0x2F)),
364 CNameToCol("Darkorange", CRGBA(0xFF, 0x8C, 0x00)),
365 CNameToCol("DarkOrchid", CRGBA(0x99, 0x32, 0xCC)),
366 CNameToCol("DarkRed", CRGBA(0x8B, 0x00, 0x00)),
367 CNameToCol("DarkSalmon", CRGBA(0xE9, 0x96, 0x7A)),
368 CNameToCol("DarkSeaGreen", CRGBA(0x8F, 0xBC, 0x8F)),
369 CNameToCol("DarkSlateBlue", CRGBA(0x48, 0x3D, 0x8B)),
370 CNameToCol("DarkSlateGray", CRGBA(0x2F, 0x4F, 0x4F)),
371 CNameToCol("DarkTurquoise", CRGBA(0x00, 0xCE, 0xD1)),
372 CNameToCol("DarkViolet", CRGBA(0x94, 0x00, 0xD3)),
373 CNameToCol("DeepPink", CRGBA(0xFF, 0x14, 0x93)),
374 CNameToCol("DeepSkyBlue", CRGBA(0x00, 0xBF, 0xFF)),
375 CNameToCol("DimGray", CRGBA(0x69, 0x69, 0x69)),
376 CNameToCol("DodgerBlue", CRGBA(0x1E, 0x90, 0xFF)),
377 CNameToCol("Feldspar", CRGBA(0xD1, 0x92, 0x75)),
378 CNameToCol("FireBrick", CRGBA(0xB2, 0x22, 0x22)),
379 CNameToCol("FloralWhite", CRGBA(0xFF, 0xFA, 0xF0)),
380 CNameToCol("ForestGreen", CRGBA(0x22, 0x8B, 0x22)),
381 CNameToCol("Fuchsia", CRGBA(0xFF, 0x00, 0xFF)),
382 CNameToCol("Gainsboro", CRGBA(0xDC, 0xDC, 0xDC)),
383 CNameToCol("GhostWhite", CRGBA(0xF8, 0xF8, 0xFF)),
384 CNameToCol("Gold", CRGBA(0xFF, 0xD7, 0x00)),
385 CNameToCol("GoldenRod", CRGBA(0xDA, 0xA5, 0x20)),
386 CNameToCol("Gray", CRGBA(0x80, 0x80, 0x80)),
387 CNameToCol("Green", CRGBA(0x00, 0x80, 0x00)),
388 CNameToCol("GreenYellow", CRGBA(0xAD, 0xFF, 0x2F)),
389 CNameToCol("HoneyDew", CRGBA(0xF0, 0xFF, 0xF0)),
390 CNameToCol("HotPink", CRGBA(0xFF, 0x69, 0xB4)),
391 CNameToCol("IndianRed ", CRGBA(0xCD, 0x5C, 0x5C)),
392 CNameToCol("Indigo ", CRGBA(0x4B, 0x00, 0x82)),
393 CNameToCol("Ivory", CRGBA(0xFF, 0xFF, 0xF0)),
394 CNameToCol("Khaki", CRGBA(0xF0, 0xE6, 0x8C)),
395 CNameToCol("Lavender", CRGBA(0xE6, 0xE6, 0xFA)),
396 CNameToCol("LavenderBlush", CRGBA(0xFF, 0xF0, 0xF5)),
397 CNameToCol("LawnGreen", CRGBA(0x7C, 0xFC, 0x00)),
398 CNameToCol("LemonChiffon", CRGBA(0xFF, 0xFA, 0xCD)),
399 CNameToCol("LightBlue", CRGBA(0xAD, 0xD8, 0xE6)),
400 CNameToCol("LightCoral", CRGBA(0xF0, 0x80, 0x80)),
401 CNameToCol("LightCyan", CRGBA(0xE0, 0xFF, 0xFF)),
402 CNameToCol("LightGoldenRodYellow", CRGBA(0xFA, 0xFA, 0xD2)),
403 CNameToCol("LightGrey", CRGBA(0xD3, 0xD3, 0xD3)),
404 CNameToCol("LightGreen", CRGBA(0x90, 0xEE, 0x90)),
405 CNameToCol("LightPink", CRGBA(0xFF, 0xB6, 0xC1)),
406 CNameToCol("LightSalmon", CRGBA(0xFF, 0xA0, 0x7A)),
407 CNameToCol("LightSeaGreen", CRGBA(0x20, 0xB2, 0xAA)),
408 CNameToCol("LightSkyBlue", CRGBA(0x87, 0xCE, 0xFA)),
409 CNameToCol("LightSlateBlue", CRGBA(0x84, 0x70, 0xFF)),
410 CNameToCol("LightSlateGray", CRGBA(0x77, 0x88, 0x99)),
411 CNameToCol("LightSteelBlue", CRGBA(0xB0, 0xC4, 0xDE)),
412 CNameToCol("LightYellow", CRGBA(0xFF, 0xFF, 0xE0)),
413 CNameToCol("Lime", CRGBA(0x00, 0xFF, 0x00)),
414 CNameToCol("LimeGreen", CRGBA(0x32, 0xCD, 0x32)),
415 CNameToCol("Linen", CRGBA(0xFA, 0xF0, 0xE6)),
416 CNameToCol("Magenta", CRGBA(0xFF, 0x00, 0xFF)),
417 CNameToCol("Maroon", CRGBA(0x80, 0x00, 0x00)),
418 CNameToCol("MediumAquaMarine", CRGBA(0x66, 0xCD, 0xAA)),
419 CNameToCol("MediumBlue", CRGBA(0x00, 0x00, 0xCD)),
420 CNameToCol("MediumOrchid", CRGBA(0xBA, 0x55, 0xD3)),
421 CNameToCol("MediumPurple", CRGBA(0x93, 0x70, 0xD8)),
422 CNameToCol("MediumSeaGreen", CRGBA(0x3C, 0xB3, 0x71)),
423 CNameToCol("MediumSlateBlue", CRGBA(0x7B, 0x68, 0xEE)),
424 CNameToCol("MediumSpringGreen", CRGBA(0x00, 0xFA, 0x9A)),
425 CNameToCol("MediumTurquoise", CRGBA(0x48, 0xD1, 0xCC)),
426 CNameToCol("MediumVioletRed", CRGBA(0xC7, 0x15, 0x85)),
427 CNameToCol("MidnightBlue", CRGBA(0x19, 0x19, 0x70)),
428 CNameToCol("MintCream", CRGBA(0xF5, 0xFF, 0xFA)),
429 CNameToCol("MistyRose", CRGBA(0xFF, 0xE4, 0xE1)),
430 CNameToCol("Moccasin", CRGBA(0xFF, 0xE4, 0xB5)),
431 CNameToCol("NavajoWhite", CRGBA(0xFF, 0xDE, 0xAD)),
432 CNameToCol("Navy", CRGBA(0x00, 0x00, 0x80)),
433 CNameToCol("OldLace", CRGBA(0xFD, 0xF5, 0xE6)),
434 CNameToCol("Olive", CRGBA(0x80, 0x80, 0x00)),
435 CNameToCol("OliveDrab", CRGBA(0x6B, 0x8E, 0x23)),
436 CNameToCol("Orange", CRGBA(0xFF, 0xA5, 0x00)),
437 CNameToCol("OrangeRed", CRGBA(0xFF, 0x45, 0x00)),
438 CNameToCol("Orchid", CRGBA(0xDA, 0x70, 0xD6)),
439 CNameToCol("PaleGoldenRod", CRGBA(0xEE, 0xE8, 0xAA)),
440 CNameToCol("PaleGreen", CRGBA(0x98, 0xFB, 0x98)),
441 CNameToCol("PaleTurquoise", CRGBA(0xAF, 0xEE, 0xEE)),
442 CNameToCol("PaleVioletRed", CRGBA(0xD8, 0x70, 0x93)),
443 CNameToCol("PapayaWhip", CRGBA(0xFF, 0xEF, 0xD5)),
444 CNameToCol("PeachPuff", CRGBA(0xFF, 0xDA, 0xB9)),
445 CNameToCol("Peru", CRGBA(0xCD, 0x85, 0x3F)),
446 CNameToCol("Pink", CRGBA(0xFF, 0xC0, 0xCB)),
447 CNameToCol("Plum", CRGBA(0xDD, 0xA0, 0xDD)),
448 CNameToCol("PowderBlue", CRGBA(0xB0, 0xE0, 0xE6)),
449 CNameToCol("Purple", CRGBA(0x80, 0x00, 0x80)),
450 CNameToCol("Red", CRGBA(0xFF, 0x00, 0x00)),
451 CNameToCol("RosyBrown", CRGBA(0xBC, 0x8F, 0x8F)),
452 CNameToCol("RoyalBlue", CRGBA(0x41, 0x69, 0xE1)),
453 CNameToCol("SaddleBrown", CRGBA(0x8B, 0x45, 0x13)),
454 CNameToCol("Salmon", CRGBA(0xFA, 0x80, 0x72)),
455 CNameToCol("SandyBrown", CRGBA(0xF4, 0xA4, 0x60)),
456 CNameToCol("SeaGreen", CRGBA(0x2E, 0x8B, 0x57)),
457 CNameToCol("SeaShell", CRGBA(0xFF, 0xF5, 0xEE)),
458 CNameToCol("Sienna", CRGBA(0xA0, 0x52, 0x2D)),
459 CNameToCol("Silver", CRGBA(0xC0, 0xC0, 0xC0)),
460 CNameToCol("SkyBlue", CRGBA(0x87, 0xCE, 0xEB)),
461 CNameToCol("SlateBlue", CRGBA(0x6A, 0x5A, 0xCD)),
462 CNameToCol("SlateGray", CRGBA(0x70, 0x80, 0x90)),
463 CNameToCol("Snow", CRGBA(0xFF, 0xFA, 0xFA)),
464 CNameToCol("SpringGreen", CRGBA(0x00, 0xFF, 0x7F)),
465 CNameToCol("SteelBlue", CRGBA(0x46, 0x82, 0xB4)),
466 CNameToCol("Tan", CRGBA(0xD2, 0xB4, 0x8C)),
467 CNameToCol("Teal", CRGBA(0x00, 0x80, 0x80)),
468 CNameToCol("Thistle", CRGBA(0xD8, 0xBF, 0xD8)),
469 CNameToCol("Tomato", CRGBA(0xFF, 0x63, 0x47)),
470 CNameToCol("Turquoise", CRGBA(0x40, 0xE0, 0xD0)),
471 CNameToCol("Violet", CRGBA(0xEE, 0x82, 0xEE)),
472 CNameToCol("VioletRed", CRGBA(0xD0, 0x20, 0x90)),
473 CNameToCol("Wheat", CRGBA(0xF5, 0xDE, 0xB3)),
474 CNameToCol("White", CRGBA(0xFF, 0xFF, 0xFF)),
475 CNameToCol("WhiteSmoke", CRGBA(0xF5, 0xF5, 0xF5)),
476 CNameToCol("Yellow", CRGBA(0xFF, 0xFF, 0x00)),
477 CNameToCol("YellowGreen", CRGBA(0x9A, 0xCD, 0x32))
480 // scan a color from a HTML form (#rrggbb format)
481 bool scanHTMLColor(const char *src
, CRGBA
&dest
)
483 if (!src
|| *src
== '\0') return false;
487 if (strlen(src
) == 3 || strlen(src
) == 4)
489 bool hasAlpha
= (strlen(src
) == 4);
490 // check RGB for valid hex
491 if (isHexa(src
[0]) && isHexa(src
[1]) && isHexa(src
[2]))
493 // check optional A for valid hex
494 if (hasAlpha
&& !isHexa(src
[3])) return false;
496 dest
.R
= convertHexa(src
[0]);
497 dest
.G
= convertHexa(src
[1]);
498 dest
.B
= convertHexa(src
[2]);
500 dest
.R
= dest
.R
<< 4 | dest
.R
;
501 dest
.G
= dest
.G
<< 4 | dest
.G
;
502 dest
.B
= dest
.B
<< 4 | dest
.B
;
506 dest
.A
= convertHexa(src
[3]);
507 dest
.A
= dest
.A
<< 4 | dest
.A
;
519 src
= scanColorComponent(src
, result
.R
); if (!src
) return false;
520 src
= scanColorComponent(src
, result
.G
); if (!src
) return false;
521 src
= scanColorComponent(src
, result
.B
); if (!src
) return false;
522 src
= scanColorComponent(src
, result
.A
);
532 // TODO: CSS Colors Level 4 support
533 // Whitespace syntax, aliases: rgb == rgba, hsl == hsla
534 // rgb(51 170 51 / 0.4) /* 40% opaque green */
535 // rgb(51 170 51 / 40%) /* 40% opaque green */
537 if (strnicmp(src
, "rgb(", 4) == 0 || strnicmp(src
, "rgba(", 5) == 0)
540 if (*src
== '(') src
++;
542 std::vector
<std::string
> parts
;
543 NLMISC::splitString(src
, ",", parts
);
544 if (parts
.size() >= 3)
551 if (getPercentage(tmpv
, tmpf
, parts
[0].c_str())) tmpv
= 255 * tmpf
;
556 if (getPercentage(tmpv
, tmpf
, parts
[1].c_str())) tmpv
= 255 * tmpf
;
561 if (getPercentage(tmpv
, tmpf
, parts
[2].c_str())) tmpv
= 255 * tmpf
;
566 if (parts
.size() == 4)
568 if (!fromString(parts
[3], tmpf
)) return false;
569 if (parts
[3].find_first_of("%") != std::string::npos
)
586 if (strnicmp(src
, "hsl(", 4) == 0 || strnicmp(src
, "hsla(", 5) == 0)
589 if (*src
== '(') src
++;
591 std::vector
<std::string
> parts
;
592 NLMISC::splitString(src
, ",", parts
);
593 if (parts
.size() >= 3)
598 if (!fromString(parts
[0], tmpv
)) return false;
599 tmpv
= ((tmpv
% 360) + 360) % 360;
600 h
= (float) tmpv
/ 360.0f
;
603 if (!getPercentage(tmpv
, s
, parts
[1].c_str())) return false;
604 clamp(s
, 0.0f
, 1.0f
);
607 if (!getPercentage(tmpv
, l
, parts
[2].c_str())) return false;
608 clamp(l
, 0.0f
, 1.0f
);
611 hslToRgb(h
, s
, l
, result
);
614 if (parts
.size() == 4)
617 if (!fromString(parts
[3], tmpf
)) return false;
618 if (parts
[3].find_first_of("%") != std::string::npos
)
620 clamp(tmpf
, 0.0f
, 1.0f
);
621 result
.A
= 255 * tmpf
;
631 if (nlstricmp(src
, "transparent") == 0)
633 dest
= CRGBA::Transparent
;
638 // slow but should suffice for now
639 for(uint k
= 0; k
< sizeofarray(htmlColorNameToRGBA
); ++k
)
641 if (nlstricmp(src
, htmlColorNameToRGBA
[k
].Name
) == 0)
643 dest
= htmlColorNameToRGBA
[k
].Color
;
651 // ***************************************************************************
653 CRGBA
getColor (const char *color
)
655 if (strlen (color
) != 7 && strlen (color
) != 9 )
657 char tmp
[3] = {0,0,0};
662 sscanf (tmp
, "%x", &value
);
663 dst
.R
= uint8(value
);
666 sscanf (tmp
, "%x", &value
);
667 dst
.G
= uint8(value
);
670 sscanf (tmp
, "%x", &value
);
671 dst
.B
= uint8(value
);
672 if (strlen (color
) == 9)
676 sscanf (tmp
, "%x", &value
);
677 dst
.A
= uint8(value
);
681 // extension to html ; try to parse an additional alpha
687 std::string
getRGBAString(const CRGBA
&color
)
689 return toString("rgba(%d, %d, %d, %.1f)", color
.R
, color
.G
, color
.B
, color
.A
/ 255.f
);
692 // update HTTPCookies list
693 static void receiveCookie(const char *nsformat
, const std::string
&domain
, bool trusted
)
696 // domain tailmatch path secure expires name value
697 // .app.ryzom.com TRUE / FALSE 1234 ryzomId AAAAAAAA|BBBBBBBB|CCCCCCCC
698 // #HttpOnly_app.ryzom.com FALSE / FALSE 0 PHPSESSID sess-id-value
699 std::string
cookie(nsformat
);
701 std::vector
<std::string
> chunks
;
702 splitString(cookie
, "\t", chunks
);
703 if (chunks
.size() < 6)
705 nlwarning("invalid cookie format '%s'", cookie
.c_str());
708 if (chunks
[0].find("#HttpOnly_") == 0)
710 chunks
[0] = chunks
[0].substr(10);
713 // make sure domain is lowercase
714 chunks
[0] = toLowerAscii(chunks
[0]);
716 if (chunks
[0] != domain
&& chunks
[0] != std::string("." + domain
))
718 // cookie is for different domain
719 //nlinfo("cookie for different domain ('%s')", nsformat);
723 if (chunks
[5] == "ryzomId")
725 // we receive this cookie because we are telling curl about this on send
726 // normally, this cookie should be set from client and not from headers
727 // it's used for R2 sessions
728 if (trusted
&& CurrentCookie
!= chunks
[6])
730 CurrentCookie
= chunks
[6];
731 nlwarning("received ryzomId cookie '%s' from trusted domain '%s'", CurrentCookie
.c_str(), domain
.c_str());
737 fromString(chunks
[4], expires
);
738 // expires == 0 is session cookie
743 if (expires
< (uint32
)now
)
745 nlwarning("cookie expired, remove from list '%s'", nsformat
);
746 HTTPCookies
[domain
].erase(chunks
[5]);
752 // this overrides cookies with same name, but different paths
753 //nlwarning("save domain '%s' cookie '%s' value '%s'", domain.c_str(), chunks[5].c_str(), nsformat);
754 HTTPCookies
[domain
][chunks
[5]] = nsformat
;
758 // update HTTPCookies with cookies received from curl
759 void receiveCookies (CURL
*curl
, const std::string
&domain
, bool trusted
)
761 struct curl_slist
*cookies
= NULL
;
762 if (curl_easy_getinfo(curl
, CURLINFO_COOKIELIST
, &cookies
) == CURLE_OK
)
764 struct curl_slist
*nc
;
768 //nlwarning("received cookie '%s'", nc->data);
769 receiveCookie(nc
->data
, domain
, trusted
);
773 curl_slist_free_all(cookies
);
777 // add all cookies for domain to curl handle
778 void sendCookies(CURL
*curl
, const std::string
&domain
, bool trusted
)
780 // enable curl cookie engine
781 curl_easy_setopt(curl
, CURLOPT_COOKIELIST
, "");
786 if (trusted
&& !CurrentCookie
.empty())
788 // domain tailmatch path secure expires name value
789 // .app.ryzom.com TRUE / FALSE 1234 ryzomId AAAAAAAA|BBBBBBBB|CCCCCCCC
790 // #HttpOnly_app.ryzom.com FALSE / FALSE 0 PHPSESSID sess-id-value
793 if (domain
[0] != '.' && domain
[0] != '#')
794 cookie
= "." + domain
+ "\tTRUE";
796 cookie
= domain
+ "\tFALSE";
797 cookie
+= "\t/\tFALSE\t0\tryzomId\t" + CurrentCookie
;
798 curl_easy_setopt(curl
, CURLOPT_COOKIELIST
, cookie
.c_str());
799 //nlwarning("domain '%s', cookie '%s'", domain.c_str(), cookie.c_str());
802 if(!HTTPCookies
[domain
].empty())
804 for(std::map
<std::string
, std::string
>::iterator it
= HTTPCookies
[domain
].begin(); it
!= HTTPCookies
[domain
].end(); it
++)
806 curl_easy_setopt(curl
, CURLOPT_COOKIELIST
, it
->second
.c_str());
807 //nlwarning("set domain '%s' cookie '%s'", domain.c_str(), it->second.c_str());
812 // ***************************************************************************