Files
2021-09-23 22:12:14 +02:00

750 lines
18 KiB
C

/* $Id$ */
/*
* Copyright (c) 2012, 2014--2018 Kristaps Dzonsons <kristaps@bsd.lv>
*
* 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.
*/
#ifndef KCGI_H
#define KCGI_H
#if !defined(__BEGIN_DECLS)
# ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# else
# define __BEGIN_DECLS
# endif
#endif
#if !defined(__END_DECLS)
# ifdef __cplusplus
# define __END_DECLS }
# else
# define __END_DECLS
# endif
#endif
/*
* Stringification of version major, minor, and build.
*/
#define NAME(s) NAME0(s)
#define NAME0(s) #s
#define NAME2(x,y,z) x ## . ## y ## . ## z
#define NAME1(x,y,z) NAME2(x,y,z)
/*
* Major version.
*/
#define KCGI_VMAJOR 0
/*
* Minor version.
*/
#define KCGI_VMINOR 13
/*
* Build version.
*/
#define KCGI_VBUILD 0
/*
* Version string of major.minor.build (as a literal string).
*/
#define KCGI_VERSION NAME(NAME1(KCGI_VMAJOR,KCGI_VMINOR,KCGI_VBUILD))
/*
* Integral stamp of version.
* Guaranteed to be increasing with build, minor, and major.
* (Assumes build and minor never go over 100.)
*/
#define KCGI_VSTAMP \
((KCGI_VBUILD+1) + \
(KCGI_VMINOR+1)*100 + \
(KCGI_VMAJOR+1)*10000)
/*
* All of the public functions, variables, and structures in this header
* file are described in kcgi(3).
* If you don't see something in kcgi(3) and see it here instead, it
* shouldn't be used.
*/
enum khttp {
KHTTP_100,
KHTTP_101,
KHTTP_103,
KHTTP_200,
KHTTP_201,
KHTTP_202,
KHTTP_203,
KHTTP_204,
KHTTP_205,
KHTTP_206,
KHTTP_207,
KHTTP_300,
KHTTP_301,
KHTTP_302,
KHTTP_303,
KHTTP_304,
KHTTP_306,
KHTTP_307,
KHTTP_308,
KHTTP_400,
KHTTP_401,
KHTTP_402,
KHTTP_403,
KHTTP_404,
KHTTP_405,
KHTTP_406,
KHTTP_407,
KHTTP_408,
KHTTP_409,
KHTTP_410,
KHTTP_411,
KHTTP_412,
KHTTP_413,
KHTTP_414,
KHTTP_415,
KHTTP_416,
KHTTP_417,
KHTTP_424,
KHTTP_428,
KHTTP_429,
KHTTP_431,
KHTTP_500,
KHTTP_501,
KHTTP_502,
KHTTP_503,
KHTTP_504,
KHTTP_505,
KHTTP_507,
KHTTP_511,
KHTTP__MAX
};
enum krequ {
KREQU_ACCEPT,
KREQU_ACCEPT_CHARSET,
KREQU_ACCEPT_ENCODING,
KREQU_ACCEPT_LANGUAGE,
KREQU_AUTHORIZATION,
KREQU_DEPTH,
KREQU_FROM,
KREQU_HOST,
KREQU_IF,
KREQU_IF_MODIFIED_SINCE,
KREQU_IF_MATCH,
KREQU_IF_NONE_MATCH,
KREQU_IF_RANGE,
KREQU_IF_UNMODIFIED_SINCE,
KREQU_MAX_FORWARDS,
KREQU_PROXY_AUTHORIZATION,
KREQU_RANGE,
KREQU_REFERER,
KREQU_USER_AGENT,
KREQU__MAX
};
enum kresp {
KRESP_ACCESS_CONTROL_ALLOW_ORIGIN,
KRESP_ACCEPT_RANGES,
KRESP_AGE,
KRESP_ALLOW,
KRESP_CACHE_CONTROL,
KRESP_CONNECTION,
KRESP_CONTENT_ENCODING,
KRESP_CONTENT_LANGUAGE,
KRESP_CONTENT_LENGTH,
KRESP_CONTENT_LOCATION,
KRESP_CONTENT_MD5,
KRESP_CONTENT_DISPOSITION,
KRESP_CONTENT_RANGE,
KRESP_CONTENT_TYPE,
KRESP_DATE,
KRESP_ETAG,
KRESP_EXPIRES,
KRESP_LAST_MODIFIED,
KRESP_LINK,
KRESP_LOCATION,
KRESP_P3P,
KRESP_PRAGMA,
KRESP_PROXY_AUTHENTICATE,
KRESP_REFRESH,
KRESP_RETRY_AFTER,
KRESP_SERVER,
KRESP_SET_COOKIE,
KRESP_STATUS,
KRESP_STRICT_TRANSPORT_SECURITY,
KRESP_TRAILER,
KRESP_TRANSFER_ENCODING,
KRESP_UPGRADE,
KRESP_VARY,
KRESP_VIA,
KRESP_WARNING,
KRESP_WWW_AUTHENTICATE,
KRESP_X_FRAME_OPTIONS,
KRESP__MAX
};
enum kattrx {
KATTRX_STRING,
KATTRX_INT,
KATTRX_DOUBLE
};
enum kmethod {
KMETHOD_ACL,
KMETHOD_CONNECT,
KMETHOD_COPY,
KMETHOD_DELETE,
KMETHOD_GET,
KMETHOD_HEAD,
KMETHOD_LOCK,
KMETHOD_MKCALENDAR,
KMETHOD_MKCOL,
KMETHOD_MOVE,
KMETHOD_OPTIONS,
KMETHOD_POST,
KMETHOD_PROPFIND,
KMETHOD_PROPPATCH,
KMETHOD_PUT,
KMETHOD_REPORT,
KMETHOD_TRACE,
KMETHOD_UNLOCK,
KMETHOD__MAX
};
enum kpairtype {
KPAIR_INTEGER,
KPAIR_STRING,
KPAIR_DOUBLE,
KPAIR__MAX
};
enum kscheme {
KSCHEME_AAA,
KSCHEME_AAAS,
KSCHEME_ABOUT,
KSCHEME_ACAP,
KSCHEME_ACCT,
KSCHEME_CAP,
KSCHEME_CID,
KSCHEME_COAP,
KSCHEME_COAPS,
KSCHEME_CRID,
KSCHEME_DATA,
KSCHEME_DAV,
KSCHEME_DICT,
KSCHEME_DNS,
KSCHEME_FILE,
KSCHEME_FTP,
KSCHEME_GEO,
KSCHEME_GO,
KSCHEME_GOPHER,
KSCHEME_H323,
KSCHEME_HTTP,
KSCHEME_HTTPS,
KSCHEME_IAX,
KSCHEME_ICAP,
KSCHEME_IM,
KSCHEME_IMAP,
KSCHEME_INFO,
KSCHEME_IPP,
KSCHEME_IRIS,
KSCHEME_IRIS_BEEP,
KSCHEME_IRIS_XPC,
KSCHEME_IRIS_XPCS,
KSCHEME_IRIS_LWZ,
KSCHEME_JABBER,
KSCHEME_LDAP,
KSCHEME_MAILTO,
KSCHEME_MID,
KSCHEME_MSRP,
KSCHEME_MSRPS,
KSCHEME_MTQP,
KSCHEME_MUPDATE,
KSCHEME_NEWS,
KSCHEME_NFS,
KSCHEME_NI,
KSCHEME_NIH,
KSCHEME_NNTP,
KSCHEME_OPAQUELOCKTOKEN,
KSCHEME_POP,
KSCHEME_PRES,
KSCHEME_RELOAD,
KSCHEME_RTSP,
KSCHEME_RTSPS,
KSCHEME_RTSPU,
KSCHEME_SERVICE,
KSCHEME_SESSION,
KSCHEME_SHTTP,
KSCHEME_SIEVE,
KSCHEME_SIP,
KSCHEME_SIPS,
KSCHEME_SMS,
KSCHEME_SNMP,
KSCHEME_SOAP_BEEP,
KSCHEME_SOAP_BEEPS,
KSCHEME_STUN,
KSCHEME_STUNS,
KSCHEME_TAG,
KSCHEME_TEL,
KSCHEME_TELNET,
KSCHEME_TFTP,
KSCHEME_THISMESSAGE,
KSCHEME_TN3270,
KSCHEME_TIP,
KSCHEME_TURN,
KSCHEME_TURNS,
KSCHEME_TV,
KSCHEME_URN,
KSCHEME_VEMMI,
KSCHEME_WS,
KSCHEME_WSS,
KSCHEME_XCON,
KSCHEME_XCON_USERID,
KSCHEME_XMLRPC_BEEP,
KSCHEME_XMLRPC_BEEPS,
KSCHEME_XMPP,
KSCHEME_Z39_50R,
KSCHEME_Z39_50S,
KSCHEME__MAX
};
enum kmime {
KMIME_APP_JAVASCRIPT,
KMIME_APP_JSON,
KMIME_APP_OCTET_STREAM,
KMIME_APP_PDF,
KMIME_APP_XML,
KMIME_APP_ZIP,
KMIME_IMAGE_GIF,
KMIME_IMAGE_JPEG,
KMIME_IMAGE_PNG,
KMIME_IMAGE_SVG_XML,
KMIME_TEXT_CALENDAR,
KMIME_TEXT_CSS,
KMIME_TEXT_CSV,
KMIME_TEXT_HTML,
KMIME_TEXT_PLAIN,
KMIME_TEXT_XML,
KMIME__MAX
};
struct kmimemap {
const char *name;
size_t mime;
};
enum kpairstate {
KPAIR_UNCHECKED = 0,
KPAIR_VALID,
KPAIR_INVALID
};
#define KREQ_DEBUG_WRITE 0x01
#define KREQ_DEBUG_READ_BODY 0x02
struct kpair {
char *key; /* key name */
size_t keypos; /* bucket (if assigned) */
char *val; /* key value */
size_t valsz; /* length of "val" */
char *file; /* content filename (or NULL) */
char *ctype; /* content type (or NULL) */
size_t ctypepos; /* content type index */
char *xcode; /* content xfer encoding (or NULL) */
struct kpair *next; /* next in map entry */
enum kpairstate state; /* parse state */
enum kpairtype type; /* if parsed, the parse type */
union parsed {
int64_t i; /* validated integer */
const char *s; /* validated string */
double d; /* validated decimal */
} parsed;
};
struct kreq; /* forward declaration */
struct kfcgi;
struct kvalid {
int (*valid)(struct kpair *kp);
const char *name;
};
enum kauth {
KAUTH_NONE = 0,
KAUTH_BASIC,
KAUTH_DIGEST,
KAUTH_BEARER,
KAUTH_UNKNOWN
};
enum khttpalg {
KHTTPALG_MD5 = 0,
KHTTPALG_MD5_SESS,
KHTTPALG__MAX
};
enum khttpqop {
KHTTPQOP_NONE = 0,
KHTTPQOP_AUTH,
KHTTPQOP_AUTH_INT,
KHTTPQOP__MAX
};
struct khttpdigest {
enum khttpalg alg;
enum khttpqop qop;
char *user;
char *uri;
char *realm;
char *nonce;
char *cnonce;
char *response;
uint32_t count;
char *opaque;
};
struct khttpbasic {
char *response;
};
struct khttpauth {
enum kauth type;
int authorised;
char *digest;
union {
struct khttpdigest digest;
struct khttpbasic basic;
} d;
};
struct kdata;
struct khead {
char *key;
char *val;
};
struct kreq {
struct khead *reqmap[KREQU__MAX];
struct khead *reqs;
size_t reqsz;
enum kmethod method;
enum kauth auth;
struct khttpauth rawauth;
struct kpair *cookies;
size_t cookiesz;
struct kpair **cookiemap;
struct kpair **cookienmap;
struct kpair *fields;
struct kpair **fieldmap;
struct kpair **fieldnmap;
size_t fieldsz;
size_t mime;
size_t page;
enum kscheme scheme;
char *path;
char *suffix;
char *fullpath;
char *pagename;
char *remote;
char *host;
uint16_t port;
struct kdata *kdata;
const struct kvalid *keys;
size_t keysz;
char *pname;
void *arg;
};
struct kopts {
ssize_t sndbufsz;
};
struct kcgi_buf {
char *buf; /* buffer contents */
size_t maxsz; /* buffer size (allocated) */
size_t sz; /* buffer current length */
size_t growsz; /* amount to grow (0 == default) */
};
struct ktemplate {
const char *const *key;
size_t keysz;
void *arg;
int (*cb)(size_t, void *);
};
enum kcgi_err {
KCGI_OK = 0,
/* ENOMEM (fork, malloc, etc.). */
KCGI_ENOMEM,
/* FastCGI request to exit. */
KCGI_EXIT,
/* FastCGI connection has closed. */
KCGI_HUP,
/* ENFILE or EMFILE (fd ops). */
KCGI_ENFILE,
/* EAGAIN (fork). */
KCGI_EAGAIN,
/* Internal system error (malformed data). */
KCGI_FORM,
/* Opaque operating-system error. */
KCGI_SYSTEM,
/* Writer error. */
KCGI_WRITER
};
typedef enum kcgi_err (*ktemplate_writef)(const char *, size_t, void *);
struct ktemplatex {
ktemplate_writef writer;
int (*fbk)(const char *, size_t, void *);
};
__BEGIN_DECLS
const char *kcgi_strerror(enum kcgi_err);
enum kcgi_err khttp_body(struct kreq *);
enum kcgi_err khttp_body_compress(struct kreq *, int);
void khttp_free(struct kreq *);
void khttp_child_free(struct kreq *);
enum kcgi_err khttp_head(struct kreq *, const char *,
const char *, ...)
__attribute__((format(printf, 3, 4)));
enum kcgi_err khttp_parse(struct kreq *,
const struct kvalid *, size_t,
const char *const *, size_t, size_t);
enum kcgi_err khttp_parsex(struct kreq *, const struct kmimemap *,
const char *const *, size_t,
const struct kvalid *, size_t,
const char *const *, size_t,
size_t, size_t, void *, void (*)(void *),
unsigned int, const struct kopts *);
enum kcgi_err khttp_printf(struct kreq *, const char *, ...)
__attribute__((format(printf, 2, 3)));
enum kcgi_err khttp_putc(struct kreq *, int);
enum kcgi_err khttp_puts(struct kreq *, const char *);
enum kcgi_err khttp_template(struct kreq *,
const struct ktemplate *, const char *);
enum kcgi_err khttp_template_fd(struct kreq *,
const struct ktemplate *, int, const char *);
enum kcgi_err khttp_template_buf(struct kreq *,
const struct ktemplate *, const char *,
size_t);
enum kcgi_err khttp_templatex(const struct ktemplate *,
const char *, const struct ktemplatex *,
void *);
enum kcgi_err khttp_templatex_buf(const struct ktemplate *,
const char *, size_t,
const struct ktemplatex *, void *);
enum kcgi_err khttp_templatex_fd(const struct ktemplate *,
int, const char *,
const struct ktemplatex *, void *);
enum kcgi_err khttp_write(struct kreq *, const char *, size_t);
enum kcgi_err kcgi_buf_printf(struct kcgi_buf *, const char *, ...)
__attribute__((format(printf, 2, 3)));
enum kcgi_err kcgi_buf_putc(struct kcgi_buf *, char);
enum kcgi_err kcgi_buf_puts(struct kcgi_buf *, const char *);
enum kcgi_err kcgi_buf_write(const char *, size_t, void *);
int khttpdigest_validate(const struct kreq *,
const char *);
int khttpdigest_validatehash(const struct kreq *,
const char *);
int khttpbasic_validate(const struct kreq *,
const char *, const char *);
int kvalid_bit(struct kpair *);
int kvalid_date(struct kpair *);
int kvalid_double(struct kpair *);
int kvalid_email(struct kpair *);
int kvalid_int(struct kpair *);
int kvalid_string(struct kpair *);
int kvalid_stringne(struct kpair *);
int kvalid_udouble(struct kpair *);
int kvalid_uint(struct kpair *);
void kcgi_writer_disable(struct kreq *);
enum kcgi_err khttp_fcgi_parse(struct kfcgi *, struct kreq *);
enum kcgi_err khttp_fcgi_init(struct kfcgi **,
const struct kvalid *, size_t,
const char *const *, size_t, size_t);
enum kcgi_err khttp_fcgi_initx(struct kfcgi **,
const char *const *, size_t,
const struct kvalid *, size_t,
const struct kmimemap *, size_t,
const char *const *, size_t, size_t,
void *, void (*)(void *), unsigned int,
const struct kopts *);
enum kcgi_err khttp_fcgi_free(struct kfcgi *);
void khttp_fcgi_child_free(struct kfcgi *);
int khttp_fcgi_test(void);
void khttp_epoch2datetime(int64_t, int64_t *, int64_t *,
int64_t *, int64_t *, int64_t *, int64_t *,
int64_t *, int64_t *);
char *khttp_epoch2str(int64_t, char *, size_t);
char *khttp_epoch2ustr(int64_t, char *, size_t);
int khttp_epoch2tms(int64_t, int *, int *, int *,
int *, int *, int *, int *, int *);
#define KHTTP_EPOCH2TM(_tt, _tm) \
khttp_epoch2tms((_tt), \
&(_tm)->tm_sec, \
&(_tm)->tm_min, \
&(_tm)->tm_hour, \
&(_tm)->tm_mday, \
&(_tm)->tm_mon, \
&(_tm)->tm_year, \
&(_tm)->tm_wday, \
&(_tm)->tm_yday)
int khttp_datetime2epoch(int64_t *, int64_t, int64_t,
int64_t, int64_t, int64_t, int64_t);
int khttp_date2epoch(int64_t *, int64_t, int64_t,
int64_t);
char *khttp_urlabs(enum kscheme, const char *,
uint16_t, const char *, ...);
enum kcgi_err khttp_urldecode(const char *, char **);
enum kcgi_err khttp_urldecode_inplace(char *);
char *khttp_urlencode(const char *);
char *khttp_urlpart(const char *,
const char *, const char *, ...);
char *khttp_urlpartx(const char *,
const char *, const char *, ...);
char *khttp_vurlabs(enum kscheme, const char *,
uint16_t, const char *, va_list);
char *khttp_vurlpart(const char *,
const char *, const char *, va_list);
char *khttp_vurlpartx(const char *,
const char *, const char *, va_list);
void kutil_invalidate(struct kreq *, struct kpair *);
int kutil_openlog(const char *);
void kutil_verr(const struct kreq *,
const char *, const char *, va_list)
__attribute__((format(printf, 3, 0)))
__attribute__((__noreturn__));
void kutil_verrx(const struct kreq *,
const char *, const char *, va_list)
__attribute__((format(printf, 3, 0)))
__attribute__((__noreturn__));
void kutil_vinfo(const struct kreq *,
const char *, const char *, va_list)
__attribute__((format(printf, 3, 0)));
void kutil_vlog(const struct kreq *, const char *,
const char *, const char *, va_list)
__attribute__((format(printf, 4, 0)));
void kutil_vlogx(const struct kreq *, const char *,
const char *, const char *, va_list)
__attribute__((format(printf, 4, 0)));
void kutil_vwarn(const struct kreq *,
const char *, const char *, va_list)
__attribute__((format(printf, 3, 0)));
void kutil_vwarnx(const struct kreq *,
const char *, const char *, va_list)
__attribute__((format(printf, 3, 0)));
void kutil_log(const struct kreq *, const char *,
const char *, const char *, ...)
__attribute__((format(printf, 4, 5)));
void kutil_logx(const struct kreq *, const char *,
const char *, const char *, ...)
__attribute__((format(printf, 4, 5)));
void kutil_info(const struct kreq *,
const char *, const char *, ...)
__attribute__((format(printf, 3, 4)));
void kutil_warn(const struct kreq *,
const char *, const char *, ...)
__attribute__((format(printf, 3, 4)));
void kutil_warnx(const struct kreq *,
const char *, const char *, ...)
__attribute__((format(printf, 3, 4)));
void kutil_err(const struct kreq *,
const char *, const char *, ...)
__attribute__((format(printf, 3, 4)))
__attribute__((__noreturn__));
void kutil_errx(const struct kreq *,
const char *, const char *, ...)
__attribute__((format(printf, 3, 4)))
__attribute__((__noreturn__));
int kasprintf(char **, const char *, ...)
__attribute__((format(printf, 2, 3)));
int kvasprintf(char **, const char *, va_list)
__attribute__((format(printf, 2, 0)));
void *kcalloc(size_t, size_t);
void *kmalloc(size_t);
void *krealloc(void *, size_t);
void *kreallocarray(void *, size_t, size_t);
char *kstrdup(const char *);
extern const char *const kmimetypes[KMIME__MAX];
extern const char *const khttps[KHTTP__MAX];
extern const char *const kschemes[KSCHEME__MAX];
extern const char *const kresps[KRESP__MAX];
extern const char *const kmethods[KMETHOD__MAX];
extern const struct kmimemap ksuffixmap[];
extern const char *const ksuffixes[KMIME__MAX];
/* DEPRECATED FUNCTIONS AND MACROS. */
#define KUTIL_EPOCH2TM(_tt, _tm) \
kutil_epoch2tmvals((_tt), \
&(_tm)->tm_sec, \
&(_tm)->tm_min, \
&(_tm)->tm_hour, \
&(_tm)->tm_mday, \
&(_tm)->tm_mon, \
&(_tm)->tm_year, \
&(_tm)->tm_wday, \
&(_tm)->tm_yday)
void kutil_epoch2tmvals(int64_t, int *, int *, int *,
int *, int *, int *, int *, int *)
__attribute__((deprecated));
char *kutil_epoch2str(int64_t, char *, size_t)
__attribute__((deprecated));
char *kutil_epoch2utcstr(int64_t, char *, size_t)
__attribute__((deprecated));
int64_t kutil_date2epoch(int64_t, int64_t, int64_t)
__attribute__((deprecated));
int kutil_date_check(int64_t, int64_t, int64_t)
__attribute__((deprecated));
int64_t kutil_datetime2epoch(int64_t, int64_t, int64_t,
int64_t, int64_t, int64_t)
__attribute__((deprecated));
int kutil_datetime_check(int64_t, int64_t, int64_t,
int64_t, int64_t, int64_t)
__attribute__((deprecated));
char *kutil_urlabs(enum kscheme, const char *,
uint16_t, const char *)
__attribute__((deprecated));
enum kcgi_err kutil_urldecode(const char *, char **)
__attribute__((deprecated));
enum kcgi_err kutil_urldecode_inplace(char *)
__attribute__((deprecated));
char *kutil_urlencode(const char *)
__attribute__((deprecated));
char *kutil_urlpart(struct kreq *, const char *,
const char *, const char *, ...)
__attribute__((deprecated));
char *kutil_urlpartx(struct kreq *, const char *,
const char *, const char *, ...)
__attribute__((deprecated));
__END_DECLS
#endif /*!KCGI_H*/