Split khttp_templatex functions out of khttp_template.3.

Provide working examples for both.
This commit is contained in:
kristapsdz committed 2020-10-17 12:02:59 +00:00
1 parent 15a2db7654
commit cfe14c8cce
4 files changed
+357 -191

No files matched your search

+1
View File
@@ -104,6 +104,7 @@ MAN3S = man/kcgi.3 \
man/khttp_putc.3 \
man/khttp_puts.3 \
man/khttp_template.3 \
man/khttp_templatex.3 \
man/khttp_urlabs.3 \
man/khttp_urldecode.3 \
man/khttp_urlencode.3 \
+1
View File
@@ -311,6 +311,7 @@ string) for the full HTTP message body.
.Xr khttp_putc 3 ,
.Xr khttp_puts 3 ,
.Xr khttp_template 3 ,
.Xr khttp_templatex 3 ,
.Xr khttp_write 3 ,
.Xr khttpbasic_validate 3 ,
.Xr khttpdigest_validate 3 ,
+108 -191
View File
@@ -1,6 +1,6 @@
.\" $Id$
.\"
.\" Copyright (c) 2014, 2017--2018 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2014, 2017--2018, 2020 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
@@ -20,11 +20,8 @@
.Os
.Sh NAME
.Nm khttp_template ,
.Nm khttp_templatex ,
.Nm khttp_template_buf ,
.Nm khttp_templatex_buf ,
.Nm khttp_template_fd ,
.Nm khttp_templatex_fd
.Nm khttp_template_fd
.Nd emit filled-in templates for kcgi
.Sh LIBRARY
.Lb libkcgi
@@ -40,13 +37,6 @@
.Fa "const char *filename"
.Fc
.Ft enum kcgi_err
.Fo khttp_templatex
.Fa "const struct ktemplate *t"
.Fa "const char *filename"
.Fa "const struct ktemplatex *tx"
.Fa "void *arg"
.Fc
.Ft enum kcgi_err
.Fo khttp_template_buf
.Fa "struct kreq *req"
.Fa "const struct ktemplate *t"
@@ -54,45 +44,31 @@
.Fa "size_t sz"
.Fc
.Ft enum kcgi_err
.Fo khttp_templatex_buf
.Fa "const struct ktemplate *t"
.Fa "const char *buf"
.Fa "size_t sz"
.Fa "const struct ktemplatex *tx"
.Fa "void *arg"
.Fc
.Ft enum kcgi_err
.Fo khttp_template_fd
.Fa "struct kreq *req"
.Fa "const struct ktemplate *t"
.Fa "int fd"
.Fa "const char *filename"
.Fc
.Ft enum kcgi_err
.Fo khttp_templatex_fd
.Fa "const struct ktemplate *t"
.Fa "int fd"
.Fa "const char *filename"
.Fa "const struct ktemplatex *tx"
.Fa "void *arg"
.Fc
.Sh DESCRIPTION
These template functions write a block of HTTP output,
replacing certain substrings with variable content.
They operate in a
.Xr kcgi 3
context
Modify input by replacing keys in a template.
May only be called after
.Xr khttp_body 3 .
Output is written with
.Xr khttp_write 3
using the
.Fa req
allocated with
previously allocated with
.Xr khttp_parse 3
or
.Xr khttp_fcgi_parse 3
and may only be called after
.Xr khttp_body 3 .
.Xr khttp_fcgi_parse 3 .
The
.Xr khttp_templatex 3
family allows for alternative writers.
.Pp
All template functions accept a
.Fa "const struct ktemplate *t"
argument consisting of the following fields:
All functions accept a template
.Fa t
consisting of the following fields:
.Bl -tag -width Ds
.It Fa "const char *const *key"
An array of keys to be replaced in the template.
@@ -111,148 +87,71 @@ is found in
.Fa t->key .
The optional
.Fa arg
is passed to the current writing function.
This callback function normally uses
.Xr khttp_write 3
or
.Fa tx->writer
to write data.
is passed the function.
The function must return zero on failure, non-zero on success.
.El
.Pp
The
.Fn khttp_template ,
.Fn khttp_template_fd ,
and
.Fn khttp_template_buf
functions use
.Xr khttp_write 3
as the current writing function.
.Pp
The
.Fn khttp_templatex ,
.Fn khttp_templatex_buf ,
and
.Fn khttp_templatex_fd
functions extend this behaviour with an additional
.Fa "const struct ktemplatex *tx"
argument having the following fields:
.Bl -tag -width Ds
.It Fa "enum kcgi_err (*writer)(const char *b, size_t sz, void *arg)"
Sets the current writing function that writes
.Fa sz
bytes pointed to by
.Fa b .
The
.Fa arg
argument is as passed to the function; it may be
.Dv NULL .
Any return value but
.Dv KCGI_OK
is considered an error.
.It Fa "int (*fbk)(const char *k, size_t sz, void *arg)"
If an encountered key
.Fa k
of length
.Fa sz
is not found in
.Fa t->key ,
this function is invoked.
The field
.Fa t->arg
is passed as the
.Fa arg .
This function normally uses the writing function in
.Fa tx->writer
to write data.
.El
.Pp
The
.Fa tx->writer
callback may not be
.Dv NULL .
.Pp
The functions
.Fn khttp_template
and
.Fn khttp_templatex
open
.Fa filename
in read-only mode and call the descriptor functions.
.Pp
The descriptor functions
.Fn khttp_template_fd
and
.Fn khttp_templatex_fd
read the template from the open file descriptor
.Fa fd
using
.Xr mmap 2
and call the buffer functions.
They only use the
.Fa filename
for error reporting.
If it is
.Dv NULL ,
.Qq <unknown descriptor>
is used.
.Pp
The buffer functions
.Fn khttp_template_buf
and
.Fn khttp_templatex_buf
read the template from the buffer
.Fa buf
of length
.Fa sz .
If
.Fa sz
is 0, the template is considered empty and
.Fa buf
is ignored.
.Ss Template language
Each substring of the template buffer beginning and ending with a pair
of
.Dq at
signs,
.Cm @@ Ns Ar key Ns Cm @@ ,
is called a
.Dq key sequence .
If the
.Dq at
pair is escaped with a single backslash,
.Cm \e@@ ,
the backslash is removed and it's emitted as
.Cm @@ .
A key sequence may not contain an escaped pair: this is parsed as a backslash
followed by the trailing pair.
.Pp
If the
.Ar key
is found in
.Fa t->key ,
the key sequence is removed from the buffer and the callback
.Fa t->cb
is invoked.
Otherwise, if the fallthrough callback
.Fa tx->fbk
is not
.Dv NULL ,
the key sequence is removed from the buffer and the callback
.Fa tx-fbk
is invoked.
If the key sequence is not found in
.Fa t->key
and the fallthrough callback is
.Dv NULL ,
the key sequence is passed unchanged to the current writing function.
.Pp
If
.Fa t
is
.Dv NULL ,
the whole template is passed through without any processing.
the input is passed through to
.Xr khttp_write 3
without any processing.
.Pp
Otherwise, the input is passed to
.Xr khttp_write 3
until a key sequence in encountered matching a key in
.Fa t->key .
The callback
.Fa t->cb
is then invoked instead of printing the key sequence.
If there are multiple matching keys in
.Fa t->key ,
only one is used (which is not yet fixed).
If the key sequence is not found in
.Fa t->key ,
it is passed unchanged to
.Xr khttp_write 3 .
.Pp
The different input types are
.Fn khttp_template ,
which reads input from the file
.Fa filename ;
.Fn khttp_template_buf ,
which reads from a binary buffer
.Fa buf
of length
.Fa sz ;
and
.Fn khttp_template_fd ,
which reads from a file descriptor
.Fa fd
with optional file-name
.Fa fname
used only for logging purposes.
.Sh SYNTAX
Each substring of the input beginning and ending with a pair
of
.Dq at
signs,
.Cm @@ Ns Ar key Ns Cm @@ ,
is called a
.Qq key sequence .
Zero-length keys
.Cm @@@@
are allowed and match empty template keys.
If the
.Cm @@
pair is escaped with a single backslash,
.Cm \e@@ ,
the backslash is removed and it's emitted as
.Cm @@ .
.Pp
A key sequence may not contain an escaped pair: this is parsed as a
backslash followed by the trailing pair.
.Sh RETURN VALUES
These functions return an
These return an
.Ft enum kcgi_err
indicating the error state:
.Bl -tag -width KCGI_SYSTEM
@@ -264,34 +163,52 @@ Memory allocation failed.
A system call failed.
For example, writing to the output stream failed, or
.Fn khttp_template
or
.Fn khttp_templatex
failed to
.Xr open 2
.Fa filename .
.It Dv KCGI_FORM
.Fa t->cb
or
.Fa tx->fbk
returned 0.
.El
.Sh EXAMPLES
The following simple example takes a buffer
.Fa buf
and applies the replacement template of two values, writing it to the
current context
.Fa req .
.Bd -literal -offset indent
static int writer(size_t idx, void *arg)
{
struct kreq *r = arg;
if (idx == 0)
khttp_puts(r, "foo-value");
else if (idx == 1)
khttp_puts(r, "bar-value");
return 1;
}
enum kcgi_err format(struct kreq *r)
{
const char *const keys[] = { "foo", "bar" };
struct ktemplate t = {
.key = keys,
.keysz = 2,
.arg = r,
.cb = writer
};
const char *buf = "foo=@@foo@@, bar=@@bar@@";
return khttp_template_buf(r, &t, buf, strlen(buf));
}
.Ed
.Pp
An empty template produces no output, and
.Dv KCGI_OK
is returned.
The function will produce
.Qq foo=foo-value, bar=bar-value .
.Sh SEE ALSO
.Xr kcgi 3 ,
.Xr khttp_body 3 ,
.Xr khttp_parse 3 ,
.Xr khttp_templatex 3 ,
.Xr khttp_write 3
.Sh AUTHORS
These functions were written by
Written by
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
.Sh CAVEATS
The
.Fn khttp_template
and
.Fn khttp_templatex
functions need access to the file system.
Read the files before entering a sandbox and use the buffer or file
descriptor versions instead.
+247
View File
@@ -0,0 +1,247 @@
.\" $Id$
.\"
.\" Copyright (c) 2014, 2017--2018, 2020 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate$
.Dt KHTTP_TEMPLATEX 3
.Os
.Sh NAME
.Nm khttp_templatex ,
.Nm khttp_templatex_buf ,
.Nm khttp_templatex_fd
.Nd emit filled-in templates for kcgi
.Sh LIBRARY
.Lb libkcgi
.Sh SYNOPSIS
.In sys/types.h
.In stdarg.h
.In stdint.h
.In kcgi.h
.Ft enum kcgi_err
.Fo khttp_templatex
.Fa "const struct ktemplate *t"
.Fa "const char *filename"
.Fa "const struct ktemplatex *x"
.Fa "void *arg"
.Fc
.Ft enum kcgi_err
.Fo khttp_templatex_buf
.Fa "const struct ktemplate *t"
.Fa "const char *buf"
.Fa "size_t sz"
.Fa "const struct ktemplatex *x"
.Fa "void *arg"
.Fc
.Ft enum kcgi_err
.Fo khttp_templatex_fd
.Fa "const struct ktemplate *t"
.Fa "int fd"
.Fa "const char *filename"
.Fa "const struct ktemplatex *x"
.Fa "void *arg"
.Fc
.Sh DESCRIPTION
Modify input by replacing keys in a template.
This generalises the
.Xr khttp_template 3
family of functions with generic writing functions.
All functions accept a template
.Fa t
consisting of the following fields:
.Bl -tag -width Ds
.It Fa "const char *const *key"
An array of keys to be replaced in the template.
.It Fa "size_t keysz"
The number of keys in
.Fa t->key .
.It Fa "void *arg"
An optional argument passed to
.Fa t->cb .
.It Fa "int (*cb)(size_t index, void *arg)"
The callback function invoked when a key at position
.Fa index ,
which is always less than
.Fa t->keysz ,
is found in
.Fa t->key .
The optional
.Fa arg
is passed the function.
The function must return zero on failure, non-zero on success.
.El
.Pp
They further accept an extension
.Fa x
consisting of the following:
.Bl -tag -width Ds
.It Fa writer
A writing function for writing input that does not match key sequences.
If it is invoked and the return value is not
.Dv KCGI_OK ,
templating stops and the return value is returned to the caller.
.It Fa fbk
A fall-back function invoked if a key sequences was not found in the
.Fa c->key
array.
This accepts the key sequence, length of the sequence, and
.Fa arg .
If
.Dv NULL ,
key sequences not found are passed to
.Fa writer .
.El
.Pp
If
.Fa t
is
.Dv NULL ,
the input is passed through to
.Fa x->writer
without any processing.
.Pp
Otherwise, the input is passed to
.Fa x->writer
until a key sequence in encountered matching a key in
.Fa t->key .
The callback
.Fa t->cb
is then invoked instead of printing the key sequence.
If there are multiple matching keys in
.Fa t->key ,
only one is used (which is not yet fixed).
If the key sequence is not found in
.Fa t->key ,
it is passed to
.Fa x->fbk ,
if not
.Dv NULL ,
or passed directly to
.Fa x->writer
otherwise.
.Pp
The different input types are
.Fn khttpx_template ,
which reads input from the file
.Fa filename ;
.Fn khttpx_template_buf ,
which reads from a binary buffer
.Fa buf
of length
.Fa sz ;
and
.Fn khttpx_template_fd ,
which reads from a file descriptor
.Fa fd
with optional file-name
.Fa fname
used only for logging purposes.
.Sh SYNTAX
Each substring of the input beginning and ending with a pair
of
.Dq at
signs,
.Cm @@ Ns Ar key Ns Cm @@ ,
is called a
.Qq key sequence .
Zero-length keys
.Cm @@@@
are allowed and match empty template keys.
If the
.Cm @@
pair is escaped with a single backslash,
.Cm \e@@ ,
the backslash is removed and it's emitted as
.Cm @@ .
.Pp
A key sequence may not contain an escaped pair: this is parsed as a
backslash followed by the trailing pair.
.Sh RETURN VALUES
These return an
.Ft enum kcgi_err
indicating the error state:
.Bl -tag -width KCGI_SYSTEM
.It Dv KCGI_OK
No error occurred.
.It Dv KCGI_ENOMEM
Memory allocation failed.
.It Dv KCGI_SYSTEM
A system call failed.
For example, writing to the output stream failed, or
.Fn khttp_template
failed to
.Xr open 2
.Fa filename .
.It Dv KCGI_FORM
.Fa t->cb
returned 0.
.El
.Pp
If the
.Fa x->writer
function returns anything but
.Dv KCGI_OK ,
the return code is passed as the return value.
.Sh EXAMPLES
The following simple example takes a buffer
.Fa buf
and applies the replacement template of two values, writing it to the
current context
.Fa req .
It stores the result in the given buffer
.Fa out .
.Bd -literal -offset indent
static int writer(size_t idx, void *arg)
{
struct kcgi_buf *p = arg;
if (idx == 0)
kcgi_buf_puts(p, "foo-value");
else if (idx == 1)
kcgi_buf_puts(p, "bar-value");
return 1;
}
enum kcgi_err format(struct kcgi_buf *out)
{
const char *const keys[] = { "foo", "bar" };
struct ktemplate t = {
.key = keys,
.keysz = 2,
.arg = out,
.cb = writer
};
struct ktemplatex x = {
.writer = kcgi_buf_write,
.fbk = NULL
};
const char *in = "foo=@@foo@@, bar=@@bar@@";
memset(&out, 0, sizeof(struct kcgi_buf));
return khttp_templatex_buf
(&t, in, strlen(in), &x, out);
}
.Ed
.Pp
The function will produce
.Qq foo=foo-value, bar=bar-value .
.Sh SEE ALSO
.Xr kcgi 3 ,
.Xr khttp_body 3 ,
.Xr khttp_parse 3 ,
.Xr khttp_template 3 ,
.Xr khttp_write 3
.Sh AUTHORS
Written by
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .