718 lines
18 KiB
C
Raw Normal View History

2025-01-22 17:22:38 +01:00
/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2022 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Extremely Lightweight HTML5 Stream Parser, same approach as lecp but for
* html5.
*/
#if !defined(LHP_MAX_ELEMS_NEST)
#define LHP_MAX_ELEMS_NEST 32
#endif
#if !defined(LHP_MAX_DEPTH)
#define LHP_MAX_DEPTH 12
#endif
#if !defined(LHP_STRING_CHUNK)
#define LHP_STRING_CHUNK 254
#endif
enum lhp_callbacks {
LHPCB_ERR_ATTRIB_SYNTAX = -5,
LHPCB_ERR_ATTRIB_LEN = -4,
LHPCB_ERR_OOM = -3,
LHPCB_ERR_ELEM_DEPTH = -2,
LHPCB_CONTINUE = -1,
LHPCB_CONSTRUCTED = 0,
LHPCB_DESTRUCTED = 1,
LHPCB_COMPLETE = 2,
LHPCB_FAILED = 3,
LHPCB_ELEMENT_START = 4, /* reported at end of <> */
LHPCB_ELEMENT_END = 5,
LHPCB_CONTENT = 6,
LHPCB_COMMENT = 7,
};
/*
* CSS v2.1 full property set, taken from
*
* https://www.w3.org/TR/CSS21/propidx.html
*/
typedef enum lcsp_props {
LCSP_PROP_AZIMUTH,
LCSP_PROP_BACKGROUND_ATTACHMENT,
LCSP_PROP_BACKGROUND_COLOR,
LCSP_PROP_BACKGROUND_IMAGE,
LCSP_PROP_BACKGROUND_POSITION,
LCSP_PROP_BACKGROUND_REPEAT,
LCSP_PROP_BACKGROUND,
LCSP_PROP_BORDER_COLLAPSE,
LCSP_PROP_BORDER_COLOR,
LCSP_PROP_BORDER_SPACING,
LCSP_PROP_BORDER_STYLE,
LCSP_PROP_BORDER_TOP,
LCSP_PROP_BORDER_RIGHT,
LCSP_PROP_BORDER_BOTTOM,
LCSP_PROP_BORDER_LEFT,
LCSP_PROP_BORDER_TOP_COLOR,
LCSP_PROP_BORDER_RIGHT_COLOR,
LCSP_PROP_BORDER_BOTTOM_COLOR,
LCSP_PROP_BORDER_LEFT_COLOR,
LCSP_PROP_BORDER_TOP_STYLE,
LCSP_PROP_BORDER_RIGHT_STYLE,
LCSP_PROP_BORDER_BOTTOM_STYLE,
LCSP_PROP_BORDER_LEFT_STYLE,
LCSP_PROP_BORDER_TOP_WIDTH,
LCSP_PROP_BORDER_RIGHT_WIDTH,
LCSP_PROP_BORDER_BOTTOM_WIDTH,
LCSP_PROP_BORDER_LEFT_WIDTH,
LCSP_PROP_BORDER_WIDTH,
LCSP_PROP_BORDER_TOP_LEFT_RADIUS,
LCSP_PROP_BORDER_TOP_RIGHT_RADIUS,
LCSP_PROP_BORDER_BOTTOM_LEFT_RADIUS,
LCSP_PROP_BORDER_BOTTOM_RIGHT_RADIUS,
LCSP_PROP_BORDER_RADIUS,
LCSP_PROP_BORDER,
LCSP_PROP_BOTTOM,
LCSP_PROP_CAPTION_SIDE,
LCSP_PROP_CLEAR,
LCSP_PROP_CLIP,
LCSP_PROP_COLOR,
LCSP_PROP_CONTENT,
LCSP_PROP_COUNTER_INCREMENT,
LCSP_PROP_COUNTER_RESET,
LCSP_PROP_CUE_AFTER,
LCSP_PROP_CUE_BEFORE,
LCSP_PROP_CUE,
LCSP_PROP_CURSOR,
LCSP_PROP_DIRECTION,
LCSP_PROP_DISPLAY,
LCSP_PROP_ELEVATION,
LCSP_PROP_EMPTY_CELLS,
LCSP_PROP_FLOAT,
LCSP_PROP_FONT_FAMILY,
LCSP_PROP_FONT_SIZE,
LCSP_PROP_FONT_STYLE,
LCSP_PROP_FONT_VARAIANT,
LCSP_PROP_FONT_WEIGHT,
LCSP_PROP_FONT,
LCSP_PROP_HEIGHT,
LCSP_PROP_LEFT,
LCSP_PROP_LETTER_SPACING,
LCSP_PROP_LINE_HEIGHT,
LCSP_PROP_LIST_STYLE_IMAGE,
LCSP_PROP_LIST_STYLE_POSITION,
LCSP_PROP_LIST_STYLE_TYPE,
LCSP_PROP_LIST_STYLE,
LCSP_PROP_MARGIN_RIGHT,
LCSP_PROP_MARGIN_LEFT,
LCSP_PROP_MARGIN_TOP,
LCSP_PROP_MARGIN_BOTTOM,
LCSP_PROP_MARGIN,
LCSP_PROP_MAX_HEIGHT,
LCSP_PROP_MAX_WIDTH,
LCSP_PROP_MIN_HEIGHT,
LCSP_PROP_MIN_WIDTH,
LCSP_PROP_ORPHANS,
LCSP_PROP_OUTLINE_COLOR,
LCSP_PROP_OUTLINE_STYLE,
LCSP_PROP_OUTLINE_WIDTH,
LCSP_PROP_OUTLINE,
LCSP_PROP_OVERFLOW,
LCSP_PROP_PADDING_TOP,
LCSP_PROP_PADDING_RIGHT,
LCSP_PROP_PADDING_BOTTOM,
LCSP_PROP_PADDING_LEFT,
LCSP_PROP_PADDING,
LCSP_PROP_PAGE_BREAK_AFTER,
LCSP_PROP_PAGE_BREAK_BEFORE,
LCSP_PROP_PAGE_BREAK_INSIDE,
LCSP_PROP_PAUSE_AFTER,
LCSP_PROP_PAUSE_BEFORE,
LCSP_PROP_PAUSE,
LCSP_PROP_PITCH_RANGE,
LCSP_PROP_PITCH,
LCSP_PROP_PLAY_DURING,
LCSP_PROP_POSITION,
LCSP_PROP_QUOTES,
LCSP_PROP_RICHNESS,
LCSP_PROP_RIGHT,
LCSP_PROP_SPEAK_HEADER,
LCSP_PROP_SPEAK_NUMERAL,
LCSP_PROP_SPEAK_PUNCTUATION,
LCSP_PROP_SPEAK,
LCSP_PROP_SPEECH_RATE,
LCSP_PROP_STRESS,
LCSP_PROP_TABLE_LAYOUT,
LCSP_PROP_TEXT_ALIGN,
LCSP_PROP_TEXT_DECORATION,
LCSP_PROP_TEXT_INDENT,
LCSP_PROP_TEXT_TRANSFORM,
LCSP_PROP_TOP,
LCSP_PROP_UNICODE_BIDI,
LCSP_PROP_VERTICAL_ALIGN,
LCSP_PROP_VISIBILITY,
LCSP_PROP_VOICE_FAMILY,
LCSP_PROP_VOLUME,
LCSP_PROP_WHITE_SPACE,
LCSP_PROP_WIDOWS,
LCSP_PROP_WIDTH,
LCSP_PROP_WORD_SPACING,
LCSP_PROP_Z_INDEX,
LCSP_PROP__COUNT /* always last */
} lcsp_props_t;
/*
* Indexes for the well-known property values
*/
typedef enum {
LCSP_PROPVAL_ABOVE,
LCSP_PROPVAL_ABSOLUTE,
LCSP_PROPVAL_ALWAYS,
LCSP_PROPVAL_ARMENIAN,
LCSP_PROPVAL_AUTO,
LCSP_PROPVAL_AVOID,
LCSP_PROPVAL_BASELINE,
LCSP_PROPVAL_BEHIND,
LCSP_PROPVAL_BELOW,
LCSP_PROPVAL_BIDI_OVERRIDE,
LCSP_PROPVAL_BLINK,
LCSP_PROPVAL_BLOCK,
LCSP_PROPVAL_BOLD,
LCSP_PROPVAL_BOLDER,
LCSP_PROPVAL_BOTH,
LCSP_PROPVAL_BOTTOM,
LCSP_PROPVAL_CAPITALIZE,
LCSP_PROPVAL_CAPTION,
LCSP_PROPVAL_CENTER,
LCSP_PROPVAL_CIRCLE,
LCSP_PROPVAL_CLOSE_QUOTE,
LCSP_PROPVAL_CODE,
LCSP_PROPVAL_COLLAPSE,
LCSP_PROPVAL_CONTINUOUS,
LCSP_PROPVAL_CROSSHAIR,
LCSP_PROPVAL_DECIMAL_LEADING_ZERO,
LCSP_PROPVAL_DECIMAL,
LCSP_PROPVAL_DIGITS,
LCSP_PROPVAL_DISC,
LCSP_PROPVAL_EMBED,
LCSP_PROPVAL_E_RESIZE,
LCSP_PROPVAL_FIXED,
LCSP_PROPVAL_GEORGIAN,
LCSP_PROPVAL_HELP,
LCSP_PROPVAL_HIDDEN,
LCSP_PROPVAL_HIDE,
LCSP_PROPVAL_HIGH,
LCSP_PROPVAL_HIGHER,
LCSP_PROPVAL_ICON,
LCSP_PROPVAL_INHERIT,
LCSP_PROPVAL_INLINE,
LCSP_PROPVAL_INLINE_BLOCK,
LCSP_PROPVAL_INLINE_TABLE,
LCSP_PROPVAL_INVERT,
LCSP_PROPVAL_ITALIC,
LCSP_PROPVAL_JUSTIFY,
LCSP_PROPVAL_LEFT,
LCSP_PROPVAL_LIGHTER,
LCSP_PROPVAL_LINE_THROUGH,
LCSP_PROPVAL_LIST_ITEM,
LCSP_PROPVAL_LOW,
LCSP_PROPVAL_LOWER,
LCSP_PROPVAL_LOWER_ALPHA,
LCSP_PROPVAL_LOWERCASE,
LCSP_PROPVAL_LOWER_GREEK,
LCSP_PROPVAL_LOWER_LATIN,
LCSP_PROPVAL_LOWER_ROMAN,
LCSP_PROPVAL_LTR,
LCSP_PROPVAL_MENU,
LCSP_PROPVAL_MESSAGE_BOX,
LCSP_PROPVAL_MIDDLE,
LCSP_PROPVAL_MIX,
LCSP_PROPVAL_MOVE,
LCSP_PROPVAL_NE_RESIZE,
LCSP_PROPVAL_NO_CLOSE_QUOTE,
LCSP_PROPVAL_NONE,
LCSP_PROPVAL_NO_OPEN_QUOTE,
LCSP_PROPVAL_NO_REPEAT,
LCSP_PROPVAL_NORMAL,
LCSP_PROPVAL_NOWRAP,
LCSP_PROPVAL_N_RESIZE,
LCSP_PROPVAL_NW_RESIZE,
LCSP_PROPVAL_OBLIQUE,
LCSP_PROPVAL_ONCE,
LCSP_PROPVAL_OPEN_QUOTE,
LCSP_PROPVAL_OUTSIDE,
LCSP_PROPVAL_OVERLINE,
LCSP_PROPVAL_POINTER,
LCSP_PROPVAL_PRE,
LCSP_PROPVAL_PRE_LINE,
LCSP_PROPVAL_PRE_WRAP,
LCSP_PROPVAL_PROGRESS,
LCSP_PROPVAL_RELATIVE,
LCSP_PROPVAL_REPEAT,
LCSP_PROPVAL_REPEAT_X,
LCSP_PROPVAL_REPEAT_Y,
LCSP_PROPVAL_RIGHT,
LCSP_PROPVAL_RTL,
LCSP_PROPVAL_SCROLL,
LCSP_PROPVAL_SEPARATE,
LCSP_PROPVAL_SE_RESIZE,
LCSP_PROPVAL_SHOW,
LCSP_PROPVAL_SILENT,
LCSP_PROPVAL_SMALL_CAPS,
LCSP_PROPVAL_SMALL_CAPTION,
LCSP_PROPVAL_SPELL_OUT,
LCSP_PROPVAL_SQUARE,
LCSP_PROPVAL_S_RESIZE,
LCSP_PROPVAL_STATIC,
LCSP_PROPVAL_STATUS_BAR,
LCSP_PROPVAL_SUB,
LCSP_PROPVAL_SUPER,
LCSP_PROPVAL_SW_RESIZE,
LCSP_PROPVAL_TABLE,
LCSP_PROPVAL_TABLE_CAPTION,
LCSP_PROPVAL_TABLE_CELL,
LCSP_PROPVAL_TABLE_COLUMN,
LCSP_PROPVAL_TABLE_COLUMN_GROUP,
LCSP_PROPVAL_TABLE_FOOTER_GROUP,
LCSP_PROPVAL_TABLE_HEADER_GROUP,
LCSP_PROPVAL_TABLE_ROW,
LCSP_PROPVAL_TABLE_ROW_GROUP,
LCSP_PROPVAL_TEXT_BOTTOM,
LCSP_PROPVAL_TEXT_TOP,
LCSP_PROPVAL_TEXT,
LCSP_PROPVAL_TOP,
LCSP_PROPVAL_TRANSPARENT,
LCSP_PROPVAL_UNDERLINE,
LCSP_PROPVAL_UPPER_ALPHA,
LCSP_PROPVAL_UPPERCASE,
LCSP_PROPVAL_UPPER_LATIN,
LCSP_PROPVAL_UPPER_ROMAN,
LCSP_PROPVAL_VISIBLE,
LCSP_PROPVAL_WAIT,
LCSP_PROPVAL_W_RESIZE,
LCSP_PROPVAL__COUNT /* always last */
} lcsp_propvals_t;
struct lhp_ctx;
typedef lws_stateful_ret_t (*lhp_callback)(struct lhp_ctx *ctx, char reason);
/* html attribute */
typedef struct lhp_atr {
lws_dll2_t list;
size_t name_len; /* 0 if it is elem tag */
size_t value_len;
/* name+NUL then value+NUL follow */
} lhp_atr_t;
/*
* In order to lay out the table, we have to incrementally adjust all foregoing
* DLOs as newer cells change the situation. So we have to keep track of all
* cell DLOs in a stack of tables until it's all done.
*/
typedef struct {
lws_dll2_t list; /* ps->table_cols */
lws_dll2_owner_t row_dlos; /* lws_dlo_t in column */
lws_fx_t height; /* currently computed row height */
} lhp_table_row_t;
typedef struct {
lws_dll2_t list; /* ps->table_cols */
lws_dll2_owner_t col_dlos; /* lws_dlo_t in column */
lws_fx_t width; /* currently computed column width */
} lhp_table_col_t;
struct lcsp_atr;
#define CCPAS_TOP 0
#define CCPAS_RIGHT 1
#define CCPAS_BOTTOM 2
#define CCPAS_LEFT 3
typedef struct lhp_pstack {
lws_dll2_t list;
void *user; /* private to the stack level */
lhp_callback cb;
/* static: x,y: offset from parent, w,h: surface size of this object */
lws_box_t drt;
/* dynamic cursor inside drt for progressive child placement */
lws_fx_t curx;
lws_fx_t cury;
lws_fx_t widest;
lws_fx_t deepest;
lws_dlo_t *dlo_set_curx;
lws_dlo_t *dlo_set_cury;
lws_dll2_owner_t atr; /* lhp_atr_t */
const lws_display_font_t *f;
const struct lcsp_atr *css_background_color;
const struct lcsp_atr *css_color;
const struct lcsp_atr *css_position;
const struct lcsp_atr *css_display;
const struct lcsp_atr *css_width;
const struct lcsp_atr *css_height;
const struct lcsp_atr *css_border_radius[4];
const struct lcsp_atr *css_pos[4];
const struct lcsp_atr *css_margin[4];
const struct lcsp_atr *css_padding[4];
uint16_t tr_idx; /* in table */
uint16_t td_idx; /* in current tr */
uint8_t is_block:1; /* children use space in our drt */
uint8_t is_table:1;
/* user layout owns these after initial values set */
lws_dlo_t *dlo;
const lws_display_font_t *font;
int oi[4];
int positioned[4];
int rel_layout_cursor[4];
uint8_t runon; /* continues same line */
} lhp_pstack_t;
typedef enum lcsp_css_units {
LCSP_UNIT_NONE,
LCSP_UNIT_NUM, /* u.i */
LCSP_UNIT_LENGTH_EM, /* u.i */
LCSP_UNIT_LENGTH_EX, /* u.i */
LCSP_UNIT_LENGTH_IN, /* u.i */
LCSP_UNIT_LENGTH_CM, /* u.i */
LCSP_UNIT_LENGTH_MM, /* u.i */
LCSP_UNIT_LENGTH_PT, /* u.i */
LCSP_UNIT_LENGTH_PC, /* u.i */
LCSP_UNIT_LENGTH_PX, /* u.i */
LCSP_UNIT_LENGTH_PERCENT, /* u.i */
LCSP_UNIT_ANGLE_ABS_DEG, /* u.i */
LCSP_UNIT_ANGLE_REL_DEG, /* u.i */
LCSP_UNIT_FREQ_HZ, /* u.i */
LCSP_UNIT_RGBA, /* u.rgba */
LCSP_UNIT_URL, /* string at end of atr */
LCSP_UNIT_STRING, /* string at end of atr */
LCSP_UNIT_DATA, /* binary data at end of atr */
} lcsp_css_units_t;
typedef struct lcsp_atr {
lws_dll2_t list;
int propval; /* lcsp_propvals_t LCSP_PROPVAL_ */
size_t value_len; /* for string . url */
lcsp_css_units_t unit;
union {
lws_fx_t i;
uint32_t rgba; /* for colours */
} u;
lws_fx_t r;
uint8_t op;
/* .value_len bytes follow (for strings and blobs) */
} lcsp_atr_t;
/* css definitions like font-weight: */
typedef struct lcsp_defs {
lws_dll2_t list;
lws_dll2_owner_t atrs; /* lcsp_atr_t */
lcsp_props_t prop; /* lcsp_props_t, LCSP_PROP_* */
} lcsp_defs_t;
typedef struct lcsp_names {
lws_dll2_t list;
size_t name_len;
/* name + NUL follow */
} lcsp_names_t;
typedef struct lcsp_stanza { /* css stanza, with names and defs */
lws_dll2_t list;
lws_dll2_owner_t names; /* lcsp_names_t */
lws_dll2_owner_t defs; /* lcsp_defs_t */
} lcsp_stanza_t;
/*
* A list of stanza references can easily have to bring in the same stanza
* multiple times, eg, <div><span class=x><div> won't work unless the div
* stanzas are listed twice at different places in the list. It means we can't
* use dll2 directly since the number of references is open-ended.
*
* lcsp_stanza_ptr provides indirection that allows multiple listings.
*/
typedef struct lcsp_stanza_ptr {
lws_dll2_t list;
lcsp_stanza_t *stz;
} lcsp_stanza_ptr_t;
typedef struct lcsp_atr_ptr {
lws_dll2_t list;
lcsp_atr_t *atr;
} lcsp_atr_ptr_t;
#define LHP_FLAG_DOCUMENT_END (1 << 0)
typedef struct lhp_ctx {
lws_dll2_owner_t stack; /* lhp_pstack_t */
struct lwsac *cssac; /* css allocations all in an ac */
struct lwsac *cascadeac; /* active_stanzas ac */
struct lwsac *propatrac; /* prop atr query results ac */
lws_dll2_owner_t css; /* lcsp_stanza_t (all in ac) */
lws_dll2_owner_t *ids;
lws_fx_t tf;
lcsp_css_units_t unit;
lcsp_stanza_t *stz; /* current stanza getting properties */
lcsp_defs_t *def; /* current property getting values */
lws_dll2_owner_t active_stanzas; /* lcsp_stanza_ptr_t allocated
* in cascadeac */
lws_dll2_owner_t active_atr; /* lcsp_atr_ptr_t allocated in
* propatrac */
lws_surface_info_t ic;
const char *base_url; /* strdup of https://x.com/y.html */
sul_cb_t ssevcb; /* callback for ss events */
lws_sorted_usec_list_t *ssevsul; /* sul to use to resume rz */
sul_cb_t sshtmlevcb; /* callback for more html parse */
lws_sorted_usec_list_t *sshtmlevsul; /* sul for more html parse */
void *user;
void *user1;
const char *tag; /* private */
size_t tag_len; /* private */
int npos;
int state; /* private */
int state_css_comm; /* private */
int nl_temp;
int temp_count;
uint32_t flags;
uint32_t temp;
int32_t window; /* 0, or ss item flow control limit */
union {
uint32_t s;
struct {
uint32_t first:1;
uint32_t closing:1;
uint32_t void_element:1;
uint32_t doctype:1;
uint32_t inq:1;
uint32_t tag_used:1;
uint32_t arg:1;
uint32_t default_css:1;
#define LHP_CSS_PROPVAL_INT_WHOLE 1
#define LHP_CSS_PROPVAL_INT_FRAC 2
#define LHP_CSS_PROPVAL_INT_UNIT 3
uint32_t integer:2;
uint32_t color:2;
} f;
} u;
int prop; /* lcsp_props_t */
int propval; /* lcsp_propvals_t */
int16_t css_state; /* private */
int16_t cssval_state; /* private */
uint8_t in_body:1;
uint8_t finish_css:1;
uint8_t is_css:1;
uint8_t await_css_done:1;
/* at end so we can memset members above it in one go */
char buf[LHP_STRING_CHUNK + 1];
} lhp_ctx_t;
/*
* lws_lhp_construct() - Construct an lhp context
*
* \param ctx: the lhp context to prepare
* \param cb: the stream parsing callback
* \param user: opaque user pointer available from the lhp context
* \param ic: struct with arguments for lhp context
*
* The lhp context is allocated by the caller (the size is known).
* Prepares an lhp context to parse html. Returns 0 for OK, or nonzero if OOM.
*/
LWS_VISIBLE LWS_EXTERN int
lws_lhp_construct(lhp_ctx_t *ctx, lhp_callback cb, void *user,
const lws_surface_info_t *ic);
/*
* lws_lhp_destruct() - Destroy an lhp context
*
* \param ctx: the lhp context to prepare
*
* Destroys an lhp context. The lhp context is allocated by the caller (the
* size is known). But there are suballocations that must be destroyed with
* this.
*/
LWS_VISIBLE LWS_EXTERN void
lws_lhp_destruct(lhp_ctx_t *ctx);
/**
* lws_lhp_ss_browse() - browse url using SS and parse via lhp to DLOs
*
* \param cx: the lws_context
* \param rs: the user's render state object
* \param url: the https://x.com/y.xyz URL to browse
* \param render: the user's linewise render callback (called from \p rs.sul)
*
* High level network fetch via SS and render html via lhp / DLO
*
* rs->ic must be prepared before calling.
*
* Returns nonzero if an early, fatal problem, else returns 0 and continues
* asynchronously.
*
* If rs->box is (0,0,0,0) on entry, it is set to represent the whole display
* surface. Otherwise if not representing the whole display surface, it
* indicates partial mode should be used.
*/
LWS_VISIBLE LWS_EXTERN int
lws_lhp_ss_browse(struct lws_context *cx, lws_display_render_state_t *rs,
const char *url, sul_cb_t render);
/**
* lws_lhp_parse() - parses a chunk of input HTML
*
* \p ctx: the parsing context
* \p buf: pointer to the start of the chunk of html
* \p len: pointer the number of bytes of html available at *\pbuf
*
* Parses up to *len bytes at *buf. On exit, *buf and *len are adjusted
* according to how much data was used. May return before processing all the
* input.
*
* Returns LWS_SRET_WANT_INPUT if the parsing is stalled on some other async
* event (eg, fetch of image to find out the dimensions).
*
* The lws_lhp_ss_browse() api wraps this.
*/
LWS_VISIBLE LWS_EXTERN lws_stateful_ret_t
lws_lhp_parse(lhp_ctx_t *ctx, const uint8_t **buf, size_t *len);
/**
* lws_css_cascade_get_prop_atr() - create active css atr list for property
*
* \p ctx: the parsing context
* \p prop: the LCSP_PROP_ property to generate the attribute list for
*
* Returns NULL if no atr or OOM.
*
* Otherwise produces a list of active CSS property attributes walkable via
* ctx->active_atr, and returns the tail one. For simple attributes where the
* last definition is the active one, this points to the last definition.
*/
LWS_VISIBLE LWS_EXTERN const lcsp_atr_t *
lws_css_cascade_get_prop_atr(lhp_ctx_t *ctx, lcsp_props_t prop);
/**
* lws_http_rel_to_url() - make absolute url from base and relative
*
* \param dest: place to store the result
* \param len: max length of result including NUL
* \param base: a reference url including a file part
* \param rel: the absolute or relative url or path to apply to base
*
* Copy the url formof rel into dest, using base to fill in missing context
*
* If base is https://x.com/y/z.html
*
* a.html -> https://x.com/y/a/html
* ../b.html -> https://x.com/b.html
* /c.html -> https://x.com/c.html
* https://y.com/a.html -> https://y.com/a.html
*/
LWS_VISIBLE LWS_EXTERN int
lws_http_rel_to_url(char *dest, size_t len, const char *base, const char *rel);
LWS_VISIBLE LWS_EXTERN lhp_pstack_t *
lws_css_get_parent_block(lhp_ctx_t *ctx, lhp_pstack_t *ps);
LWS_VISIBLE LWS_EXTERN const char *
lws_css_pstack_name(lhp_pstack_t *ps);
LWS_VISIBLE LWS_EXTERN const char *
lws_html_get_atr(lhp_pstack_t *ps, const char *aname, size_t aname_len);
LWS_VISIBLE LWS_EXTERN const lws_fx_t *
lws_csp_px(const lcsp_atr_t *a, lhp_pstack_t *ps);
LWS_VISIBLE LWS_EXTERN void
lws_lhp_tag_dlo_id(lhp_ctx_t *ctx, lhp_pstack_t *ps, lws_dlo_t *dlo);
void
lhp_set_dlo_padding_margin(lhp_pstack_t *ps, lws_dlo_t *dlo);
#define LWS_LHPREF_WIDTH 0
#define LWS_LHPREF_HEIGHT 1
#define LWS_LHPREF_NONE 2
LWS_VISIBLE LWS_EXTERN int
lhp_prop_axis(const lcsp_atr_t *a);