| 1 | /* |
| 2 | * libwebsockets - small server side websockets and web server implementation |
| 3 | * |
| 4 | * Copyright (C) 2010 - 2022 Andy Green <andy@warmcat.com> |
| 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | * of this software and associated documentation files (the "Software"), to |
| 8 | * deal in the Software without restriction, including without limitation the |
| 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| 10 | * sell copies of the Software, and to permit persons to whom the Software is |
| 11 | * furnished to do so, subject to the following conditions: |
| 12 | * |
| 13 | * The above copyright notice and this permission notice shall be included in |
| 14 | * all copies or substantial portions of the Software. |
| 15 | * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 22 | * IN THE SOFTWARE. |
| 23 | * |
| 24 | * Extremely Lightweight HTML5 Stream Parser, same approach as lecp but for |
| 25 | * html5. |
| 26 | */ |
| 27 | |
| 28 | #if !defined(LHP_MAX_ELEMS_NEST) |
| 29 | #define LHP_MAX_ELEMS_NEST 32 |
| 30 | #endif |
| 31 | #if !defined(LHP_MAX_DEPTH) |
| 32 | #define LHP_MAX_DEPTH 12 |
| 33 | #endif |
| 34 | #if !defined(LHP_STRING_CHUNK) |
| 35 | #define LHP_STRING_CHUNK 254 |
| 36 | #endif |
| 37 | |
| 38 | enum lhp_callbacks { |
| 39 | |
| 40 | LHPCB_ERR_ATTRIB_SYNTAX = -5, |
| 41 | LHPCB_ERR_ATTRIB_LEN = -4, |
| 42 | LHPCB_ERR_OOM = -3, |
| 43 | LHPCB_ERR_ELEM_DEPTH = -2, |
| 44 | LHPCB_CONTINUE = -1, |
| 45 | |
| 46 | LHPCB_CONSTRUCTED = 0, |
| 47 | LHPCB_DESTRUCTED = 1, |
| 48 | |
| 49 | LHPCB_COMPLETE = 2, |
| 50 | LHPCB_FAILED = 3, |
| 51 | |
| 52 | LHPCB_ELEMENT_START = 4, /* reported at end of <> */ |
| 53 | LHPCB_ELEMENT_END = 5, |
| 54 | |
| 55 | LHPCB_CONTENT = 6, |
| 56 | |
| 57 | = 7, |
| 58 | }; |
| 59 | |
| 60 | /* |
| 61 | * CSS v2.1 full property set, taken from |
| 62 | * |
| 63 | * https://www.w3.org/TR/CSS21/propidx.html |
| 64 | */ |
| 65 | |
| 66 | typedef enum lcsp_props { |
| 67 | LCSP_PROP_AZIMUTH, |
| 68 | LCSP_PROP_BACKGROUND_ATTACHMENT, |
| 69 | LCSP_PROP_BACKGROUND_COLOR, |
| 70 | LCSP_PROP_BACKGROUND_IMAGE, |
| 71 | LCSP_PROP_BACKGROUND_POSITION, |
| 72 | LCSP_PROP_BACKGROUND_REPEAT, |
| 73 | LCSP_PROP_BACKGROUND, |
| 74 | LCSP_PROP_BORDER_COLLAPSE, |
| 75 | LCSP_PROP_BORDER_COLOR, |
| 76 | LCSP_PROP_BORDER_SPACING, |
| 77 | LCSP_PROP_BORDER_STYLE, |
| 78 | LCSP_PROP_BORDER_TOP, |
| 79 | LCSP_PROP_BORDER_RIGHT, |
| 80 | LCSP_PROP_BORDER_BOTTOM, |
| 81 | LCSP_PROP_BORDER_LEFT, |
| 82 | LCSP_PROP_BORDER_TOP_COLOR, |
| 83 | LCSP_PROP_BORDER_RIGHT_COLOR, |
| 84 | LCSP_PROP_BORDER_BOTTOM_COLOR, |
| 85 | LCSP_PROP_BORDER_LEFT_COLOR, |
| 86 | LCSP_PROP_BORDER_TOP_STYLE, |
| 87 | LCSP_PROP_BORDER_RIGHT_STYLE, |
| 88 | LCSP_PROP_BORDER_BOTTOM_STYLE, |
| 89 | LCSP_PROP_BORDER_LEFT_STYLE, |
| 90 | LCSP_PROP_BORDER_TOP_WIDTH, |
| 91 | LCSP_PROP_BORDER_RIGHT_WIDTH, |
| 92 | LCSP_PROP_BORDER_BOTTOM_WIDTH, |
| 93 | LCSP_PROP_BORDER_LEFT_WIDTH, |
| 94 | LCSP_PROP_BORDER_WIDTH, |
| 95 | LCSP_PROP_BORDER_TOP_LEFT_RADIUS, |
| 96 | LCSP_PROP_BORDER_TOP_RIGHT_RADIUS, |
| 97 | LCSP_PROP_BORDER_BOTTOM_LEFT_RADIUS, |
| 98 | LCSP_PROP_BORDER_BOTTOM_RIGHT_RADIUS, |
| 99 | LCSP_PROP_BORDER_RADIUS, |
| 100 | LCSP_PROP_BORDER, |
| 101 | LCSP_PROP_BOTTOM, |
| 102 | LCSP_PROP_CAPTION_SIDE, |
| 103 | LCSP_PROP_CLEAR, |
| 104 | LCSP_PROP_CLIP, |
| 105 | LCSP_PROP_COLOR, |
| 106 | LCSP_PROP_CONTENT, |
| 107 | LCSP_PROP_COUNTER_INCREMENT, |
| 108 | LCSP_PROP_COUNTER_RESET, |
| 109 | LCSP_PROP_CUE_AFTER, |
| 110 | LCSP_PROP_CUE_BEFORE, |
| 111 | LCSP_PROP_CUE, |
| 112 | LCSP_PROP_CURSOR, |
| 113 | LCSP_PROP_DIRECTION, |
| 114 | LCSP_PROP_DISPLAY, |
| 115 | LCSP_PROP_ELEVATION, |
| 116 | LCSP_PROP_EMPTY_CELLS, |
| 117 | LCSP_PROP_FLOAT, |
| 118 | LCSP_PROP_FONT_FAMILY, |
| 119 | LCSP_PROP_FONT_SIZE, |
| 120 | LCSP_PROP_FONT_STYLE, |
| 121 | LCSP_PROP_FONT_VARAIANT, |
| 122 | LCSP_PROP_FONT_WEIGHT, |
| 123 | LCSP_PROP_FONT, |
| 124 | LCSP_PROP_HEIGHT, |
| 125 | LCSP_PROP_LEFT, |
| 126 | LCSP_PROP_LETTER_SPACING, |
| 127 | LCSP_PROP_LINE_HEIGHT, |
| 128 | LCSP_PROP_LIST_STYLE_IMAGE, |
| 129 | LCSP_PROP_LIST_STYLE_POSITION, |
| 130 | LCSP_PROP_LIST_STYLE_TYPE, |
| 131 | LCSP_PROP_LIST_STYLE, |
| 132 | LCSP_PROP_MARGIN_RIGHT, |
| 133 | LCSP_PROP_MARGIN_LEFT, |
| 134 | LCSP_PROP_MARGIN_TOP, |
| 135 | LCSP_PROP_MARGIN_BOTTOM, |
| 136 | LCSP_PROP_MARGIN, |
| 137 | LCSP_PROP_MAX_HEIGHT, |
| 138 | LCSP_PROP_MAX_WIDTH, |
| 139 | LCSP_PROP_MIN_HEIGHT, |
| 140 | LCSP_PROP_MIN_WIDTH, |
| 141 | LCSP_PROP_ORPHANS, |
| 142 | LCSP_PROP_OUTLINE_COLOR, |
| 143 | LCSP_PROP_OUTLINE_STYLE, |
| 144 | LCSP_PROP_OUTLINE_WIDTH, |
| 145 | LCSP_PROP_OUTLINE, |
| 146 | LCSP_PROP_OVERFLOW, |
| 147 | LCSP_PROP_PADDING_TOP, |
| 148 | LCSP_PROP_PADDING_RIGHT, |
| 149 | LCSP_PROP_PADDING_BOTTOM, |
| 150 | LCSP_PROP_PADDING_LEFT, |
| 151 | LCSP_PROP_PADDING, |
| 152 | LCSP_PROP_PAGE_BREAK_AFTER, |
| 153 | LCSP_PROP_PAGE_BREAK_BEFORE, |
| 154 | LCSP_PROP_PAGE_BREAK_INSIDE, |
| 155 | LCSP_PROP_PAUSE_AFTER, |
| 156 | LCSP_PROP_PAUSE_BEFORE, |
| 157 | LCSP_PROP_PAUSE, |
| 158 | LCSP_PROP_PITCH_RANGE, |
| 159 | LCSP_PROP_PITCH, |
| 160 | LCSP_PROP_PLAY_DURING, |
| 161 | LCSP_PROP_POSITION, |
| 162 | LCSP_PROP_QUOTES, |
| 163 | LCSP_PROP_RICHNESS, |
| 164 | LCSP_PROP_RIGHT, |
| 165 | , |
| 166 | LCSP_PROP_SPEAK_NUMERAL, |
| 167 | LCSP_PROP_SPEAK_PUNCTUATION, |
| 168 | LCSP_PROP_SPEAK, |
| 169 | LCSP_PROP_SPEECH_RATE, |
| 170 | LCSP_PROP_STRESS, |
| 171 | LCSP_PROP_TABLE_LAYOUT, |
| 172 | LCSP_PROP_TEXT_ALIGN, |
| 173 | LCSP_PROP_TEXT_DECORATION, |
| 174 | LCSP_PROP_TEXT_INDENT, |
| 175 | LCSP_PROP_TEXT_TRANSFORM, |
| 176 | LCSP_PROP_TOP, |
| 177 | LCSP_PROP_UNICODE_BIDI, |
| 178 | LCSP_PROP_VERTICAL_ALIGN, |
| 179 | LCSP_PROP_VISIBILITY, |
| 180 | LCSP_PROP_VOICE_FAMILY, |
| 181 | LCSP_PROP_VOLUME, |
| 182 | LCSP_PROP_WHITE_SPACE, |
| 183 | LCSP_PROP_WIDOWS, |
| 184 | LCSP_PROP_WIDTH, |
| 185 | LCSP_PROP_WORD_SPACING, |
| 186 | LCSP_PROP_Z_INDEX, |
| 187 | |
| 188 | LCSP_PROP__COUNT /* always last */ |
| 189 | } lcsp_props_t; |
| 190 | |
| 191 | /* |
| 192 | * Indexes for the well-known property values |
| 193 | */ |
| 194 | |
| 195 | typedef enum { |
| 196 | LCSP_PROPVAL_ABOVE, |
| 197 | LCSP_PROPVAL_ABSOLUTE, |
| 198 | LCSP_PROPVAL_ALWAYS, |
| 199 | LCSP_PROPVAL_ARMENIAN, |
| 200 | LCSP_PROPVAL_AUTO, |
| 201 | LCSP_PROPVAL_AVOID, |
| 202 | LCSP_PROPVAL_BASELINE, |
| 203 | LCSP_PROPVAL_BEHIND, |
| 204 | LCSP_PROPVAL_BELOW, |
| 205 | LCSP_PROPVAL_BIDI_OVERRIDE, |
| 206 | LCSP_PROPVAL_BLINK, |
| 207 | LCSP_PROPVAL_BLOCK, |
| 208 | LCSP_PROPVAL_BOLD, |
| 209 | LCSP_PROPVAL_BOLDER, |
| 210 | LCSP_PROPVAL_BOTH, |
| 211 | LCSP_PROPVAL_BOTTOM, |
| 212 | LCSP_PROPVAL_CAPITALIZE, |
| 213 | LCSP_PROPVAL_CAPTION, |
| 214 | LCSP_PROPVAL_CENTER, |
| 215 | LCSP_PROPVAL_CIRCLE, |
| 216 | LCSP_PROPVAL_CLOSE_QUOTE, |
| 217 | LCSP_PROPVAL_CODE, |
| 218 | LCSP_PROPVAL_COLLAPSE, |
| 219 | LCSP_PROPVAL_CONTINUOUS, |
| 220 | LCSP_PROPVAL_CROSSHAIR, |
| 221 | LCSP_PROPVAL_DECIMAL_LEADING_ZERO, |
| 222 | LCSP_PROPVAL_DECIMAL, |
| 223 | LCSP_PROPVAL_DIGITS, |
| 224 | LCSP_PROPVAL_DISC, |
| 225 | LCSP_PROPVAL_EMBED, |
| 226 | LCSP_PROPVAL_E_RESIZE, |
| 227 | LCSP_PROPVAL_FIXED, |
| 228 | LCSP_PROPVAL_GEORGIAN, |
| 229 | LCSP_PROPVAL_HELP, |
| 230 | LCSP_PROPVAL_HIDDEN, |
| 231 | LCSP_PROPVAL_HIDE, |
| 232 | LCSP_PROPVAL_HIGH, |
| 233 | LCSP_PROPVAL_HIGHER, |
| 234 | LCSP_PROPVAL_ICON, |
| 235 | LCSP_PROPVAL_INHERIT, |
| 236 | LCSP_PROPVAL_INLINE, |
| 237 | LCSP_PROPVAL_INLINE_BLOCK, |
| 238 | LCSP_PROPVAL_INLINE_TABLE, |
| 239 | LCSP_PROPVAL_INVERT, |
| 240 | LCSP_PROPVAL_ITALIC, |
| 241 | LCSP_PROPVAL_JUSTIFY, |
| 242 | LCSP_PROPVAL_LEFT, |
| 243 | LCSP_PROPVAL_LIGHTER, |
| 244 | LCSP_PROPVAL_LINE_THROUGH, |
| 245 | LCSP_PROPVAL_LIST_ITEM, |
| 246 | LCSP_PROPVAL_LOW, |
| 247 | LCSP_PROPVAL_LOWER, |
| 248 | LCSP_PROPVAL_LOWER_ALPHA, |
| 249 | LCSP_PROPVAL_LOWERCASE, |
| 250 | LCSP_PROPVAL_LOWER_GREEK, |
| 251 | LCSP_PROPVAL_LOWER_LATIN, |
| 252 | LCSP_PROPVAL_LOWER_ROMAN, |
| 253 | LCSP_PROPVAL_LTR, |
| 254 | , |
| 255 | LCSP_PROPVAL_MESSAGE_BOX, |
| 256 | LCSP_PROPVAL_MIDDLE, |
| 257 | LCSP_PROPVAL_MIX, |
| 258 | LCSP_PROPVAL_MOVE, |
| 259 | LCSP_PROPVAL_NE_RESIZE, |
| 260 | LCSP_PROPVAL_NO_CLOSE_QUOTE, |
| 261 | LCSP_PROPVAL_NONE, |
| 262 | LCSP_PROPVAL_NO_OPEN_QUOTE, |
| 263 | LCSP_PROPVAL_NO_REPEAT, |
| 264 | LCSP_PROPVAL_NORMAL, |
| 265 | LCSP_PROPVAL_NOWRAP, |
| 266 | LCSP_PROPVAL_N_RESIZE, |
| 267 | LCSP_PROPVAL_NW_RESIZE, |
| 268 | LCSP_PROPVAL_OBLIQUE, |
| 269 | LCSP_PROPVAL_ONCE, |
| 270 | LCSP_PROPVAL_OPEN_QUOTE, |
| 271 | LCSP_PROPVAL_OUTSIDE, |
| 272 | LCSP_PROPVAL_OVERLINE, |
| 273 | LCSP_PROPVAL_POINTER, |
| 274 | LCSP_PROPVAL_PRE, |
| 275 | LCSP_PROPVAL_PRE_LINE, |
| 276 | LCSP_PROPVAL_PRE_WRAP, |
| 277 | LCSP_PROPVAL_PROGRESS, |
| 278 | LCSP_PROPVAL_RELATIVE, |
| 279 | LCSP_PROPVAL_REPEAT, |
| 280 | LCSP_PROPVAL_REPEAT_X, |
| 281 | LCSP_PROPVAL_REPEAT_Y, |
| 282 | LCSP_PROPVAL_RIGHT, |
| 283 | LCSP_PROPVAL_RTL, |
| 284 | LCSP_PROPVAL_SCROLL, |
| 285 | LCSP_PROPVAL_SEPARATE, |
| 286 | LCSP_PROPVAL_SE_RESIZE, |
| 287 | LCSP_PROPVAL_SHOW, |
| 288 | LCSP_PROPVAL_SILENT, |
| 289 | LCSP_PROPVAL_SMALL_CAPS, |
| 290 | LCSP_PROPVAL_SMALL_CAPTION, |
| 291 | LCSP_PROPVAL_SPELL_OUT, |
| 292 | LCSP_PROPVAL_SQUARE, |
| 293 | LCSP_PROPVAL_S_RESIZE, |
| 294 | LCSP_PROPVAL_STATIC, |
| 295 | LCSP_PROPVAL_STATUS_BAR, |
| 296 | LCSP_PROPVAL_SUB, |
| 297 | LCSP_PROPVAL_SUPER, |
| 298 | LCSP_PROPVAL_SW_RESIZE, |
| 299 | LCSP_PROPVAL_TABLE, |
| 300 | LCSP_PROPVAL_TABLE_CAPTION, |
| 301 | LCSP_PROPVAL_TABLE_CELL, |
| 302 | LCSP_PROPVAL_TABLE_COLUMN, |
| 303 | LCSP_PROPVAL_TABLE_COLUMN_GROUP, |
| 304 | , |
| 305 | , |
| 306 | LCSP_PROPVAL_TABLE_ROW, |
| 307 | LCSP_PROPVAL_TABLE_ROW_GROUP, |
| 308 | LCSP_PROPVAL_TEXT_BOTTOM, |
| 309 | LCSP_PROPVAL_TEXT_TOP, |
| 310 | LCSP_PROPVAL_TEXT, |
| 311 | LCSP_PROPVAL_TOP, |
| 312 | LCSP_PROPVAL_TRANSPARENT, |
| 313 | LCSP_PROPVAL_UNDERLINE, |
| 314 | LCSP_PROPVAL_UPPER_ALPHA, |
| 315 | LCSP_PROPVAL_UPPERCASE, |
| 316 | LCSP_PROPVAL_UPPER_LATIN, |
| 317 | LCSP_PROPVAL_UPPER_ROMAN, |
| 318 | LCSP_PROPVAL_VISIBLE, |
| 319 | LCSP_PROPVAL_WAIT, |
| 320 | LCSP_PROPVAL_W_RESIZE, |
| 321 | |
| 322 | LCSP_PROPVAL__COUNT /* always last */ |
| 323 | } lcsp_propvals_t; |
| 324 | |
| 325 | struct lhp_ctx; |
| 326 | typedef lws_stateful_ret_t (*lhp_callback)(struct lhp_ctx *ctx, char reason); |
| 327 | |
| 328 | /* html attribute */ |
| 329 | |
| 330 | typedef struct lhp_atr { |
| 331 | lws_dll2_t list; |
| 332 | size_t name_len; /* 0 if it is elem tag */ |
| 333 | size_t value_len; |
| 334 | |
| 335 | /* name+NUL then value+NUL follow */ |
| 336 | } lhp_atr_t; |
| 337 | |
| 338 | /* |
| 339 | * In order to lay out the table, we have to incrementally adjust all foregoing |
| 340 | * DLOs as newer cells change the situation. So we have to keep track of all |
| 341 | * cell DLOs in a stack of tables until it's all done. |
| 342 | */ |
| 343 | |
| 344 | typedef struct { |
| 345 | lws_dll2_t list; /* ps->table_cols */ |
| 346 | |
| 347 | lws_dll2_owner_t row_dlos; /* lws_dlo_t in column */ |
| 348 | |
| 349 | lws_fx_t height; /* currently computed row height */ |
| 350 | } lhp_table_row_t; |
| 351 | |
| 352 | typedef struct { |
| 353 | lws_dll2_t list; /* ps->table_cols */ |
| 354 | |
| 355 | lws_dll2_owner_t col_dlos; /* lws_dlo_t in column */ |
| 356 | |
| 357 | lws_fx_t width; /* currently computed column width */ |
| 358 | } lhp_table_col_t; |
| 359 | |
| 360 | struct lcsp_atr; |
| 361 | |
| 362 | #define CCPAS_TOP 0 |
| 363 | #define CCPAS_RIGHT 1 |
| 364 | #define CCPAS_BOTTOM 2 |
| 365 | #define CCPAS_LEFT 3 |
| 366 | |
| 367 | typedef struct lhp_pstack { |
| 368 | lws_dll2_t list; |
| 369 | void *user; /* private to the stack level */ |
| 370 | lhp_callback cb; |
| 371 | |
| 372 | /* static: x,y: offset from parent, w,h: surface size of this object */ |
| 373 | lws_box_t drt; |
| 374 | |
| 375 | /* dynamic cursor inside drt for progressive child placement */ |
| 376 | lws_fx_t curx; |
| 377 | lws_fx_t cury; |
| 378 | lws_fx_t widest; |
| 379 | lws_fx_t deepest; |
| 380 | |
| 381 | lws_dlo_t *dlo_set_curx; |
| 382 | lws_dlo_t *dlo_set_cury; |
| 383 | |
| 384 | lws_dll2_owner_t atr; /* lhp_atr_t */ |
| 385 | |
| 386 | const lws_display_font_t *f; |
| 387 | |
| 388 | const struct lcsp_atr *css_background_color; |
| 389 | const struct lcsp_atr *css_color; |
| 390 | |
| 391 | const struct lcsp_atr *css_position; |
| 392 | const struct lcsp_atr *css_display; |
| 393 | const struct lcsp_atr *css_width; |
| 394 | const struct lcsp_atr *css_height; |
| 395 | |
| 396 | const struct lcsp_atr *css_border_radius[4]; |
| 397 | |
| 398 | const struct lcsp_atr *css_pos[4]; |
| 399 | const struct lcsp_atr *css_margin[4]; |
| 400 | const struct lcsp_atr *css_padding[4]; |
| 401 | |
| 402 | uint16_t tr_idx; /* in table */ |
| 403 | uint16_t td_idx; /* in current tr */ |
| 404 | |
| 405 | uint8_t is_block:1; /* children use space in our drt */ |
| 406 | uint8_t is_table:1; |
| 407 | |
| 408 | /* user layout owns these after initial values set */ |
| 409 | |
| 410 | lws_dlo_t *dlo; |
| 411 | const lws_display_font_t *font; |
| 412 | int oi[4]; |
| 413 | int positioned[4]; |
| 414 | int rel_layout_cursor[4]; |
| 415 | uint8_t runon; /* continues same line */ |
| 416 | |
| 417 | } lhp_pstack_t; |
| 418 | |
| 419 | typedef enum lcsp_css_units { |
| 420 | LCSP_UNIT_NONE, |
| 421 | |
| 422 | LCSP_UNIT_NUM, /* u.i */ |
| 423 | |
| 424 | LCSP_UNIT_LENGTH_EM, /* u.i */ |
| 425 | LCSP_UNIT_LENGTH_EX, /* u.i */ |
| 426 | LCSP_UNIT_LENGTH_IN, /* u.i */ |
| 427 | LCSP_UNIT_LENGTH_CM, /* u.i */ |
| 428 | LCSP_UNIT_LENGTH_MM, /* u.i */ |
| 429 | LCSP_UNIT_LENGTH_PT, /* u.i */ |
| 430 | LCSP_UNIT_LENGTH_PC, /* u.i */ |
| 431 | LCSP_UNIT_LENGTH_PX, /* u.i */ |
| 432 | LCSP_UNIT_LENGTH_PERCENT, /* u.i */ |
| 433 | |
| 434 | LCSP_UNIT_ANGLE_ABS_DEG, /* u.i */ |
| 435 | LCSP_UNIT_ANGLE_REL_DEG, /* u.i */ |
| 436 | |
| 437 | LCSP_UNIT_FREQ_HZ, /* u.i */ |
| 438 | |
| 439 | LCSP_UNIT_RGBA, /* u.rgba */ |
| 440 | |
| 441 | LCSP_UNIT_URL, /* string at end of atr */ |
| 442 | LCSP_UNIT_STRING, /* string at end of atr */ |
| 443 | LCSP_UNIT_DATA, /* binary data at end of atr */ |
| 444 | |
| 445 | } lcsp_css_units_t; |
| 446 | |
| 447 | typedef struct lcsp_atr { |
| 448 | lws_dll2_t list; |
| 449 | |
| 450 | int propval; /* lcsp_propvals_t LCSP_PROPVAL_ */ |
| 451 | |
| 452 | size_t value_len; /* for string . url */ |
| 453 | lcsp_css_units_t unit; |
| 454 | |
| 455 | union { |
| 456 | lws_fx_t i; |
| 457 | uint32_t rgba; /* for colours */ |
| 458 | } u; |
| 459 | |
| 460 | lws_fx_t r; |
| 461 | |
| 462 | uint8_t op; |
| 463 | |
| 464 | /* .value_len bytes follow (for strings and blobs) */ |
| 465 | } lcsp_atr_t; |
| 466 | |
| 467 | /* css definitions like font-weight: */ |
| 468 | typedef struct lcsp_defs { |
| 469 | lws_dll2_t list; |
| 470 | lws_dll2_owner_t atrs; /* lcsp_atr_t */ |
| 471 | lcsp_props_t prop; /* lcsp_props_t, LCSP_PROP_* */ |
| 472 | } lcsp_defs_t; |
| 473 | |
| 474 | typedef struct lcsp_names { |
| 475 | lws_dll2_t list; |
| 476 | size_t name_len; |
| 477 | |
| 478 | /* name + NUL follow */ |
| 479 | } lcsp_names_t; |
| 480 | |
| 481 | typedef struct lcsp_stanza { /* css stanza, with names and defs */ |
| 482 | lws_dll2_t list; |
| 483 | |
| 484 | lws_dll2_owner_t names; /* lcsp_names_t */ |
| 485 | lws_dll2_owner_t defs; /* lcsp_defs_t */ |
| 486 | |
| 487 | } lcsp_stanza_t; |
| 488 | |
| 489 | /* |
| 490 | * A list of stanza references can easily have to bring in the same stanza |
| 491 | * multiple times, eg, <div><span class=x><div> won't work unless the div |
| 492 | * stanzas are listed twice at different places in the list. It means we can't |
| 493 | * use dll2 directly since the number of references is open-ended. |
| 494 | * |
| 495 | * lcsp_stanza_ptr provides indirection that allows multiple listings. |
| 496 | */ |
| 497 | |
| 498 | typedef struct lcsp_stanza_ptr { |
| 499 | lws_dll2_t list; |
| 500 | |
| 501 | lcsp_stanza_t *stz; |
| 502 | } lcsp_stanza_ptr_t; |
| 503 | |
| 504 | typedef struct lcsp_atr_ptr { |
| 505 | lws_dll2_t list; |
| 506 | |
| 507 | lcsp_atr_t *atr; |
| 508 | } lcsp_atr_ptr_t; |
| 509 | |
| 510 | #define LHP_FLAG_DOCUMENT_END (1 << 0) |
| 511 | |
| 512 | typedef struct lhp_ctx { |
| 513 | lws_dll2_owner_t stack; /* lhp_pstack_t */ |
| 514 | |
| 515 | struct lwsac *cssac; /* css allocations all in an ac */ |
| 516 | struct lwsac *cascadeac; /* active_stanzas ac */ |
| 517 | struct lwsac *propatrac; /* prop atr query results ac */ |
| 518 | lws_dll2_owner_t css; /* lcsp_stanza_t (all in ac) */ |
| 519 | |
| 520 | lws_dll2_owner_t *ids; |
| 521 | |
| 522 | lws_fx_t tf; |
| 523 | lcsp_css_units_t unit; |
| 524 | lcsp_stanza_t *stz; /* current stanza getting properties */ |
| 525 | lcsp_defs_t *def; /* current property getting values */ |
| 526 | |
| 527 | lws_dll2_owner_t active_stanzas; /* lcsp_stanza_ptr_t allocated |
| 528 | * in cascadeac */ |
| 529 | lws_dll2_owner_t active_atr; /* lcsp_atr_ptr_t allocated in |
| 530 | * propatrac */ |
| 531 | |
| 532 | lws_surface_info_t ic; |
| 533 | |
| 534 | const char *base_url; /* strdup of https://x.com/y.html */ |
| 535 | sul_cb_t ssevcb; /* callback for ss events */ |
| 536 | lws_sorted_usec_list_t *ssevsul; /* sul to use to resume rz */ |
| 537 | sul_cb_t sshtmlevcb; /* callback for more html parse */ |
| 538 | lws_sorted_usec_list_t *sshtmlevsul; /* sul for more html parse */ |
| 539 | |
| 540 | void *user; |
| 541 | void *user1; |
| 542 | const char *tag; /* private */ |
| 543 | size_t tag_len; /* private */ |
| 544 | |
| 545 | int npos; |
| 546 | int state; /* private */ |
| 547 | int state_css_comm; /* private */ |
| 548 | int nl_temp; |
| 549 | int temp_count; |
| 550 | |
| 551 | uint32_t flags; |
| 552 | uint32_t temp; |
| 553 | int32_t window; /* 0, or ss item flow control limit */ |
| 554 | |
| 555 | union { |
| 556 | uint32_t s; |
| 557 | struct { |
| 558 | uint32_t first:1; |
| 559 | uint32_t closing:1; |
| 560 | uint32_t void_element:1; |
| 561 | uint32_t doctype:1; |
| 562 | uint32_t inq:1; |
| 563 | uint32_t tag_used:1; |
| 564 | uint32_t arg:1; |
| 565 | uint32_t default_css:1; |
| 566 | #define LHP_CSS_PROPVAL_INT_WHOLE 1 |
| 567 | #define LHP_CSS_PROPVAL_INT_FRAC 2 |
| 568 | #define LHP_CSS_PROPVAL_INT_UNIT 3 |
| 569 | uint32_t integer:2; |
| 570 | uint32_t color:2; |
| 571 | } f; |
| 572 | } u; |
| 573 | |
| 574 | int prop; /* lcsp_props_t */ |
| 575 | int propval; /* lcsp_propvals_t */ |
| 576 | int16_t css_state; /* private */ |
| 577 | int16_t cssval_state; /* private */ |
| 578 | |
| 579 | uint8_t in_body:1; |
| 580 | uint8_t finish_css:1; |
| 581 | uint8_t is_css:1; |
| 582 | uint8_t await_css_done:1; |
| 583 | |
| 584 | /* at end so we can memset members above it in one go */ |
| 585 | |
| 586 | char buf[LHP_STRING_CHUNK + 1]; |
| 587 | |
| 588 | } lhp_ctx_t; |
| 589 | |
| 590 | /* |
| 591 | * lws_lhp_construct() - Construct an lhp context |
| 592 | * |
| 593 | * \param ctx: the lhp context to prepare |
| 594 | * \param cb: the stream parsing callback |
| 595 | * \param user: opaque user pointer available from the lhp context |
| 596 | * \param ic: struct with arguments for lhp context |
| 597 | * |
| 598 | * The lhp context is allocated by the caller (the size is known). |
| 599 | * Prepares an lhp context to parse html. Returns 0 for OK, or nonzero if OOM. |
| 600 | */ |
| 601 | LWS_VISIBLE LWS_EXTERN int |
| 602 | lws_lhp_construct(lhp_ctx_t *ctx, lhp_callback cb, void *user, |
| 603 | const lws_surface_info_t *ic); |
| 604 | |
| 605 | /* |
| 606 | * lws_lhp_destruct() - Destroy an lhp context |
| 607 | * |
| 608 | * \param ctx: the lhp context to prepare |
| 609 | * |
| 610 | * Destroys an lhp context. The lhp context is allocated by the caller (the |
| 611 | * size is known). But there are suballocations that must be destroyed with |
| 612 | * this. |
| 613 | */ |
| 614 | LWS_VISIBLE LWS_EXTERN void |
| 615 | lws_lhp_destruct(lhp_ctx_t *ctx); |
| 616 | |
| 617 | /** |
| 618 | * lws_lhp_ss_browse() - browse url using SS and parse via lhp to DLOs |
| 619 | * |
| 620 | * \param cx: the lws_context |
| 621 | * \param rs: the user's render state object |
| 622 | * \param url: the https://x.com/y.xyz URL to browse |
| 623 | * \param render: the user's linewise render callback (called from \p rs.sul) |
| 624 | * |
| 625 | * High level network fetch via SS and render html via lhp / DLO |
| 626 | * |
| 627 | * rs->ic must be prepared before calling. |
| 628 | * |
| 629 | * Returns nonzero if an early, fatal problem, else returns 0 and continues |
| 630 | * asynchronously. |
| 631 | * |
| 632 | * If rs->box is (0,0,0,0) on entry, it is set to represent the whole display |
| 633 | * surface. Otherwise if not representing the whole display surface, it |
| 634 | * indicates partial mode should be used. |
| 635 | */ |
| 636 | LWS_VISIBLE LWS_EXTERN int |
| 637 | lws_lhp_ss_browse(struct lws_context *cx, lws_display_render_state_t *rs, |
| 638 | const char *url, sul_cb_t render); |
| 639 | |
| 640 | /** |
| 641 | * lws_lhp_parse() - parses a chunk of input HTML |
| 642 | * |
| 643 | * \p ctx: the parsing context |
| 644 | * \p buf: pointer to the start of the chunk of html |
| 645 | * \p len: pointer the number of bytes of html available at *\pbuf |
| 646 | * |
| 647 | * Parses up to *len bytes at *buf. On exit, *buf and *len are adjusted |
| 648 | * according to how much data was used. May return before processing all the |
| 649 | * input. |
| 650 | * |
| 651 | * Returns LWS_SRET_WANT_INPUT if the parsing is stalled on some other async |
| 652 | * event (eg, fetch of image to find out the dimensions). |
| 653 | * |
| 654 | * The lws_lhp_ss_browse() api wraps this. |
| 655 | */ |
| 656 | LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t |
| 657 | lws_lhp_parse(lhp_ctx_t *ctx, const uint8_t **buf, size_t *len); |
| 658 | |
| 659 | /** |
| 660 | * lws_css_cascade_get_prop_atr() - create active css atr list for property |
| 661 | * |
| 662 | * \p ctx: the parsing context |
| 663 | * \p prop: the LCSP_PROP_ property to generate the attribute list for |
| 664 | * |
| 665 | * Returns NULL if no atr or OOM. |
| 666 | * |
| 667 | * Otherwise produces a list of active CSS property attributes walkable via |
| 668 | * ctx->active_atr, and returns the tail one. For simple attributes where the |
| 669 | * last definition is the active one, this points to the last definition. |
| 670 | */ |
| 671 | LWS_VISIBLE LWS_EXTERN const lcsp_atr_t * |
| 672 | lws_css_cascade_get_prop_atr(lhp_ctx_t *ctx, lcsp_props_t prop); |
| 673 | |
| 674 | /** |
| 675 | * lws_http_rel_to_url() - make absolute url from base and relative |
| 676 | * |
| 677 | * \param dest: place to store the result |
| 678 | * \param len: max length of result including NUL |
| 679 | * \param base: a reference url including a file part |
| 680 | * \param rel: the absolute or relative url or path to apply to base |
| 681 | * |
| 682 | * Copy the url formof rel into dest, using base to fill in missing context |
| 683 | * |
| 684 | * If base is https://x.com/y/z.html |
| 685 | * |
| 686 | * a.html -> https://x.com/y/a/html |
| 687 | * ../b.html -> https://x.com/b.html |
| 688 | * /c.html -> https://x.com/c.html |
| 689 | * https://y.com/a.html -> https://y.com/a.html |
| 690 | */ |
| 691 | LWS_VISIBLE LWS_EXTERN int |
| 692 | lws_http_rel_to_url(char *dest, size_t len, const char *base, const char *rel); |
| 693 | |
| 694 | LWS_VISIBLE LWS_EXTERN lhp_pstack_t * |
| 695 | lws_css_get_parent_block(lhp_ctx_t *ctx, lhp_pstack_t *ps); |
| 696 | |
| 697 | LWS_VISIBLE LWS_EXTERN const char * |
| 698 | lws_css_pstack_name(lhp_pstack_t *ps); |
| 699 | |
| 700 | LWS_VISIBLE LWS_EXTERN const char * |
| 701 | lws_html_get_atr(lhp_pstack_t *ps, const char *aname, size_t aname_len); |
| 702 | |
| 703 | LWS_VISIBLE LWS_EXTERN const lws_fx_t * |
| 704 | lws_csp_px(const lcsp_atr_t *a, lhp_pstack_t *ps); |
| 705 | |
| 706 | LWS_VISIBLE LWS_EXTERN void |
| 707 | lws_lhp_tag_dlo_id(lhp_ctx_t *ctx, lhp_pstack_t *ps, lws_dlo_t *dlo); |
| 708 | |
| 709 | void |
| 710 | lhp_set_dlo_padding_margin(lhp_pstack_t *ps, lws_dlo_t *dlo); |
| 711 | |
| 712 | #define LWS_LHPREF_WIDTH 0 |
| 713 | #define LWS_LHPREF_HEIGHT 1 |
| 714 | #define LWS_LHPREF_NONE 2 |
| 715 | |
| 716 | LWS_VISIBLE LWS_EXTERN int |
| 717 | lhp_prop_axis(const lcsp_atr_t *a); |
| 718 | |