You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
7.3 KiB
216 lines
7.3 KiB
//
|
|
// This module implements token substitution in files served by the server.
|
|
//
|
|
// Tokens are in the form {token}, or {escape:token}, where escape can be:
|
|
// - h ... html escape (plain text in a html file, attribute value)
|
|
// - j ... js escape (for use in JS strings)
|
|
//
|
|
// When no escape is specified, the token substitution is written verbatim into the response.
|
|
//
|
|
// var foo = "{j:foo}";
|
|
// <input value="{h:old_value}">
|
|
// {generated-html-goes-here}
|
|
//
|
|
// Token can be made optional by adding '?' at the end (this can't be used for includes).
|
|
// Such token then simply becomes empty string when not substituted, as opposed to being included in the page verbatim.
|
|
//
|
|
// <input value="{h:old_value?}">
|
|
//
|
|
// token names can contain alnum, dash, period and underscore, and are case sensitive.
|
|
//
|
|
//
|
|
// It is further possible to include a static file with optional key-value replacements. These serve as defaults.
|
|
//
|
|
// {@_subfile.html}
|
|
// {@_subfile.html|key=value lalala}
|
|
// {@_subfile.html|key=value lalala|other=value}
|
|
//
|
|
// File inclusion can be nested, and the files can use replacement tokens as specified by the include statement
|
|
//
|
|
// Created on 2019/01/24 by Ondrej Hruska <ondra@ondrovo.com>
|
|
//
|
|
|
|
#ifndef FBNODE_TOKEN_SUBS_H
|
|
#define FBNODE_TOKEN_SUBS_H
|
|
|
|
#include "embedded_files.h"
|
|
#include <sys/queue.h>
|
|
#include <esp_err.h>
|
|
#include <esp_http_server.h>
|
|
|
|
/** Max length of a token buffer (must suffice for all included filenames) */
|
|
#define MAX_TOKEN_LEN 32
|
|
|
|
/** Max length of a key-value substitution when using tpl_kv_replacer;
|
|
* This is also used internally for in-line replacements in file imports. */
|
|
#define TPL_KV_KEY_LEN 24
|
|
/** Max length of a substituion in tpl_kv_replacer */
|
|
#define TPL_KV_SUBST_LEN 64
|
|
|
|
/**
|
|
* Escape type - argument for httpd_resp_send_chunk_escaped()
|
|
*/
|
|
typedef enum {
|
|
TPL_ESCAPE_NONE = 0,
|
|
TPL_ESCAPE_HTML,
|
|
TPL_ESCAPE_JS,
|
|
} tpl_escape_t;
|
|
|
|
enum {
|
|
HTOPT_NONE = 0,
|
|
HTOPT_NO_HEADERS = 1 << 0,
|
|
HTOPT_NO_CLOSE = 1 << 1,
|
|
HTOPT_INCLUDE = HTOPT_NO_HEADERS|HTOPT_NO_CLOSE,
|
|
};
|
|
|
|
/**
|
|
* Send string using a given escaping scheme
|
|
*
|
|
* @param r
|
|
* @param buf - buf to send
|
|
* @param len - buf len, or HTTPD_RESP_USE_STRLEN
|
|
* @param escape - escaping type
|
|
* @return success
|
|
*/
|
|
esp_err_t httpd_resp_send_chunk_escaped(httpd_req_t *r, const char *buf, ssize_t len, tpl_escape_t escape);
|
|
|
|
/**
|
|
* Template substitution callback. Data shall be sent using httpd_resp_send_chunk_escaped().
|
|
*
|
|
* @param[in,out] context - user-defined page state data
|
|
* @param[in] token - replacement token
|
|
* @return ESP_OK if the token was substituted, ESP_ERR_NOT_FOUND if it is unknown, other errors on e.g. send failure
|
|
*/
|
|
typedef esp_err_t (*template_subst_t)(httpd_req_t *r, void *context, const char *token, tpl_escape_t escape);
|
|
|
|
/**
|
|
* Send a template file as a response. The content type from the file struct will be used.
|
|
*
|
|
* Use HTOPT_INCLUDE when used to embed a file inside a template.
|
|
*
|
|
* @param r - request
|
|
* @param file_index - file index in EMBEDDED_FILE_LOOKUP
|
|
* @param replacer - substitution callback, can be NULL if only includes are to be processed
|
|
* @param context - arbitrary context, will be passed to the replacer function; can be NULL
|
|
* @param opts - flag options (HTOPT_*)
|
|
*/
|
|
esp_err_t httpd_send_template_file(httpd_req_t *r, int file_index, template_subst_t replacer, void *context, uint32_t opts);
|
|
|
|
/**
|
|
* Same as httpd_send_template_file, but using an `embedded_file_info` struct.
|
|
*/
|
|
esp_err_t httpd_send_template_file_struct(httpd_req_t *r, const struct embedded_file_info *file, template_subst_t replacer, void *context, uint32_t opts);
|
|
|
|
/**
|
|
* Process and send a string template.
|
|
* The content-type header should be set beforehand, if different from the default (text/html).
|
|
*
|
|
* Use HTOPT_INCLUDE when used to embed a file inside a template.
|
|
*
|
|
* @param r - request
|
|
* @param template - template string (does not have to be terminated by a null byte)
|
|
* @param template_len - length of the template string; -1 to use strlen()
|
|
* @param replacer - substitution callback, can be NULL if only includes are to be processed
|
|
* @param context - arbitrary context, will be passed to the replacer function; can be NULL
|
|
* @param opts - flag options (HTOPT_*)
|
|
*/
|
|
esp_err_t httpd_send_template(httpd_req_t *r, const char *template, ssize_t template_len, template_subst_t replacer, void *context, uint32_t opts);
|
|
|
|
/**
|
|
* Send a static file. This can be used to just send a file, or to embed a static template as a token substitution.
|
|
*
|
|
* Use HTOPT_INCLUDE when used to embed a file inside a template.
|
|
*
|
|
* Note: use httpd_resp_send_chunk_escaped() or httpd_resp_send_chunk() to send a plain string.
|
|
*
|
|
* @param r - request
|
|
* @param file_index - file index in EMBEDDED_FILE_LOOKUP
|
|
* @param escape - escape option
|
|
* @param opts - flag options (HTOPT_*)
|
|
* @return
|
|
*/
|
|
esp_err_t httpd_send_static_file(httpd_req_t *r, int file_index, tpl_escape_t escape, uint32_t opts);
|
|
|
|
/**
|
|
* Same as httpd_send_template_file, but using an `embedded_file_info` struct.
|
|
*/
|
|
esp_err_t httpd_send_static_file_struct(httpd_req_t *r, const struct embedded_file_info *file, tpl_escape_t escape, uint32_t opts);
|
|
|
|
struct tpl_kv_entry {
|
|
char key[TPL_KV_KEY_LEN]; // copied here
|
|
char subst[TPL_KV_SUBST_LEN]; // copied here
|
|
SLIST_ENTRY(tpl_kv_entry) link;
|
|
};
|
|
|
|
SLIST_HEAD(tpl_kv_list, tpl_kv_entry);
|
|
|
|
/**
|
|
* key-value replacer that works with a dynamically allocated SLIST.
|
|
*
|
|
* @param r - request
|
|
* @param context - context - must be a pointer to `struct tpl_kv_list`
|
|
* @param token - token to replace
|
|
* @param escape - escape option
|
|
* @return OK/not found/other
|
|
*/
|
|
esp_err_t tpl_kv_replacer(httpd_req_t *r, void *context, const char *token, tpl_escape_t escape);
|
|
|
|
/**
|
|
* Add a pair into the substitutions list
|
|
*
|
|
* @param head - list head
|
|
* @param key - key, copied
|
|
* @param subst - value, copied
|
|
* @return success (fails if malloc failed)
|
|
*/
|
|
esp_err_t tpl_kv_add(struct tpl_kv_list *head, const char *key, const char *subst);
|
|
|
|
/**
|
|
* Convenience function that converts an IP address to string and adds it as a substitution
|
|
*
|
|
* @param head - list head
|
|
* @param key - key, copied
|
|
* @param ip4h - host order ipv4 address
|
|
* @return success
|
|
*/
|
|
esp_err_t tpl_kv_add_ipv4str(struct tpl_kv_list *head, const char *key, uint32_t ip4h);
|
|
|
|
/** add int as a substitution; key is copied */
|
|
esp_err_t tpl_kv_add_int(struct tpl_kv_list *head, const char *key, int32_t num);
|
|
|
|
/** add long as a substitution; key is copied */
|
|
esp_err_t tpl_kv_add_long(struct tpl_kv_list *head, const char *key, int64_t num);
|
|
|
|
/** add printf-formatted value; key is copied */
|
|
esp_err_t tpl_kv_sprintf(struct tpl_kv_list *head, const char *key, const char *format, ...)
|
|
__attribute__((format(printf,3,4)));
|
|
|
|
/**
|
|
* Init a substitutions list (on the stack)
|
|
*
|
|
* @return the list
|
|
*/
|
|
static inline struct tpl_kv_list tpl_kv_init(void)
|
|
{
|
|
return (struct tpl_kv_list) {.slh_first = NULL};
|
|
}
|
|
|
|
/**
|
|
* Free the list (head is left alone because it was allocated on the stack)
|
|
* @param head
|
|
*/
|
|
void tpl_kv_free(struct tpl_kv_list *head);
|
|
|
|
/**
|
|
* Send the map as an ASCII table separated by Record Separator (30) and Unit Separator (31).
|
|
* Content type is set to application/octet-stream.
|
|
*
|
|
* key 31 value 30
|
|
* key 31 value 30
|
|
* key 31 value
|
|
*
|
|
* @param req
|
|
*/
|
|
esp_err_t tpl_kv_send_as_ascii_map(httpd_req_t *req, struct tpl_kv_list *head);
|
|
|
|
#endif //FBNODE_TOKEN_SUBS_H
|
|
|