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
)
211 std::string::size_type pos
= 0;
212 std::string::size_type len
= str
.size();
213 if (len
== 1 && str
[0] == '.')
218 if (len
== 1 && str
[0] == '0')
227 bool isNumeric
= (str
[pos
] >= '0' && str
[pos
] <= '9')
228 || (pos
== 0 && str
[pos
] == '.')
229 || (pos
> 0 && str
[pos
] == '.' && str
[pos
-1] >= '0' && str
[pos
-1] <= '9');
238 unit
= toLowerAscii(str
.substr(pos
));
239 if (unit
== "%" || unit
== "rem" || unit
== "em" || unit
== "px" || unit
== "pt")
241 std::string tmpstr
= str
.substr(0, pos
);
242 return fromString(tmpstr
, value
);
248 // Read a width HTML parameter. "100" or "100%". Returns true if percent (0 ~ 1) else false
249 bool getPercentage (sint32
&width
, float &percent
, const char *str
)
252 const char *percentChar
;
253 if ((percentChar
= strchr (str
, '%')) != NULL
)
255 std::string toto
= str
;
256 toto
= toto
.substr (0, percentChar
- str
);
257 fromString(toto
, percent
);
263 fromString(str
, width
);
268 static bool isHexa(char c
)
270 return isdigit(c
) || (tolower(c
) >= 'a' && tolower(c
) <= 'f');
273 static uint8
convertHexa(char c
)
275 return (uint8
) (tolower(c
) - (isdigit(c
) ? '0' : ('a' - 10)));
278 // scan a color component, and return pointer to next position
279 static const char *scanColorComponent(const char *src
, uint8
&intensity
)
281 if (!src
) return NULL
;
282 if (!isHexa(*src
)) return NULL
;
283 uint8 value
= convertHexa(*src
++) << 4;
284 if (!isHexa(*src
)) return NULL
;
285 value
+= convertHexa(*src
++);
290 static float hueToRgb(float m1
, float m2
, float h
)
292 if (h
< 0) h
+= 1.0f
;
293 if (h
> 1) h
-= 1.0f
;
294 if (h
*6 < 1.0f
) return m1
+ (m2
- m1
)*h
*6;
295 if (h
*2 < 1.0f
) return m2
;
296 if (h
*3 < 2.0f
) return m1
+ (m2
- m1
) * (2.0f
/3.0f
- h
)*6;
300 static void hslToRgb(float h
, float s
, float l
, CRGBA
&result
)
309 result
.R
= 255 * hueToRgb(m1
, m2
, h
+ 1.0f
/3.0f
);
310 result
.G
= 255 * hueToRgb(m1
, m2
, h
);
311 result
.B
= 255 * hueToRgb(m1
, m2
, h
- 1.0f
/3.0f
);
320 CNameToCol(const char *name
, CRGBA color
) : Name(name
), Color(color
) {}
323 static CNameToCol htmlColorNameToRGBA
[] =
325 CNameToCol("AliceBlue", CRGBA(0xF0, 0xF8, 0xFF)),
326 CNameToCol("AntiqueWhite", CRGBA(0xFA, 0xEB, 0xD7)),
327 CNameToCol("Aqua", CRGBA(0x00, 0xFF, 0xFF)),
328 CNameToCol("Aquamarine", CRGBA(0x7F, 0xFF, 0xD4)),
329 CNameToCol("Azure", CRGBA(0xF0, 0xFF, 0xFF)),
330 CNameToCol("Beige", CRGBA(0xF5, 0xF5, 0xDC)),
331 CNameToCol("Bisque", CRGBA(0xFF, 0xE4, 0xC4)),
332 CNameToCol("Black", CRGBA(0x00, 0x00, 0x00)),
333 CNameToCol("BlanchedAlmond", CRGBA(0xFF, 0xEB, 0xCD)),
334 CNameToCol("Blue", CRGBA(0x00, 0x00, 0xFF)),
335 CNameToCol("BlueViolet", CRGBA(0x8A, 0x2B, 0xE2)),
336 CNameToCol("Brown", CRGBA(0xA5, 0x2A, 0x2A)),
337 CNameToCol("BurlyWood", CRGBA(0xDE, 0xB8, 0x87)),
338 CNameToCol("CadetBlue", CRGBA(0x5F, 0x9E, 0xA0)),
339 CNameToCol("Chartreuse", CRGBA(0x7F, 0xFF, 0x00)),
340 CNameToCol("Chocolate", CRGBA(0xD2, 0x69, 0x1E)),
341 CNameToCol("Coral", CRGBA(0xFF, 0x7F, 0x50)),
342 CNameToCol("CornflowerBlue", CRGBA(0x64, 0x95, 0xED)),
343 CNameToCol("Cornsilk", CRGBA(0xFF, 0xF8, 0xDC)),
344 CNameToCol("Crimson", CRGBA(0xDC, 0x14, 0x3C)),
345 CNameToCol("Cyan", CRGBA(0x00, 0xFF, 0xFF)),
346 CNameToCol("DarkBlue", CRGBA(0x00, 0x00, 0x8B)),
347 CNameToCol("DarkCyan", CRGBA(0x00, 0x8B, 0x8B)),
348 CNameToCol("DarkGoldenRod", CRGBA(0xB8, 0x86, 0x0B)),
349 CNameToCol("DarkGray", CRGBA(0xA9, 0xA9, 0xA9)),
350 CNameToCol("DarkGreen", CRGBA(0x00, 0x64, 0x00)),
351 CNameToCol("DarkKhaki", CRGBA(0xBD, 0xB7, 0x6B)),
352 CNameToCol("DarkMagenta", CRGBA(0x8B, 0x00, 0x8B)),
353 CNameToCol("DarkOliveGreen", CRGBA(0x55, 0x6B, 0x2F)),
354 CNameToCol("Darkorange", CRGBA(0xFF, 0x8C, 0x00)),
355 CNameToCol("DarkOrchid", CRGBA(0x99, 0x32, 0xCC)),
356 CNameToCol("DarkRed", CRGBA(0x8B, 0x00, 0x00)),
357 CNameToCol("DarkSalmon", CRGBA(0xE9, 0x96, 0x7A)),
358 CNameToCol("DarkSeaGreen", CRGBA(0x8F, 0xBC, 0x8F)),
359 CNameToCol("DarkSlateBlue", CRGBA(0x48, 0x3D, 0x8B)),
360 CNameToCol("DarkSlateGray", CRGBA(0x2F, 0x4F, 0x4F)),
361 CNameToCol("DarkTurquoise", CRGBA(0x00, 0xCE, 0xD1)),
362 CNameToCol("DarkViolet", CRGBA(0x94, 0x00, 0xD3)),
363 CNameToCol("DeepPink", CRGBA(0xFF, 0x14, 0x93)),
364 CNameToCol("DeepSkyBlue", CRGBA(0x00, 0xBF, 0xFF)),
365 CNameToCol("DimGray", CRGBA(0x69, 0x69, 0x69)),
366 CNameToCol("DodgerBlue", CRGBA(0x1E, 0x90, 0xFF)),
367 CNameToCol("Feldspar", CRGBA(0xD1, 0x92, 0x75)),
368 CNameToCol("FireBrick", CRGBA(0xB2, 0x22, 0x22)),
369 CNameToCol("FloralWhite", CRGBA(0xFF, 0xFA, 0xF0)),
370 CNameToCol("ForestGreen", CRGBA(0x22, 0x8B, 0x22)),
371 CNameToCol("Fuchsia", CRGBA(0xFF, 0x00, 0xFF)),
372 CNameToCol("Gainsboro", CRGBA(0xDC, 0xDC, 0xDC)),
373 CNameToCol("GhostWhite", CRGBA(0xF8, 0xF8, 0xFF)),
374 CNameToCol("Gold", CRGBA(0xFF, 0xD7, 0x00)),
375 CNameToCol("GoldenRod", CRGBA(0xDA, 0xA5, 0x20)),
376 CNameToCol("Gray", CRGBA(0x80, 0x80, 0x80)),
377 CNameToCol("Green", CRGBA(0x00, 0x80, 0x00)),
378 CNameToCol("GreenYellow", CRGBA(0xAD, 0xFF, 0x2F)),
379 CNameToCol("HoneyDew", CRGBA(0xF0, 0xFF, 0xF0)),
380 CNameToCol("HotPink", CRGBA(0xFF, 0x69, 0xB4)),
381 CNameToCol("IndianRed ", CRGBA(0xCD, 0x5C, 0x5C)),
382 CNameToCol("Indigo ", CRGBA(0x4B, 0x00, 0x82)),
383 CNameToCol("Ivory", CRGBA(0xFF, 0xFF, 0xF0)),
384 CNameToCol("Khaki", CRGBA(0xF0, 0xE6, 0x8C)),
385 CNameToCol("Lavender", CRGBA(0xE6, 0xE6, 0xFA)),
386 CNameToCol("LavenderBlush", CRGBA(0xFF, 0xF0, 0xF5)),
387 CNameToCol("LawnGreen", CRGBA(0x7C, 0xFC, 0x00)),
388 CNameToCol("LemonChiffon", CRGBA(0xFF, 0xFA, 0xCD)),
389 CNameToCol("LightBlue", CRGBA(0xAD, 0xD8, 0xE6)),
390 CNameToCol("LightCoral", CRGBA(0xF0, 0x80, 0x80)),
391 CNameToCol("LightCyan", CRGBA(0xE0, 0xFF, 0xFF)),
392 CNameToCol("LightGoldenRodYellow", CRGBA(0xFA, 0xFA, 0xD2)),
393 CNameToCol("LightGrey", CRGBA(0xD3, 0xD3, 0xD3)),
394 CNameToCol("LightGreen", CRGBA(0x90, 0xEE, 0x90)),
395 CNameToCol("LightPink", CRGBA(0xFF, 0xB6, 0xC1)),
396 CNameToCol("LightSalmon", CRGBA(0xFF, 0xA0, 0x7A)),
397 CNameToCol("LightSeaGreen", CRGBA(0x20, 0xB2, 0xAA)),
398 CNameToCol("LightSkyBlue", CRGBA(0x87, 0xCE, 0xFA)),
399 CNameToCol("LightSlateBlue", CRGBA(0x84, 0x70, 0xFF)),
400 CNameToCol("LightSlateGray", CRGBA(0x77, 0x88, 0x99)),
401 CNameToCol("LightSteelBlue", CRGBA(0xB0, 0xC4, 0xDE)),
402 CNameToCol("LightYellow", CRGBA(0xFF, 0xFF, 0xE0)),
403 CNameToCol("Lime", CRGBA(0x00, 0xFF, 0x00)),
404 CNameToCol("LimeGreen", CRGBA(0x32, 0xCD, 0x32)),
405 CNameToCol("Linen", CRGBA(0xFA, 0xF0, 0xE6)),
406 CNameToCol("Magenta", CRGBA(0xFF, 0x00, 0xFF)),
407 CNameToCol("Maroon", CRGBA(0x80, 0x00, 0x00)),
408 CNameToCol("MediumAquaMarine", CRGBA(0x66, 0xCD, 0xAA)),
409 CNameToCol("MediumBlue", CRGBA(0x00, 0x00, 0xCD)),
410 CNameToCol("MediumOrchid", CRGBA(0xBA, 0x55, 0xD3)),
411 CNameToCol("MediumPurple", CRGBA(0x93, 0x70, 0xD8)),
412 CNameToCol("MediumSeaGreen", CRGBA(0x3C, 0xB3, 0x71)),
413 CNameToCol("MediumSlateBlue", CRGBA(0x7B, 0x68, 0xEE)),
414 CNameToCol("MediumSpringGreen", CRGBA(0x00, 0xFA, 0x9A)),
415 CNameToCol("MediumTurquoise", CRGBA(0x48, 0xD1, 0xCC)),
416 CNameToCol("MediumVioletRed", CRGBA(0xC7, 0x15, 0x85)),
417 CNameToCol("MidnightBlue", CRGBA(0x19, 0x19, 0x70)),
418 CNameToCol("MintCream", CRGBA(0xF5, 0xFF, 0xFA)),
419 CNameToCol("MistyRose", CRGBA(0xFF, 0xE4, 0xE1)),
420 CNameToCol("Moccasin", CRGBA(0xFF, 0xE4, 0xB5)),
421 CNameToCol("NavajoWhite", CRGBA(0xFF, 0xDE, 0xAD)),
422 CNameToCol("Navy", CRGBA(0x00, 0x00, 0x80)),
423 CNameToCol("OldLace", CRGBA(0xFD, 0xF5, 0xE6)),
424 CNameToCol("Olive", CRGBA(0x80, 0x80, 0x00)),
425 CNameToCol("OliveDrab", CRGBA(0x6B, 0x8E, 0x23)),
426 CNameToCol("Orange", CRGBA(0xFF, 0xA5, 0x00)),
427 CNameToCol("OrangeRed", CRGBA(0xFF, 0x45, 0x00)),
428 CNameToCol("Orchid", CRGBA(0xDA, 0x70, 0xD6)),
429 CNameToCol("PaleGoldenRod", CRGBA(0xEE, 0xE8, 0xAA)),
430 CNameToCol("PaleGreen", CRGBA(0x98, 0xFB, 0x98)),
431 CNameToCol("PaleTurquoise", CRGBA(0xAF, 0xEE, 0xEE)),
432 CNameToCol("PaleVioletRed", CRGBA(0xD8, 0x70, 0x93)),
433 CNameToCol("PapayaWhip", CRGBA(0xFF, 0xEF, 0xD5)),
434 CNameToCol("PeachPuff", CRGBA(0xFF, 0xDA, 0xB9)),
435 CNameToCol("Peru", CRGBA(0xCD, 0x85, 0x3F)),
436 CNameToCol("Pink", CRGBA(0xFF, 0xC0, 0xCB)),
437 CNameToCol("Plum", CRGBA(0xDD, 0xA0, 0xDD)),
438 CNameToCol("PowderBlue", CRGBA(0xB0, 0xE0, 0xE6)),
439 CNameToCol("Purple", CRGBA(0x80, 0x00, 0x80)),
440 CNameToCol("Red", CRGBA(0xFF, 0x00, 0x00)),
441 CNameToCol("RosyBrown", CRGBA(0xBC, 0x8F, 0x8F)),
442 CNameToCol("RoyalBlue", CRGBA(0x41, 0x69, 0xE1)),
443 CNameToCol("SaddleBrown", CRGBA(0x8B, 0x45, 0x13)),
444 CNameToCol("Salmon", CRGBA(0xFA, 0x80, 0x72)),
445 CNameToCol("SandyBrown", CRGBA(0xF4, 0xA4, 0x60)),
446 CNameToCol("SeaGreen", CRGBA(0x2E, 0x8B, 0x57)),
447 CNameToCol("SeaShell", CRGBA(0xFF, 0xF5, 0xEE)),
448 CNameToCol("Sienna", CRGBA(0xA0, 0x52, 0x2D)),
449 CNameToCol("Silver", CRGBA(0xC0, 0xC0, 0xC0)),
450 CNameToCol("SkyBlue", CRGBA(0x87, 0xCE, 0xEB)),
451 CNameToCol("SlateBlue", CRGBA(0x6A, 0x5A, 0xCD)),
452 CNameToCol("SlateGray", CRGBA(0x70, 0x80, 0x90)),
453 CNameToCol("Snow", CRGBA(0xFF, 0xFA, 0xFA)),
454 CNameToCol("SpringGreen", CRGBA(0x00, 0xFF, 0x7F)),
455 CNameToCol("SteelBlue", CRGBA(0x46, 0x82, 0xB4)),
456 CNameToCol("Tan", CRGBA(0xD2, 0xB4, 0x8C)),
457 CNameToCol("Teal", CRGBA(0x00, 0x80, 0x80)),
458 CNameToCol("Thistle", CRGBA(0xD8, 0xBF, 0xD8)),
459 CNameToCol("Tomato", CRGBA(0xFF, 0x63, 0x47)),
460 CNameToCol("Turquoise", CRGBA(0x40, 0xE0, 0xD0)),
461 CNameToCol("Violet", CRGBA(0xEE, 0x82, 0xEE)),
462 CNameToCol("VioletRed", CRGBA(0xD0, 0x20, 0x90)),
463 CNameToCol("Wheat", CRGBA(0xF5, 0xDE, 0xB3)),
464 CNameToCol("White", CRGBA(0xFF, 0xFF, 0xFF)),
465 CNameToCol("WhiteSmoke", CRGBA(0xF5, 0xF5, 0xF5)),
466 CNameToCol("Yellow", CRGBA(0xFF, 0xFF, 0x00)),
467 CNameToCol("YellowGreen", CRGBA(0x9A, 0xCD, 0x32))
470 // scan a color from a HTML form (#rrggbb format)
471 bool scanHTMLColor(const char *src
, CRGBA
&dest
)
473 if (!src
|| *src
== '\0') return false;
477 if (strlen(src
) == 3 || strlen(src
) == 4)
479 bool hasAlpha
= (strlen(src
) == 4);
480 // check RGB for valid hex
481 if (isHexa(src
[0]) && isHexa(src
[1]) && isHexa(src
[2]))
483 // check optional A for valid hex
484 if (hasAlpha
&& !isHexa(src
[3])) return false;
486 dest
.R
= convertHexa(src
[0]);
487 dest
.G
= convertHexa(src
[1]);
488 dest
.B
= convertHexa(src
[2]);
490 dest
.R
= dest
.R
<< 4 | dest
.R
;
491 dest
.G
= dest
.G
<< 4 | dest
.G
;
492 dest
.B
= dest
.B
<< 4 | dest
.B
;
496 dest
.A
= convertHexa(src
[3]);
497 dest
.A
= dest
.A
<< 4 | dest
.A
;
509 src
= scanColorComponent(src
, result
.R
); if (!src
) return false;
510 src
= scanColorComponent(src
, result
.G
); if (!src
) return false;
511 src
= scanColorComponent(src
, result
.B
); if (!src
) return false;
512 src
= scanColorComponent(src
, result
.A
);
522 // TODO: CSS Colors Level 4 support
523 // Whitespace syntax, aliases: rgb == rgba, hsl == hsla
524 // rgb(51 170 51 / 0.4) /* 40% opaque green */
525 // rgb(51 170 51 / 40%) /* 40% opaque green */
527 if (strnicmp(src
, "rgb(", 4) == 0 || strnicmp(src
, "rgba(", 5) == 0)
530 if (*src
== '(') src
++;
532 std::vector
<std::string
> parts
;
533 NLMISC::splitString(src
, ",", parts
);
534 if (parts
.size() >= 3)
541 if (getPercentage(tmpv
, tmpf
, parts
[0].c_str())) tmpv
= 255 * tmpf
;
546 if (getPercentage(tmpv
, tmpf
, parts
[1].c_str())) tmpv
= 255 * tmpf
;
551 if (getPercentage(tmpv
, tmpf
, parts
[2].c_str())) tmpv
= 255 * tmpf
;
556 if (parts
.size() == 4)
558 if (!fromString(parts
[3], tmpf
)) return false;
559 if (parts
[3].find_first_of("%") != std::string::npos
)
576 if (strnicmp(src
, "hsl(", 4) == 0 || strnicmp(src
, "hsla(", 5) == 0)
579 if (*src
== '(') src
++;
581 std::vector
<std::string
> parts
;
582 NLMISC::splitString(src
, ",", parts
);
583 if (parts
.size() >= 3)
588 if (!fromString(parts
[0], tmpv
)) return false;
589 tmpv
= ((tmpv
% 360) + 360) % 360;
590 h
= (float) tmpv
/ 360.0f
;
593 if (!getPercentage(tmpv
, s
, parts
[1].c_str())) return false;
594 clamp(s
, 0.0f
, 1.0f
);
597 if (!getPercentage(tmpv
, l
, parts
[2].c_str())) return false;
598 clamp(l
, 0.0f
, 1.0f
);
601 hslToRgb(h
, s
, l
, result
);
604 if (parts
.size() == 4)
607 if (!fromString(parts
[3], tmpf
)) return false;
608 if (parts
[3].find_first_of("%") != std::string::npos
)
610 clamp(tmpf
, 0.0f
, 1.0f
);
611 result
.A
= 255 * tmpf
;
622 // slow but should suffice for now
623 for(uint k
= 0; k
< sizeofarray(htmlColorNameToRGBA
); ++k
)
625 if (nlstricmp(src
, htmlColorNameToRGBA
[k
].Name
) == 0)
627 dest
= htmlColorNameToRGBA
[k
].Color
;
635 // ***************************************************************************
637 CRGBA
getColor (const char *color
)
639 if (strlen (color
) != 7 && strlen (color
) != 9 )
641 char tmp
[3] = {0,0,0};
646 sscanf (tmp
, "%x", &value
);
647 dst
.R
= uint8(value
);
650 sscanf (tmp
, "%x", &value
);
651 dst
.G
= uint8(value
);
654 sscanf (tmp
, "%x", &value
);
655 dst
.B
= uint8(value
);
656 if (strlen (color
) == 9)
660 sscanf (tmp
, "%x", &value
);
661 dst
.A
= uint8(value
);
665 // extension to html ; try to parse an additional alpha
671 std::string
getRGBAString(const CRGBA
&color
)
673 return toString("rgba(%d, %d, %d, %.1f)", color
.R
, color
.G
, color
.B
, color
.A
/ 255.f
);
676 // update HTTPCookies list
677 static void receiveCookie(const char *nsformat
, const std::string
&domain
, bool trusted
)
680 // domain tailmatch path secure expires name value
681 // .app.ryzom.com TRUE / FALSE 1234 ryzomId AAAAAAAA|BBBBBBBB|CCCCCCCC
682 // #HttpOnly_app.ryzom.com FALSE / FALSE 0 PHPSESSID sess-id-value
683 std::string
cookie(nsformat
);
685 std::vector
<std::string
> chunks
;
686 splitString(cookie
, "\t", chunks
);
687 if (chunks
.size() < 6)
689 nlwarning("invalid cookie format '%s'", cookie
.c_str());
692 if (chunks
[0].find("#HttpOnly_") == 0)
694 chunks
[0] = chunks
[0].substr(10);
697 // make sure domain is lowercase
698 chunks
[0] = toLowerAscii(chunks
[0]);
700 if (chunks
[0] != domain
&& chunks
[0] != std::string("." + domain
))
702 // cookie is for different domain
703 //nlinfo("cookie for different domain ('%s')", nsformat);
707 if (chunks
[5] == "ryzomId")
709 // we receive this cookie because we are telling curl about this on send
710 // normally, this cookie should be set from client and not from headers
711 // it's used for R2 sessions
712 if (trusted
&& CurrentCookie
!= chunks
[6])
714 CurrentCookie
= chunks
[6];
715 nlwarning("received ryzomId cookie '%s' from trusted domain '%s'", CurrentCookie
.c_str(), domain
.c_str());
721 fromString(chunks
[4], expires
);
722 // expires == 0 is session cookie
727 if (expires
< (uint32
)now
)
729 nlwarning("cookie expired, remove from list '%s'", nsformat
);
730 HTTPCookies
[domain
].erase(chunks
[5]);
736 // this overrides cookies with same name, but different paths
737 //nlwarning("save domain '%s' cookie '%s' value '%s'", domain.c_str(), chunks[5].c_str(), nsformat);
738 HTTPCookies
[domain
][chunks
[5]] = nsformat
;
742 // update HTTPCookies with cookies received from curl
743 void receiveCookies (CURL
*curl
, const std::string
&domain
, bool trusted
)
745 struct curl_slist
*cookies
= NULL
;
746 if (curl_easy_getinfo(curl
, CURLINFO_COOKIELIST
, &cookies
) == CURLE_OK
)
748 struct curl_slist
*nc
;
752 //nlwarning("received cookie '%s'", nc->data);
753 receiveCookie(nc
->data
, domain
, trusted
);
757 curl_slist_free_all(cookies
);
761 // add all cookies for domain to curl handle
762 void sendCookies(CURL
*curl
, const std::string
&domain
, bool trusted
)
764 // enable curl cookie engine
765 curl_easy_setopt(curl
, CURLOPT_COOKIELIST
, "");
770 if (trusted
&& !CurrentCookie
.empty())
772 // domain tailmatch path secure expires name value
773 // .app.ryzom.com TRUE / FALSE 1234 ryzomId AAAAAAAA|BBBBBBBB|CCCCCCCC
774 // #HttpOnly_app.ryzom.com FALSE / FALSE 0 PHPSESSID sess-id-value
777 if (domain
[0] != '.' && domain
[0] != '#')
778 cookie
= "." + domain
+ "\tTRUE";
780 cookie
= domain
+ "\tFALSE";
781 cookie
+= "\t/\tFALSE\t0\tryzomId\t" + CurrentCookie
;
782 curl_easy_setopt(curl
, CURLOPT_COOKIELIST
, cookie
.c_str());
783 //nlwarning("domain '%s', cookie '%s'", domain.c_str(), cookie.c_str());
786 if(!HTTPCookies
[domain
].empty())
788 for(std::map
<std::string
, std::string
>::iterator it
= HTTPCookies
[domain
].begin(); it
!= HTTPCookies
[domain
].end(); it
++)
790 curl_easy_setopt(curl
, CURLOPT_COOKIELIST
, it
->second
.c_str());
791 //nlwarning("set domain '%s' cookie '%s'", domain.c_str(), it->second.c_str());
796 // ***************************************************************************