static int tmpl_load(nxt_context* ctx, const char* uri, nxt_file* dst_file, nxt_block* dst_block) { // function to make subrequests if (dst_block) { nxweb_log_error("including file %s", uri); nxt_block_append_value(ctx, dst_block, "{% This is included file %}", sizeof("{% This is included file %}")-1, 0); } else { nxweb_log_error("loading template from %s", uri); if (!strcmp(uri, "base")) { const char* tmpl_src=" {%block _top_%}{%raw%}{{{{%%%%}}}}{%endraw%}{% include aaa %}AAA-YYY{%block header%}Header{%endblock%} bye...{% endblock %}{% block title %}New Title{% endblock %}"; char* tmpl=nxb_copy_obj(ctx->nxb, tmpl_src, strlen(tmpl_src)+1); nxt_parse_file(dst_file, (char*)tmpl, strlen(tmpl)); } else if (!strcmp(uri, "ttt")) { const char* tmpl_src=" {% extends 'base'%} {%block header%}Bbbb {%block title%}{%endblock%} {% parent %}{%endblock%}"; char* tmpl=nxb_copy_obj(ctx->nxb, tmpl_src, strlen(tmpl_src)+1); nxt_parse_file(dst_file, (char*)tmpl, strlen(tmpl)); } } }
static nxweb_result tmpl_on_request(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_response* resp) { nxweb_set_response_content_type(resp, "text/html"); const char* tmpl="{% extends \"ttt\"%} {% block title %}The Very {% parent %}{% endblock %}"; tmpl=nxb_copy_obj(req->nxb, tmpl, strlen(tmpl)+1); nxt_context ctx; nxt_init(&ctx, req->nxb, tmpl_load); nxt_parse(&ctx, req->uri, (char*)tmpl, strlen(tmpl)); nxt_merge(&ctx); resp->content=nxt_serialize(&ctx); resp->content_length=strlen(resp->content); return NXWEB_OK; }
static const char* expand_vars(ssi_buffer* ssib, const char* expr) { char expanded[SSI_MAX_EXPR_LEN]; char *d=expanded, *de=d+SSI_MAX_EXPR_LEN-1; const char* start=expr; const char *p, *pp; while ((p=strchr(start, '$'))) { if (p>start && *(p-1)=='\\') { // escaped \$ exp_append(start, p-start-1); exp_append_char('$'); start=p+1; continue; } exp_append(start, p-start); p++; if (*p=='{') { pp=strchr(p+1, '}'); if (!pp) return 0; exp_append_var(p+1, pp-(p+1)); start=pp+1; } else { for (pp=p; (*pp>='a' && *pp<='z')||(*pp>='A' && *pp<='Z')||(*pp>='0' && *pp<='9')||*pp=='_'; pp++) ; exp_append_var(p, pp-p); start=pp; } } if (d==expanded) return expr; // unchanged else { exp_append(start, strlen(start)); *d++='\0'; return nxb_copy_obj(ssib->nxb, expanded, d-expanded); } }
static int parse_directive(ssi_buffer* ssib, char* str, int len) { assert(!str[len]); // zero-terminated char* p=str; char* pe=str+len; char* attr_name[SSI_MAX_ATTRS]; char* attr_value[SSI_MAX_ATTRS]; int num_attr=0; while ((unsigned char)*p<=SPACE && p<pe) p++; if (p>=pe) return -1; char* cmd=p; while ((unsigned char)*p>SPACE) p++; *p++='\0'; while (num_attr<SSI_MAX_ATTRS) { attr_name[num_attr]=p; p=strchr(p, '='); if (!p) break; *p++='\0'; attr_name[num_attr]=nxweb_trunc_space(attr_name[num_attr]); while ((unsigned char)*p<=SPACE && p<pe) p++; if (p>=pe) return -1; char q=*p++; if (q!='\"' && q!='\'') return -1; attr_value[num_attr]=p; p=strchr(p, q); if (!p) return -1; *p++='\0'; num_attr++; } if (!strcmp(cmd, "include")) { int i; for (i=0; i<num_attr; i++) { if (!strcmp(attr_name[i], "virtual")) { const char* expanded=expand_vars(ssib, attr_value[i]); if (!expanded) { nxweb_log_warning("ssi variables expansion failure: %s @ %s", attr_value[i], ssib->req->uri); return -1; } // nxweb_log_error("ssi variables expanded: %s -> %s", attr_value[i], expanded); nxweb_composite_stream_append_subrequest(ssib->cs, ssib->cs->req->host, expanded); return 0; } } } else if (!strcmp(cmd, "set")) { int i; const char* var_name=0; const char* var_value=0; nx_simple_map_entry* param; for (i=0; i<num_attr; i++) { if (!strcmp(attr_name[i], "var")) { var_name=attr_value[i]; } else if (!strcmp(attr_name[i], "value")) { var_value=expand_vars(ssib, attr_value[i]); if (!var_value) { nxweb_log_warning("ssi set variable expansion failure: %s @ %s", attr_value[i], ssib->req->uri); return -1; } // nxweb_log_error("ssi variables expanded: %s -> %s", attr_value[i], var_value); } } if (var_name && var_value) { param=nx_simple_map_find(ssib->var_map, var_name); if (!param) { param=nxb_calloc_obj(ssib->nxb, sizeof(nx_simple_map_entry)); ssib->var_map=nx_simple_map_add(ssib->var_map, param); param->name=var_name; } param->value=var_value; return 0; } } else if (!strcmp(cmd, "echo")) { int i; for (i=0; i<num_attr; i++) { if (!strcmp(attr_name[i], "var")) { const char* var_name=attr_value[i]; char expanded[SSI_MAX_EXPR_LEN]; char* end=expand_var(ssib, var_name, strlen(var_name), expanded, SSI_MAX_EXPR_LEN); if (!end) { // nxweb_log_warning("ssi echo variable expansion failure: %s @ %s", var_name, ssib->req->uri); return -1; } int len=end-expanded; char* buf=nxb_copy_obj(ssib->nxb, expanded, len); nxweb_composite_stream_append_bytes(ssib->cs, buf, len); return 0; } } } return -1; }