1 /*
    2  * WARNING: automatically generated by kwebapp 0.6.5.
    3  * DO NOT EDIT!
    4  */
    5 #include <sys/queue.h>
    6 
    7 #include <assert.h>
    8 /*
    9  * Required for b64_ntop().
   10  */
   11 #include <netinet/in.h>
   12 #include <resolv.h>
   13 #include <ctype.h>
   14 #include <inttypes.h>
   15 #include <stdarg.h>
   16 #include <stdint.h>
   17 #include <stdio.h>
   18 #include <stdlib.h>
   19 #include <string.h>
   20 #include <time.h>
   21 #include <unistd.h>
   22 
   23 #include <ksql.h>
   24 #include <kcgi.h>
   25 #include <kcgijson.h>
   26 
   27 #include "db.h"
   28 
   29 /*
   30  * File imported from /usr/local/share/kwebapp/jsmn.c.
   31  */
   32 /* 
   33  * https://github.com/zserge/jsmn
   34  * Current as of 26-09-2018.
   35  */
   36 /**
   37  * Copyright (c) 2010 Serge A. Zaitsev
   38  *
   39  * Permission is hereby granted, free of charge, to any person obtaining a copy
   40  * of this software and associated documentation files (the "Software"), to deal
   41  * in the Software without restriction, including without limitation the rights
   42  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   43  * copies of the Software, and to permit persons to whom the Software is
   44  * furnished to do so, subject to the following conditions:
   45  * 
   46  * The above copyright notice and this permission notice shall be included in
   47  * all copies or substantial portions of the Software.
   48  * 
   49  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   50  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   51  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   52  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   53  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   54  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   55  * THE SOFTWARE.
   56  */
   57 
   58 /**
   59  * Allocates a fresh unused token from the token pull.
   60  */
   61 static jsmntok_t *
   62 jsmn_alloc_token(jsmn_parser *parser, 
   63 	jsmntok_t *tokens, size_t num_tokens) 
   64 {
   65 	jsmntok_t *tok;
   66 	if (parser->toknext >= num_tokens) {
   67 		return NULL;
   68 	}
   69 	tok = &tokens[parser->toknext++];
   70 	tok->start = tok->end = -1;
   71 	tok->size = 0;
   72 	return tok;
   73 }
   74 
   75 /**
   76  * Fills token type and boundaries.
   77  */
   78 static void 
   79 jsmn_fill_token(jsmntok_t *token, jsmntype_t type, int start, int end) 
   80 {
   81 	token->type = type;
   82 	token->start = start;
   83 	token->end = end;
   84 	token->size = 0;
   85 }
   86 
   87 /**
   88  * Fills next available token with JSON primitive.
   89  */
   90 static int 
   91 jsmn_parse_primitive(jsmn_parser *parser, const char *js,
   92 	size_t len, jsmntok_t *tokens, size_t num_tokens) 
   93 {
   94 	jsmntok_t *token;
   95 	int start;
   96 
   97 	start = parser->pos;
   98 
   99 	for (; parser->pos < len && js[parser->pos] != '\0'; 
  100 	     parser->pos++) {
  101 		switch (js[parser->pos]) {
  102 		/* In strict mode primitive must be followed by "," or
  103 		 * "}" or "]" */
  104 		case ':':
  105 		case '\t' : case '\r' : case '\n' : case ' ' :
  106 		case ','  : case ']'  : case '}' :
  107 			goto found;
  108 		}
  109 		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
  110 			parser->pos = start;
  111 			return JSMN_ERROR_INVAL;
  112 		}
  113 	}
  114 found:
  115 	if (tokens == NULL) {
  116 		parser->pos--;
  117 		return 0;
  118 	}
  119 	token = jsmn_alloc_token(parser, tokens, num_tokens);
  120 	if (token == NULL) {
  121 		parser->pos = start;
  122 		return JSMN_ERROR_NOMEM;
  123 	}
  124 	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
  125 	parser->pos--;
  126 	return 0;
  127 }
  128 
  129 /**
  130  * Fills next token with JSON string.
  131  */
  132 static int 
  133 jsmn_parse_string(jsmn_parser *parser, const char *js,
  134 	size_t len, jsmntok_t *tokens, size_t num_tokens) 
  135 {
  136 	jsmntok_t *token;
  137 
  138 	int start = parser->pos;
  139 
  140 	parser->pos++;
  141 
  142 	/* Skip starting quote */
  143 	for (; parser->pos < len && js[parser->pos] != '\0'; 
  144 	     parser->pos++) {
  145 		char c = js[parser->pos];
  146 
  147 		/* Quote: end of string */
  148 		if (c == '\"') {
  149 			if (tokens == NULL) {
  150 				return 0;
  151 			}
  152 			token = jsmn_alloc_token
  153 				(parser, tokens, num_tokens);
  154 			if (token == NULL) {
  155 				parser->pos = start;
  156 				return JSMN_ERROR_NOMEM;
  157 			}
  158 			jsmn_fill_token
  159 				(token, JSMN_STRING, 
  160 				 start+1, parser->pos);
  161 			return 0;
  162 		}
  163 
  164 		/* Backslash: Quoted symbol expected */
  165 		if (c == '\\' && parser->pos + 1 < len) {
  166 			int i;
  167 			parser->pos++;
  168 			switch (js[parser->pos]) {
  169 			/* Allowed escaped symbols */
  170 			case '\"': case '/' : case '\\' : case 'b' :
  171 			case 'f' : case 'r' : case 'n'  : case 't' :
  172 				break;
  173 			/* Allows escaped symbol \uXXXX */
  174 			case 'u':
  175 				parser->pos++;
  176 				for(i = 0; 
  177 				    i < 4 && parser->pos < len && 
  178 				    js[parser->pos] != '\0'; i++) {
  179 					/* If it isn't a hex character we have an error */
  180 					if(!((js[parser->pos] >= 48 && 
  181 					      js[parser->pos] <= 57) || /* 0-9 */
  182 					   (js[parser->pos] >= 65 && 
  183 					    js[parser->pos] <= 70) || /* A-F */
  184 					   (js[parser->pos] >= 97 && 
  185 					    js[parser->pos] <= 102))) { /* a-f */
  186 						parser->pos = start;
  187 						return JSMN_ERROR_INVAL;
  188 					}
  189 					parser->pos++;
  190 				}
  191 				parser->pos--;
  192 				break;
  193 			/* Unexpected symbol */
  194 			default:
  195 				parser->pos = start;
  196 				return JSMN_ERROR_INVAL;
  197 			}
  198 		}
  199 	}
  200 	parser->pos = start;
  201 	return JSMN_ERROR_PART;
  202 }
  203 
  204 /**
  205  * Parse JSON string and fill tokens.
  206  */
  207 int 
  208 jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
  209 	jsmntok_t *tokens, unsigned int num_tokens) 
  210 {
  211 	int r;
  212 	int i;
  213 	jsmntok_t *token;
  214 	int count = parser->toknext;
  215 
  216 	for (; parser->pos < len && js[parser->pos] != '\0'; 
  217 	     parser->pos++) {
  218 		char c;
  219 		jsmntype_t type;
  220 
  221 		c = js[parser->pos];
  222 		switch (c) {
  223 		case '{': case '[':
  224 			count++;
  225 			if (tokens == NULL) {
  226 				break;
  227 			}
  228 			token = jsmn_alloc_token
  229 				(parser, tokens, num_tokens);
  230 			if (token == NULL)
  231 				return JSMN_ERROR_NOMEM;
  232 			if (parser->toksuper != -1) {
  233 				tokens[parser->toksuper].size++;
  234 			}
  235 			token->type = (c == '{' ? 
  236 				JSMN_OBJECT : JSMN_ARRAY);
  237 			token->start = parser->pos;
  238 			parser->toksuper = parser->toknext - 1;
  239 			break;
  240 		case '}': case ']':
  241 			if (tokens == NULL)
  242 				break;
  243 			type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
  244 			for (i = parser->toknext - 1; i >= 0; i--) {
  245 				token = &tokens[i];
  246 				if (token->start != -1 && 
  247 				    token->end == -1) {
  248 					if (token->type != type) {
  249 						return JSMN_ERROR_INVAL;
  250 					}
  251 					parser->toksuper = -1;
  252 					token->end = parser->pos + 1;
  253 					break;
  254 				}
  255 			}
  256 			/* Error if unmatched closing bracket */
  257 			if (i == -1) 
  258 				return JSMN_ERROR_INVAL;
  259 			for (; i >= 0; i--) {
  260 				token = &tokens[i];
  261 				if (token->start != -1 && 
  262 				    token->end == -1) {
  263 					parser->toksuper = i;
  264 					break;
  265 				}
  266 			}
  267 			break;
  268 		case '\"':
  269 			r = jsmn_parse_string
  270 				(parser, js, len, tokens, num_tokens);
  271 			if (r < 0) 
  272 				return r;
  273 			count++;
  274 			if (parser->toksuper != -1 && tokens != NULL)
  275 				tokens[parser->toksuper].size++;
  276 			break;
  277 		case '\t' : case '\r' : case '\n' : case ' ':
  278 			break;
  279 		case ':':
  280 			parser->toksuper = parser->toknext - 1;
  281 			break;
  282 		case ',':
  283 			if (tokens != NULL && parser->toksuper != -1 &&
  284 			    tokens[parser->toksuper].type != JSMN_ARRAY &&
  285 			    tokens[parser->toksuper].type != JSMN_OBJECT) {
  286 				for (i = parser->toknext - 1; i >= 0; i--) {
  287 					if (tokens[i].type == JSMN_ARRAY || 
  288 					    tokens[i].type == JSMN_OBJECT) {
  289 						if (tokens[i].start != -1 && 
  290 						    tokens[i].end == -1) {
  291 							parser->toksuper = i;
  292 							break;
  293 						}
  294 					}
  295 				}
  296 			}
  297 			break;
  298 		/* In non-strict mode every unquoted value is a primitive */
  299 		default:
  300 			r = jsmn_parse_primitive
  301 				(parser, js, len, tokens, num_tokens);
  302 			if (r < 0) return r;
  303 			count++;
  304 			if (parser->toksuper != -1 && tokens != NULL)
  305 				tokens[parser->toksuper].size++;
  306 			break;
  307 		}
  308 	}
  309 
  310 	if (tokens != NULL) {
  311 		for (i = parser->toknext - 1; i >= 0; i--) {
  312 			/* Unmatched opened object or array */
  313 			if (tokens[i].start != -1 && tokens[i].end == -1) {
  314 				return JSMN_ERROR_PART;
  315 			}
  316 		}
  317 	}
  318 
  319 	return count;
  320 }
  321 
  322 /**
  323  * Creates a new parser based over a given  buffer with an array of tokens
  324  * available.
  325  */
  326 void 
  327 jsmn_init(jsmn_parser *parser) 
  328 {
  329 	parser->pos = 0;
  330 	parser->toknext = 0;
  331 	parser->toksuper = -1;
  332 }
  333 
  334 /*
  335  * The remainder here are written for kwebapp.
  336  */
  337 
  338 int 
  339 jsmn_eq(const char *json, const jsmntok_t *tok, const char *s) 
  340 {
  341 	if (tok->type == JSMN_STRING && 
  342 	    (int)strlen(s) == tok->end - tok->start &&
  343 	    strncmp(json + tok->start, s, tok->end - tok->start) == 0) 
  344 		return 1;
  345 	return 0;
  346 }
  347 
  348 static int
  349 jsmn_parse_real(const char *buf, size_t sz, double *ret)
  350 {
  351 	char 	 tmp[128];
  352 	int	 rc;
  353 
  354 	if (sz > sizeof(tmp) - 1)
  355 		return 0;
  356 
  357 	memcpy(tmp, buf, sz);
  358 	tmp[sz] = '\0';
  359 
  360 	if ((rc = sscanf(tmp, "%lf", ret)) < 0)
  361 		return -1;
  362 
  363 	return 1 == rc;
  364 }
  365 
  366 static int
  367 jsmn_parse_int(const char *buf, size_t sz, int64_t *ret)
  368 {
  369 	char 	 tmp[32];
  370 	int	 rc;
  371 
  372 	if (sz > sizeof(tmp) - 1)
  373 		return 0;
  374 
  375 	memcpy(tmp, buf, sz);
  376 	tmp[sz] = '\0';
  377 
  378 	if ((rc = sscanf(tmp, "%" SCNd64, ret)) < 0)
  379 		return -1;
  380 
  381 	return 1 == rc;
  382 }
  383 /*
  384  * All SQL statements we'll later define in "stmts".
  385  */
  386 enum	stmt {
  387 	STMT_COMPANY_BY_UNIQUE_id,
  388 	STMT_COMPANY_BY_SEARCH_0,
  389 	STMT_COMPANY_INSERT,
  390 	STMT_USER_BY_UNIQUE_email,
  391 	STMT_USER_BY_UNIQUE_uid,
  392 	STMT_USER_BY_SEARCH_0,
  393 	STMT_USER_BY_SEARCH_1,
  394 	STMT_USER_BY_SEARCH_2,
  395 	STMT_USER_INSERT,
  396 	STMT_USER_UPDATE_0,
  397 	STMT_USER_UPDATE_1,
  398 	STMT_SESSION_BY_UNIQUE_id,
  399 	STMT_SESSION_BY_SEARCH_0,
  400 	STMT_SESSION_INSERT,
  401 	STMT_SESSION_DELETE_0,
  402 	STMT__MAX
  403 };
  404 
  405 /*
  406  * Our full set of SQL statements.
  407  * We define these beforehand because that's how ksql(3) handles 
  408  * statement generation.
  409  * Notice the "AS" part: this allows for multiple inner joins without 
  410  * ambiguity.
  411  */
  412 static	const char *const stmts[STMT__MAX] = {
  413 	/* STMT_COMPANY_BY_UNIQUE_id */
  414 	"SELECT " DB_SCHEMA_COMPANY(company) " FROM company WHERE company.id = ?",
  415 	/* STMT_COMPANY_BY_SEARCH_0 */
  416 	"SELECT " DB_SCHEMA_COMPANY(company) " FROM company "
  417 		"WHERE company.somenum ISNULL",
  418 	/* STMT_COMPANY_INSERT */
  419 	"INSERT INTO company (name,somenum) VALUES (?,?)",
  420 	/* STMT_USER_BY_UNIQUE_email */
  421 	"SELECT " DB_SCHEMA_USER(user) "," DB_SCHEMA_COMPANY(_a) " FROM user "
  422 		"INNER JOIN company AS _a ON _a.id=user.cid "
  423 		"WHERE user.email = ?",
  424 	/* STMT_USER_BY_UNIQUE_uid */
  425 	"SELECT " DB_SCHEMA_USER(user) "," DB_SCHEMA_COMPANY(_a) " FROM user "
  426 		"INNER JOIN company AS _a ON _a.id=user.cid "
  427 		"WHERE user.uid = ?",
  428 	/* STMT_USER_BY_SEARCH_0 */
  429 	"SELECT " DB_SCHEMA_USER(user) "," DB_SCHEMA_COMPANY(_a) " FROM user "
  430 		"INNER JOIN company AS _a ON _a.id=user.cid "
  431 		"WHERE user.name = ? LIMIT 5",
  432 	/* STMT_USER_BY_SEARCH_1 */
  433 	"SELECT " DB_SCHEMA_USER(user) "," DB_SCHEMA_COMPANY(_a) " FROM user "
  434 		"INNER JOIN company AS _a ON _a.id=user.cid "
  435 		"WHERE user.email = ?",
  436 	/* STMT_USER_BY_SEARCH_2 */
  437 	"SELECT " DB_SCHEMA_USER(user) "," DB_SCHEMA_COMPANY(_a) " FROM user "
  438 		"INNER JOIN company AS _a ON _a.id=user.cid "
  439 		"WHERE user.uid = ? ORDER BY _a.name ASC",
  440 	/* STMT_USER_INSERT */
  441 	"INSERT INTO user (cid,sex,hash,email,image,name) VALUES (?,?,?,?,?,?)",
  442 	/* STMT_USER_UPDATE_0 */
  443 	"UPDATE user SET hash = ? WHERE uid = ?",
  444 	/* STMT_USER_UPDATE_1 */
  445 	"UPDATE user SET email = ? WHERE uid = ?",
  446 	/* STMT_SESSION_BY_UNIQUE_id */
  447 	"SELECT " DB_SCHEMA_SESSION(session) "," DB_SCHEMA_USER(_b) "," DB_SCHEMA_COMPANY(_c) " FROM session "
  448 		"INNER JOIN user AS _b ON _b.uid=session.userid "
  449 		"INNER JOIN company AS _c ON _c.id=_b.cid "
  450 		"WHERE session.id = ?",
  451 	/* STMT_SESSION_BY_SEARCH_0 */
  452 	"SELECT " DB_SCHEMA_SESSION(session) "," DB_SCHEMA_USER(_b) "," DB_SCHEMA_COMPANY(_c) " FROM session "
  453 		"INNER JOIN user AS _b ON _b.uid=session.userid "
  454 		"INNER JOIN company AS _c ON _c.id=_b.cid "
  455 		"WHERE _c.name = ? AND session.mtime = ?",
  456 	/* STMT_SESSION_INSERT */
  457 	"INSERT INTO session (userid,token,mtime) VALUES (?,?,?)",
  458 	/* STMT_SESSION_DELETE_0 */
  459 	"DELETE FROM session WHERE id = ?",
  460 };
  461 
  462 const struct kvalid valid_keys[VALID__MAX] = {
  463 	{ valid_company_name, "company-name" },
  464 	{ valid_company_id, "company-id" },
  465 	{ valid_company_somenum, "company-somenum" },
  466 	{ valid_user_cid, "user-cid" },
  467 	{ valid_user_sex, "user-sex" },
  468 	{ valid_user_hash, "user-hash" },
  469 	{ valid_user_email, "user-email" },
  470 	{ valid_user_image, "user-image" },
  471 	{ valid_user_name, "user-name" },
  472 	{ valid_user_uid, "user-uid" },
  473 	{ valid_session_userid, "session-userid" },
  474 	{ valid_session_token, "session-token" },
  475 	{ valid_session_mtime, "session-mtime" },
  476 	{ valid_session_id, "session-id" },
  477 };
  478 
  479 /*
  480  * Finally, all of the functions we'll use.
  481  */
  482 
  483 void
  484 db_trans_open(struct ksql *p, size_t id, int mode)
  485 {
  486 	if (mode < 0)
  487 		ksql_trans_exclopen(p, id);
  488 	else if (mode > 0)
  489 		ksql_trans_singleopen(p, id);
  490 	else
  491 		ksql_trans_open(p, id);
  492 }
  493 
  494 void
  495 db_trans_rollback(struct ksql *p, size_t id)
  496 {
  497 	ksql_trans_rollback(p, id);
  498 }
  499 
  500 void
  501 db_trans_commit(struct ksql *p, size_t id)
  502 {
  503 	ksql_trans_commit(p, id);
  504 }
  505 
  506 struct ksql *
  507 db_open(const char *file)
  508 {
  509 	struct ksqlcfg cfg;
  510 	struct ksql *db;
  511 
  512 	ksql_cfg_defaults(&cfg);
  513 	cfg.flags |= KSQL_FOREIGN_KEYS;
  514 
  515 	db = ksql_alloc_child(&cfg, NULL, NULL);
  516 	if (NULL == db)
  517 		return(NULL);
  518 	ksql_open(db, file);
  519 	return(db);
  520 }
  521 
  522 void
  523 db_close(struct ksql *p)
  524 {
  525 	if (NULL == p)
  526 		return;
  527 	ksql_close(p);
  528 	ksql_free(p);
  529 }
  530 
  531 void
  532 db_company_fill(struct company *p, struct ksqlstmt *stmt, size_t *pos)
  533 {
  534 	size_t i = 0;
  535 	enum ksqlc c;
  536 
  537 	if (NULL == pos)
  538 		pos = &i;
  539 	memset(p, 0, sizeof(*p));
  540 	c = ksql_result_str_alloc(stmt, &p->name, (*pos)++);
  541 	if (KSQL_OK != c)
  542 		exit(EXIT_FAILURE);
  543 	c = ksql_result_int(stmt, &p->id, (*pos)++);
  544 	if (KSQL_OK != c)
  545 		exit(EXIT_FAILURE);
  546 	p->has_somenum = ! ksql_stmt_isnull(stmt, *pos);
  547 	if (p->has_somenum) {
  548 		c = ksql_result_int(stmt, &p->somenum, (*pos)++);
  549 		if (KSQL_OK != c)
  550 			exit(EXIT_FAILURE);
  551 	} else
  552 		(*pos)++;
  553 }
  554 
  555 static void
  556 db_company_fill_r(struct company *p, struct ksqlstmt *stmt, size_t *pos)
  557 {
  558 	size_t i = 0;
  559 
  560 	if (NULL == pos)
  561 		pos = &i;
  562 	db_company_fill(p, stmt, pos);
  563 }
  564 
  565 void
  566 db_company_unfill(struct company *p)
  567 {
  568 	if (NULL == p)
  569 		return;
  570 	free(p->name);
  571 }
  572 
  573 static void
  574 db_company_unfill_r(struct company *p)
  575 {
  576 	if (NULL == p)
  577 		return;
  578 
  579 	db_company_unfill(p);
  580 }
  581 
  582 void
  583 db_company_free(struct company *p)
  584 {
  585 	db_company_unfill_r(p);
  586 	free(p);
  587 }
  588 
  589 void
  590 db_company_freeq(struct company_q *q)
  591 {
  592 	struct company *p;
  593 
  594 	if (NULL == q)
  595 		return;
  596 	while (NULL != (p = TAILQ_FIRST(q))) {
  597 		TAILQ_REMOVE(q, p, _entries);
  598 		db_company_free(p);
  599 	}
  600 
  601 	free(q);
  602 }
  603 
  604 int64_t
  605 db_company_insert(struct ksql *db, const char *v1, int64_t *v2)
  606 {
  607 	struct ksqlstmt *stmt;
  608 	int64_t id = -1;
  609 
  610 	ksql_stmt_alloc(db, &stmt,
  611 		stmts[STMT_COMPANY_INSERT],
  612 		STMT_COMPANY_INSERT);
  613 	ksql_bind_str(stmt, 0, v1);
  614 	if (NULL == v2)
  615 		ksql_bind_null(stmt, 1);
  616 	else
  617 		ksql_bind_int(stmt, 1, *v2);
  618 	if (KSQL_DONE == ksql_stmt_cstep(stmt))
  619 		ksql_lastid(db, &id);
  620 	ksql_stmt_free(stmt);
  621 	return(id);
  622 }
  623 
  624 void
  625 json_company_data(struct kjsonreq *r, const struct company *p)
  626 {
  627 	kjson_putstringp(r, "name", p->name);
  628 	kjson_putintp(r, "id", p->id);
  629 
  630 	if ( ! p->has_somenum)
  631 		kjson_putnullp(r, "somenum");
  632 	else
  633 		kjson_putintp(r, "somenum", p->somenum);
  634 
  635 }
  636 
  637 void
  638 json_company_obj(struct kjsonreq *r, const struct company *p)
  639 {
  640 	kjson_objp_open(r, "company");
  641 	json_company_data(r, p);
  642 	kjson_obj_close(r);
  643 }
  644 
  645 void
  646 json_company_array(struct kjsonreq *r, const struct company_q *q)
  647 {
  648 	struct company *p;
  649 
  650 	kjson_arrayp_open(r, "company_q");
  651 	TAILQ_FOREACH(p, q, _entries) {
  652 		kjson_obj_open(r);
  653 		json_company_data(r, p);
  654 		kjson_obj_close(r);
  655 	}
  656 	kjson_array_close(r);
  657 }
  658 
  659 int
  660 jsmn_company(struct company *p, const char *buf, const jsmntok_t *t, size_t toksz)
  661 {
  662 	int i;
  663 	size_t j;
  664 
  665 	if (toksz < 1 || t[0].type != JSMN_OBJECT)
  666 		return 0;
  667 
  668 	for (i = 0, j = 0; i < t[0].size; i++) {
  669 		if (jsmn_eq(buf, &t[j+1], "name")) {
  670 			j++;
  671 			if (t[j+1].type != JSMN_STRING)
  672 				return 0;
  673 			p->name = strndup
  674 				(buf + t[j+1].start,
  675 				 t[j+1].end - t[j+1].start);
  676 			if (NULL == p->name)
  677 				return -1;
  678 			j++;
  679 			continue;
  680 		}
  681 		if (jsmn_eq(buf, &t[j+1], "id")) {
  682 			j++;
  683 			if (t[j+1].type != JSMN_PRIMITIVE ||
  684 			    ('-' != buf[t[j+1].start] &&
  685 			    ! isdigit((unsigned int)buf[t[j+1].start])))
  686 				return 0;
  687 			if ( ! jsmn_parse_int(buf + t[j+1].start,
  688 			    t[j+1].end - t[j+1].start, &p->id))
  689 				return 0;
  690 			j++;
  691 			continue;
  692 		}
  693 		if (jsmn_eq(buf, &t[j+1], "somenum")) {
  694 			j++;
  695 			if (t[j+1].type == JSMN_PRIMITIVE &&
  696 			    'n' == buf[t[j+1].start]) {
  697 				p->has_somenum = 0;
  698 				j++;
  699 				continue;
  700 			} else
  701 				p->has_somenum = 1;
  702 			if (t[j+1].type != JSMN_PRIMITIVE ||
  703 			    ('-' != buf[t[j+1].start] &&
  704 			    ! isdigit((unsigned int)buf[t[j+1].start])))
  705 				return 0;
  706 			if ( ! jsmn_parse_int(buf + t[j+1].start,
  707 			    t[j+1].end - t[j+1].start, &p->somenum))
  708 				return 0;
  709 			j++;
  710 			continue;
  711 		}
  712 
  713 		/* Anything else is unexpected. */
  714 
  715 		return 0;
  716 	}
  717 	return j+1;
  718 }
  719 
  720 void
  721 jsmn_company_clear(struct company *p)
  722 
  723 {
  724 	if (NULL == p)
  725 		return;
  726 	free(p->name);
  727 }
  728 
  729 void
  730 jsmn_company_free_array(struct company *p, size_t sz)
  731 {
  732 	size_t i;
  733 	for (i = 0; i < sz; i++)
  734 		jsmn_company_clear(&p[i]);
  735 	free(p);
  736 }
  737 
  738 int
  739 jsmn_company_array(struct company **p, size_t *sz, const char *buf, const jsmntok_t *t, size_t toksz)
  740 {
  741 	size_t i, j;
  742 	int rc;
  743 
  744 	*sz = 0;
  745 	*p = NULL;
  746 
  747 	if (toksz < 1 || t[0].type != JSMN_ARRAY)
  748 		return 0;
  749 
  750 	*sz = t[0].size;
  751 	if (NULL == (*p = calloc(*sz, sizeof(struct company))))
  752 		return -1;
  753 
  754 	for (i = j = 0; i < *sz; i++) {
  755 		rc = jsmn_company(&(*p)[i], buf, &t[j+1], toksz - j);
  756 		if (rc <= 0)
  757 			return rc;
  758 		j += rc;
  759 	}
  760 	return j + 1;
  761 }
  762 
  763 int
  764 valid_company_name(struct kpair *p)
  765 {
  766 	if ( ! kvalid_string(p))
  767 		return 0;
  768 	if (p->valsz <= 0)
  769 		return 0;
  770 	return 1;
  771 }
  772 
  773 int
  774 valid_company_id(struct kpair *p)
  775 {
  776 	if ( ! kvalid_int(p))
  777 		return 0;
  778 	return 1;
  779 }
  780 
  781 int
  782 valid_company_somenum(struct kpair *p)
  783 {
  784 	if ( ! kvalid_int(p))
  785 		return 0;
  786 	return 1;
  787 }
  788 
  789 struct company_q *
  790 db_company_list_by_somenum_isnull(struct ksql *db)
  791 {
  792 	struct ksqlstmt *stmt;
  793 	struct company_q *q;
  794 	struct company *p;
  795 
  796 	q = malloc(sizeof(struct company_q));
  797 	if (NULL == q) {
  798 		perror(NULL);
  799 		exit(EXIT_FAILURE);
  800 	}
  801 	TAILQ_INIT(q);
  802 
  803 	ksql_stmt_alloc(db, &stmt,
  804 		stmts[STMT_COMPANY_BY_SEARCH_0],
  805 		STMT_COMPANY_BY_SEARCH_0);
  806 	while (KSQL_ROW == ksql_stmt_step(stmt)) {
  807 		p = malloc(sizeof(struct company));
  808 		if (NULL == p) {
  809 			perror(NULL);
  810 			exit(EXIT_FAILURE);
  811 		}
  812 		db_company_fill_r(p, stmt, NULL);
  813 		TAILQ_INSERT_TAIL(q, p, _entries);
  814 	}
  815 	ksql_stmt_free(stmt);
  816 	return(q);
  817 }
  818 
  819 void
  820 db_user_fill(struct user *p, struct ksqlstmt *stmt, size_t *pos)
  821 {
  822 	size_t i = 0;
  823 	enum ksqlc c;
  824 	int64_t tmpint;
  825 
  826 	if (NULL == pos)
  827 		pos = &i;
  828 	memset(p, 0, sizeof(*p));
  829 	c = ksql_result_int(stmt, &p->cid, (*pos)++);
  830 	if (KSQL_OK != c)
  831 		exit(EXIT_FAILURE);
  832 	c = ksql_result_int(stmt, &tmpint, (*pos)++);
  833 	if (KSQL_OK != c)
  834 		exit(EXIT_FAILURE);
  835 	p->sex = tmpint;
  836 	c = ksql_result_str_alloc(stmt, &p->hash, (*pos)++);
  837 	if (KSQL_OK != c)
  838 		exit(EXIT_FAILURE);
  839 	c = ksql_result_str_alloc(stmt, &p->email, (*pos)++);
  840 	if (KSQL_OK != c)
  841 		exit(EXIT_FAILURE);
  842 	p->has_image = ! ksql_stmt_isnull(stmt, *pos);
  843 	if (p->has_image) {
  844 		c = ksql_result_blob_alloc(stmt, &p->image, &p->image_sz, (*pos)++);
  845 		if (KSQL_OK != c)
  846 			exit(EXIT_FAILURE);
  847 	} else
  848 		(*pos)++;
  849 	c = ksql_result_str_alloc(stmt, &p->name, (*pos)++);
  850 	if (KSQL_OK != c)
  851 		exit(EXIT_FAILURE);
  852 	c = ksql_result_int(stmt, &p->uid, (*pos)++);
  853 	if (KSQL_OK != c)
  854 		exit(EXIT_FAILURE);
  855 }
  856 
  857 static void
  858 db_user_fill_r(struct user *p, struct ksqlstmt *stmt, size_t *pos)
  859 {
  860 	size_t i = 0;
  861 
  862 	if (NULL == pos)
  863 		pos = &i;
  864 	db_user_fill(p, stmt, pos);
  865 	db_company_fill_r(&p->company, stmt, pos);
  866 }
  867 
  868 void
  869 db_user_unfill(struct user *p)
  870 {
  871 	if (NULL == p)
  872 		return;
  873 	free(p->hash);
  874 	free(p->email);
  875 	free(p->image);
  876 	free(p->name);
  877 }
  878 
  879 static void
  880 db_user_unfill_r(struct user *p)
  881 {
  882 	if (NULL == p)
  883 		return;
  884 
  885 	db_user_unfill(p);
  886 	db_company_unfill_r(&p->company);
  887 }
  888 
  889 void
  890 db_user_free(struct user *p)
  891 {
  892 	db_user_unfill_r(p);
  893 	free(p);
  894 }
  895 
  896 int64_t
  897 db_user_insert(struct ksql *db, int64_t v1, enum sex v2, const char *v3,
  898 	const char *v4, size_t v5_sz, const void **v5, const char *v6)
  899 {
  900 	struct ksqlstmt *stmt;
  901 	int64_t id = -1;
  902 	char hash1[64];
  903 
  904 	crypt_newhash(v3, "blowfish,a", hash1, sizeof(hash1));
  905 
  906 	ksql_stmt_alloc(db, &stmt,
  907 		stmts[STMT_USER_INSERT],
  908 		STMT_USER_INSERT);
  909 	ksql_bind_int(stmt, 0, v1);
  910 	ksql_bind_int(stmt, 1, v2);
  911 	ksql_bind_str(stmt, 2, hash1);
  912 	ksql_bind_str(stmt, 3, v4);
  913 	if (NULL == v5)
  914 		ksql_bind_null(stmt, 4);
  915 	else
  916 		ksql_bind_blob(stmt, 4, *v5, v5_sz);
  917 	ksql_bind_str(stmt, 5, v6);
  918 	if (KSQL_DONE == ksql_stmt_cstep(stmt))
  919 		ksql_lastid(db, &id);
  920 	ksql_stmt_free(stmt);
  921 	return(id);
  922 }
  923 
  924 void
  925 json_user_data(struct kjsonreq *r, const struct user *p)
  926 {
  927 	char *buf1;
  928 	size_t sz;
  929 
  930 	/*
  931 	 * We need to base64 encode the binary buffers prior to 
  932 	 * serialisation.
  933 	 * Allocate space for these buffers and do so now.
  934 	 * We'll free the buffers at the epilogue of the function.
  935 	 */
  936 
  937 	sz = (p->image_sz + 2) / 3 * 4 + 1;
  938 	buf1 = malloc(sz);
  939 	if (NULL == buf1) {
  940 		perror(NULL);
  941 		exit(EXIT_FAILURE);
  942 	}
  943 	if (p->has_image)
  944 		b64_ntop(p->image, p->image_sz, buf1, sz);
  945 
  946 	kjson_objp_open(r, "company");
  947 	json_company_data(r, &p->company);
  948 	kjson_obj_close(r);
  949 	kjson_putintp(r, "cid", p->cid);
  950 	kjson_putintp(r, "sex", p->sex);
  951 
  952 	/* Omitting hash: is a password hash. */
  953 
  954 	kjson_putstringp(r, "email", p->email);
  955 
  956 	if ( ! p->has_image)
  957 		kjson_putnullp(r, "image");
  958 	else
  959 		kjson_putstringp(r, "image", buf1);
  960 
  961 	kjson_putstringp(r, "name", p->name);
  962 	kjson_putintp(r, "uid", p->uid);
  963 
  964 	free(buf1);
  965 }
  966 
  967 void
  968 json_user_obj(struct kjsonreq *r, const struct user *p)
  969 {
  970 	kjson_objp_open(r, "user");
  971 	json_user_data(r, p);
  972 	kjson_obj_close(r);
  973 }
  974 
  975 void
  976 json_user_iterate(const struct user *p, void *arg)
  977 {
  978 	struct kjsonreq *r = arg;
  979 
  980 	kjson_obj_open(r);
  981 	json_user_data(r, p);
  982 	kjson_obj_close(r);
  983 }
  984 
  985 int
  986 jsmn_user(struct user *p, const char *buf, const jsmntok_t *t, size_t toksz)
  987 {
  988 	int i;
  989 	size_t j;
  990 	int64_t tmpint;
  991 	int rc;
  992 	char *tmpbuf;
  993 
  994 	if (toksz < 1 || t[0].type != JSMN_OBJECT)
  995 		return 0;
  996 
  997 	for (i = 0, j = 0; i < t[0].size; i++) {
  998 		if (jsmn_eq(buf, &t[j+1], "company")) {
  999 			j++;
 1000 			if (t[j+1].type != JSMN_OBJECT)
 1001 				return 0;
 1002 			rc = jsmn_company
 1003 				(&p->company, buf,
 1004 				 &t[j+1], toksz - j);
 1005 			if (rc <= 0)
 1006 				return rc;
 1007 			j += rc;
 1008 			continue;
 1009 		}
 1010 		if (jsmn_eq(buf, &t[j+1], "cid")) {
 1011 			j++;
 1012 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1013 			    ('-' != buf[t[j+1].start] &&
 1014 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1015 				return 0;
 1016 			if ( ! jsmn_parse_int(buf + t[j+1].start,
 1017 			    t[j+1].end - t[j+1].start, &p->cid))
 1018 				return 0;
 1019 			j++;
 1020 			continue;
 1021 		}
 1022 		if (jsmn_eq(buf, &t[j+1], "sex")) {
 1023 			j++;
 1024 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1025 			    ('-' != buf[t[j+1].start] &&
 1026 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1027 				return 0;
 1028 			if ( ! jsmn_parse_int(buf + t[j+1].start,
 1029 			    t[j+1].end - t[j+1].start, &tmpint))
 1030 				return 0;
 1031 			p->sex = tmpint;
 1032 			j++;
 1033 			continue;
 1034 		}
 1035 		if (jsmn_eq(buf, &t[j+1], "hash")) {
 1036 			j++;
 1037 			if (t[j+1].type != JSMN_STRING)
 1038 				return 0;
 1039 			p->hash = strndup
 1040 				(buf + t[j+1].start,
 1041 				 t[j+1].end - t[j+1].start);
 1042 			if (NULL == p->hash)
 1043 				return -1;
 1044 			j++;
 1045 			continue;
 1046 		}
 1047 		if (jsmn_eq(buf, &t[j+1], "email")) {
 1048 			j++;
 1049 			if (t[j+1].type != JSMN_STRING)
 1050 				return 0;
 1051 			p->email = strndup
 1052 				(buf + t[j+1].start,
 1053 				 t[j+1].end - t[j+1].start);
 1054 			if (NULL == p->email)
 1055 				return -1;
 1056 			j++;
 1057 			continue;
 1058 		}
 1059 		if (jsmn_eq(buf, &t[j+1], "image")) {
 1060 			j++;
 1061 			if (t[j+1].type == JSMN_PRIMITIVE &&
 1062 			    'n' == buf[t[j+1].start]) {
 1063 				p->has_image = 0;
 1064 				j++;
 1065 				continue;
 1066 			} else
 1067 				p->has_image = 1;
 1068 			if (t[j+1].type != JSMN_STRING)
 1069 				return 0;
 1070 			tmpbuf = strndup
 1071 				(buf + t[j+1].start,
 1072 				 t[j+1].end - t[j+1].start);
 1073 			if (NULL == tmpbuf)
 1074 				return -1;
 1075 			p->image = malloc((t[j+1].end - t[j+1].start) + 1);
 1076 			if (NULL == p->image) {
 1077 				free(tmpbuf);
 1078 				return -1;
 1079 			}
 1080 			rc = b64_pton(tmpbuf, p->image,
 1081 				(t[j+1].end - t[j+1].start) + 1);
 1082 			free(tmpbuf);
 1083 			if (rc < 0)
 1084 				return -1;
 1085 			p->image_sz = rc;
 1086 			j++;
 1087 			continue;
 1088 		}
 1089 		if (jsmn_eq(buf, &t[j+1], "name")) {
 1090 			j++;
 1091 			if (t[j+1].type != JSMN_STRING)
 1092 				return 0;
 1093 			p->name = strndup
 1094 				(buf + t[j+1].start,
 1095 				 t[j+1].end - t[j+1].start);
 1096 			if (NULL == p->name)
 1097 				return -1;
 1098 			j++;
 1099 			continue;
 1100 		}
 1101 		if (jsmn_eq(buf, &t[j+1], "uid")) {
 1102 			j++;
 1103 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1104 			    ('-' != buf[t[j+1].start] &&
 1105 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1106 				return 0;
 1107 			if ( ! jsmn_parse_int(buf + t[j+1].start,
 1108 			    t[j+1].end - t[j+1].start, &p->uid))
 1109 				return 0;
 1110 			j++;
 1111 			continue;
 1112 		}
 1113 
 1114 		/* Anything else is unexpected. */
 1115 
 1116 		return 0;
 1117 	}
 1118 	return j+1;
 1119 }
 1120 
 1121 void
 1122 jsmn_user_clear(struct user *p)
 1123 
 1124 {
 1125 	if (NULL == p)
 1126 		return;
 1127 	jsmn_company_clear(&p->company);
 1128 	free(p->hash);
 1129 	free(p->email);
 1130 	free(p->image);
 1131 	free(p->name);
 1132 }
 1133 
 1134 void
 1135 jsmn_user_free_array(struct user *p, size_t sz)
 1136 {
 1137 	size_t i;
 1138 	for (i = 0; i < sz; i++)
 1139 		jsmn_user_clear(&p[i]);
 1140 	free(p);
 1141 }
 1142 
 1143 int
 1144 jsmn_user_array(struct user **p, size_t *sz, const char *buf, const jsmntok_t *t, size_t toksz)
 1145 {
 1146 	size_t i, j;
 1147 	int rc;
 1148 
 1149 	*sz = 0;
 1150 	*p = NULL;
 1151 
 1152 	if (toksz < 1 || t[0].type != JSMN_ARRAY)
 1153 		return 0;
 1154 
 1155 	*sz = t[0].size;
 1156 	if (NULL == (*p = calloc(*sz, sizeof(struct user))))
 1157 		return -1;
 1158 
 1159 	for (i = j = 0; i < *sz; i++) {
 1160 		rc = jsmn_user(&(*p)[i], buf, &t[j+1], toksz - j);
 1161 		if (rc <= 0)
 1162 			return rc;
 1163 		j += rc;
 1164 	}
 1165 	return j + 1;
 1166 }
 1167 
 1168 int
 1169 valid_user_cid(struct kpair *p)
 1170 {
 1171 	if ( ! kvalid_int(p))
 1172 		return 0;
 1173 	return 1;
 1174 }
 1175 
 1176 int
 1177 valid_user_sex(struct kpair *p)
 1178 {
 1179 	if ( ! kvalid_int(p))
 1180 		return 0;
 1181 	switch(p->parsed.i) {
 1182 	case 0:
 1183 	case 1:
 1184 	case 2:
 1185 		break;
 1186 	default:
 1187 		return 0;
 1188 	}
 1189 	return 1;
 1190 }
 1191 
 1192 int
 1193 valid_user_hash(struct kpair *p)
 1194 {
 1195 	if ( ! kvalid_string(p))
 1196 		return 0;
 1197 	if (p->valsz <= 0)
 1198 		return 0;
 1199 	return 1;
 1200 }
 1201 
 1202 int
 1203 valid_user_email(struct kpair *p)
 1204 {
 1205 	if ( ! kvalid_email(p))
 1206 		return 0;
 1207 	return 1;
 1208 }
 1209 
 1210 int
 1211 valid_user_image(struct kpair *p)
 1212 {
 1213 	return 1;
 1214 }
 1215 
 1216 int
 1217 valid_user_name(struct kpair *p)
 1218 {
 1219 	if ( ! kvalid_string(p))
 1220 		return 0;
 1221 	return 1;
 1222 }
 1223 
 1224 int
 1225 valid_user_uid(struct kpair *p)
 1226 {
 1227 	if ( ! kvalid_int(p))
 1228 		return 0;
 1229 	return 1;
 1230 }
 1231 
 1232 void
 1233 db_user_iterate_by_name_eq(struct ksql *db, user_cb cb, void *arg, const char *v1)
 1234 {
 1235 	struct ksqlstmt *stmt;
 1236 	struct user p;
 1237 
 1238 	ksql_stmt_alloc(db, &stmt,
 1239 		stmts[STMT_USER_BY_SEARCH_0],
 1240 		STMT_USER_BY_SEARCH_0);
 1241 	ksql_bind_str(stmt, 0, v1);
 1242 	while (KSQL_ROW == ksql_stmt_step(stmt)) {
 1243 		db_user_fill_r(&p, stmt, NULL);
 1244 		(*cb)(&p, arg);
 1245 		db_user_unfill_r(&p);
 1246 	}
 1247 	ksql_stmt_free(stmt);
 1248 }
 1249 
 1250 struct user *
 1251 db_user_get_creds(struct ksql *db, const char *v1, const char *v2)
 1252 {
 1253 	struct ksqlstmt *stmt;
 1254 	struct user *p = NULL;
 1255 
 1256 	ksql_stmt_alloc(db, &stmt,
 1257 		stmts[STMT_USER_BY_SEARCH_1],
 1258 		STMT_USER_BY_SEARCH_1);
 1259 	ksql_bind_str(stmt, 0, v1);
 1260 	if (KSQL_ROW == ksql_stmt_step(stmt)) {
 1261 		p = malloc(sizeof(struct user));
 1262 		if (NULL == p) {
 1263 			perror(NULL);
 1264 			exit(EXIT_FAILURE);
 1265 		}
 1266 		db_user_fill_r(p, stmt, NULL);
 1267 		if (NULL != p && (crypt_checkpass(v2, p->hash) < 0)) {
 1268 			db_user_free(p);
 1269 			p = NULL;
 1270 		}
 1271 	}
 1272 	ksql_stmt_free(stmt);
 1273 	return p;
 1274 }
 1275 
 1276 struct user *
 1277 db_user_get_by_uid_eq(struct ksql *db, int64_t v1)
 1278 {
 1279 	struct ksqlstmt *stmt;
 1280 	struct user *p = NULL;
 1281 
 1282 	ksql_stmt_alloc(db, &stmt,
 1283 		stmts[STMT_USER_BY_SEARCH_2],
 1284 		STMT_USER_BY_SEARCH_2);
 1285 	ksql_bind_int(stmt, 0, v1);
 1286 	if (KSQL_ROW == ksql_stmt_step(stmt)) {
 1287 		p = malloc(sizeof(struct user));
 1288 		if (NULL == p) {
 1289 			perror(NULL);
 1290 			exit(EXIT_FAILURE);
 1291 		}
 1292 		db_user_fill_r(p, stmt, NULL);
 1293 	}
 1294 	ksql_stmt_free(stmt);
 1295 	return p;
 1296 }
 1297 
 1298 int
 1299 db_user_update_hash_by_uid_eq(struct ksql *db, const char *v1, int64_t v2)
 1300 {
 1301 	struct ksqlstmt *stmt;
 1302 	enum ksqlc c;
 1303 	char hash1[64];
 1304 
 1305 	crypt_newhash(v1, "blowfish,a", hash1, sizeof(hash1));
 1306 
 1307 	ksql_stmt_alloc(db, &stmt,
 1308 		stmts[STMT_USER_UPDATE_0],
 1309 		STMT_USER_UPDATE_0);
 1310 	ksql_bind_str(stmt, 0, hash1);
 1311 	ksql_bind_int(stmt, 1, v2);
 1312 	c = ksql_stmt_cstep(stmt);
 1313 	ksql_stmt_free(stmt);
 1314 	return(KSQL_CONSTRAINT != c);
 1315 }
 1316 
 1317 int
 1318 db_user_update_email_by_uid_eq(struct ksql *db, const char *v1, int64_t v2)
 1319 {
 1320 	struct ksqlstmt *stmt;
 1321 	enum ksqlc c;
 1322 
 1323 	ksql_stmt_alloc(db, &stmt,
 1324 		stmts[STMT_USER_UPDATE_1],
 1325 		STMT_USER_UPDATE_1);
 1326 	ksql_bind_str(stmt, 0, v1);
 1327 	ksql_bind_int(stmt, 1, v2);
 1328 	c = ksql_stmt_cstep(stmt);
 1329 	ksql_stmt_free(stmt);
 1330 	return(KSQL_CONSTRAINT != c);
 1331 }
 1332 
 1333 void
 1334 db_session_fill(struct session *p, struct ksqlstmt *stmt, size_t *pos)
 1335 {
 1336 	size_t i = 0;
 1337 	enum ksqlc c;
 1338 
 1339 	if (NULL == pos)
 1340 		pos = &i;
 1341 	memset(p, 0, sizeof(*p));
 1342 	c = ksql_result_int(stmt, &p->userid, (*pos)++);
 1343 	if (KSQL_OK != c)
 1344 		exit(EXIT_FAILURE);
 1345 	c = ksql_result_int(stmt, &p->token, (*pos)++);
 1346 	if (KSQL_OK != c)
 1347 		exit(EXIT_FAILURE);
 1348 	c = ksql_result_int(stmt, &p->mtime, (*pos)++);
 1349 	if (KSQL_OK != c)
 1350 		exit(EXIT_FAILURE);
 1351 	c = ksql_result_int(stmt, &p->id, (*pos)++);
 1352 	if (KSQL_OK != c)
 1353 		exit(EXIT_FAILURE);
 1354 }
 1355 
 1356 static void
 1357 db_session_fill_r(struct session *p, struct ksqlstmt *stmt, size_t *pos)
 1358 {
 1359 	size_t i = 0;
 1360 
 1361 	if (NULL == pos)
 1362 		pos = &i;
 1363 	db_session_fill(p, stmt, pos);
 1364 	db_user_fill_r(&p->user, stmt, pos);
 1365 }
 1366 
 1367 void
 1368 db_session_unfill(struct session *p)
 1369 {
 1370 	if (NULL == p)
 1371 		return;
 1372 }
 1373 
 1374 static void
 1375 db_session_unfill_r(struct session *p)
 1376 {
 1377 	if (NULL == p)
 1378 		return;
 1379 
 1380 	db_session_unfill(p);
 1381 	db_user_unfill_r(&p->user);
 1382 }
 1383 
 1384 void
 1385 db_session_free(struct session *p)
 1386 {
 1387 	db_session_unfill_r(p);
 1388 	free(p);
 1389 }
 1390 
 1391 int64_t
 1392 db_session_insert(struct ksql *db, int64_t v1, int64_t v2, time_t v3)
 1393 {
 1394 	struct ksqlstmt *stmt;
 1395 	int64_t id = -1;
 1396 
 1397 	ksql_stmt_alloc(db, &stmt,
 1398 		stmts[STMT_SESSION_INSERT],
 1399 		STMT_SESSION_INSERT);
 1400 	ksql_bind_int(stmt, 0, v1);
 1401 	ksql_bind_int(stmt, 1, v2);
 1402 	ksql_bind_int(stmt, 2, v3);
 1403 	if (KSQL_DONE == ksql_stmt_cstep(stmt))
 1404 		ksql_lastid(db, &id);
 1405 	ksql_stmt_free(stmt);
 1406 	return(id);
 1407 }
 1408 
 1409 void
 1410 json_session_data(struct kjsonreq *r, const struct session *p)
 1411 {
 1412 	kjson_objp_open(r, "user");
 1413 	json_user_data(r, &p->user);
 1414 	kjson_obj_close(r);
 1415 	kjson_putintp(r, "userid", p->userid);
 1416 	kjson_putintp(r, "token", p->token);
 1417 	kjson_putintp(r, "mtime", p->mtime);
 1418 	kjson_putintp(r, "id", p->id);
 1419 }
 1420 
 1421 void
 1422 json_session_obj(struct kjsonreq *r, const struct session *p)
 1423 {
 1424 	kjson_objp_open(r, "session");
 1425 	json_session_data(r, p);
 1426 	kjson_obj_close(r);
 1427 }
 1428 
 1429 void
 1430 json_session_iterate(const struct session *p, void *arg)
 1431 {
 1432 	struct kjsonreq *r = arg;
 1433 
 1434 	kjson_obj_open(r);
 1435 	json_session_data(r, p);
 1436 	kjson_obj_close(r);
 1437 }
 1438 
 1439 int
 1440 jsmn_session(struct session *p, const char *buf, const jsmntok_t *t, size_t toksz)
 1441 {
 1442 	int i;
 1443 	size_t j;
 1444 	int rc;
 1445 
 1446 	if (toksz < 1 || t[0].type != JSMN_OBJECT)
 1447 		return 0;
 1448 
 1449 	for (i = 0, j = 0; i < t[0].size; i++) {
 1450 		if (jsmn_eq(buf, &t[j+1], "user")) {
 1451 			j++;
 1452 			if (t[j+1].type != JSMN_OBJECT)
 1453 				return 0;
 1454 			rc = jsmn_user
 1455 				(&p->user, buf,
 1456 				 &t[j+1], toksz - j);
 1457 			if (rc <= 0)
 1458 				return rc;
 1459 			j += rc;
 1460 			continue;
 1461 		}
 1462 		if (jsmn_eq(buf, &t[j+1], "userid")) {
 1463 			j++;
 1464 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1465 			    ('-' != buf[t[j+1].start] &&
 1466 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1467 				return 0;
 1468 			if ( ! jsmn_parse_int(buf + t[j+1].start,
 1469 			    t[j+1].end - t[j+1].start, &p->userid))
 1470 				return 0;
 1471 			j++;
 1472 			continue;
 1473 		}
 1474 		if (jsmn_eq(buf, &t[j+1], "token")) {
 1475 			j++;
 1476 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1477 			    ('-' != buf[t[j+1].start] &&
 1478 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1479 				return 0;
 1480 			if ( ! jsmn_parse_int(buf + t[j+1].start,
 1481 			    t[j+1].end - t[j+1].start, &p->token))
 1482 				return 0;
 1483 			j++;
 1484 			continue;
 1485 		}
 1486 		if (jsmn_eq(buf, &t[j+1], "mtime")) {
 1487 			j++;
 1488 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1489 			    ('-' != buf[t[j+1].start] &&
 1490 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1491 				return 0;
 1492 			if ( ! jsmn_parse_int(buf + t[j+1].start,
 1493 			    t[j+1].end - t[j+1].start, &p->mtime))
 1494 				return 0;
 1495 			j++;
 1496 			continue;
 1497 		}
 1498 		if (jsmn_eq(buf, &t[j+1], "id")) {
 1499 			j++;
 1500 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1501 			    ('-' != buf[t[j+1].start] &&
 1502 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1503 				return 0;
 1504 			if ( ! jsmn_parse_int(buf + t[j+1].start,
 1505 			    t[j+1].end - t[j+1].start, &p->id))
 1506 				return 0;
 1507 			j++;
 1508 			continue;
 1509 		}
 1510 
 1511 		/* Anything else is unexpected. */
 1512 
 1513 		return 0;
 1514 	}
 1515 	return j+1;
 1516 }
 1517 
 1518 void
 1519 jsmn_session_clear(struct session *p)
 1520 
 1521 {
 1522 	if (NULL == p)
 1523 		return;
 1524 	jsmn_user_clear(&p->user);
 1525 }
 1526 
 1527 void
 1528 jsmn_session_free_array(struct session *p, size_t sz)
 1529 {
 1530 	size_t i;
 1531 	for (i = 0; i < sz; i++)
 1532 		jsmn_session_clear(&p[i]);
 1533 	free(p);
 1534 }
 1535 
 1536 int
 1537 jsmn_session_array(struct session **p, size_t *sz, const char *buf, const jsmntok_t *t, size_t toksz)
 1538 {
 1539 	size_t i, j;
 1540 	int rc;
 1541 
 1542 	*sz = 0;
 1543 	*p = NULL;
 1544 
 1545 	if (toksz < 1 || t[0].type != JSMN_ARRAY)
 1546 		return 0;
 1547 
 1548 	*sz = t[0].size;
 1549 	if (NULL == (*p = calloc(*sz, sizeof(struct session))))
 1550 		return -1;
 1551 
 1552 	for (i = j = 0; i < *sz; i++) {
 1553 		rc = jsmn_session(&(*p)[i], buf, &t[j+1], toksz - j);
 1554 		if (rc <= 0)
 1555 			return rc;
 1556 		j += rc;
 1557 	}
 1558 	return j + 1;
 1559 }
 1560 
 1561 int
 1562 valid_session_userid(struct kpair *p)
 1563 {
 1564 	if ( ! kvalid_int(p))
 1565 		return 0;
 1566 	return 1;
 1567 }
 1568 
 1569 int
 1570 valid_session_token(struct kpair *p)
 1571 {
 1572 	if ( ! kvalid_int(p))
 1573 		return 0;
 1574 	return 1;
 1575 }
 1576 
 1577 int
 1578 valid_session_mtime(struct kpair *p)
 1579 {
 1580 	if ( ! kvalid_int(p))
 1581 		return 0;
 1582 	return 1;
 1583 }
 1584 
 1585 int
 1586 valid_session_id(struct kpair *p)
 1587 {
 1588 	if ( ! kvalid_int(p))
 1589 		return 0;
 1590 	return 1;
 1591 }
 1592 
 1593 void
 1594 db_session_iterate_foo(struct ksql *db, session_cb cb, void *arg, const char *v1,
 1595 	time_t v2)
 1596 {
 1597 	struct ksqlstmt *stmt;
 1598 	struct session p;
 1599 
 1600 	ksql_stmt_alloc(db, &stmt,
 1601 		stmts[STMT_SESSION_BY_SEARCH_0],
 1602 		STMT_SESSION_BY_SEARCH_0);
 1603 	ksql_bind_str(stmt, 0, v1);
 1604 	ksql_bind_int(stmt, 1, v2);
 1605 	while (KSQL_ROW == ksql_stmt_step(stmt)) {
 1606 		db_session_fill_r(&p, stmt, NULL);
 1607 		(*cb)(&p, arg);
 1608 		db_session_unfill_r(&p);
 1609 	}
 1610 	ksql_stmt_free(stmt);
 1611 }
 1612 
 1613 int
 1614 db_session_delete_by_id_eq(struct ksql *db, int64_t v1)
 1615 {
 1616 	struct ksqlstmt *stmt;
 1617 	enum ksqlc c;
 1618 
 1619 	ksql_stmt_alloc(db, &stmt,
 1620 		stmts[STMT_SESSION_DELETE_0],
 1621 		STMT_SESSION_DELETE_0);
 1622 	ksql_bind_int(stmt, 0, v1);
 1623 	c = ksql_stmt_cstep(stmt);
 1624 	ksql_stmt_free(stmt);
 1625 	return(KSQL_CONSTRAINT != c);
 1626 }
 1627