1 /*
    2  * WARNING: automatically generated by ort-c-source 0.7.8.
    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 <stdio.h>
   17 #include <stdint.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/openradtool/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 ort.
  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) "," 
  448 		DB_SCHEMA_COMPANY(_c) " FROM session "
  449 		"INNER JOIN user AS _b ON _b.uid=session.userid "
  450 		"INNER JOIN company AS _c ON _c.id=_b.cid "
  451 		"WHERE session.id = ?",
  452 	/* STMT_SESSION_BY_SEARCH_0 */
  453 	"SELECT " DB_SCHEMA_SESSION(session) "," DB_SCHEMA_USER(_b) "," 
  454 		DB_SCHEMA_COMPANY(_c) " FROM session "
  455 		"INNER JOIN user AS _b ON _b.uid=session.userid "
  456 		"INNER JOIN company AS _c ON _c.id=_b.cid "
  457 		"WHERE _c.name = ? AND session.mtime = ?",
  458 	/* STMT_SESSION_INSERT */
  459 	"INSERT INTO session (userid,token,mtime) VALUES (?,?,?)",
  460 	/* STMT_SESSION_DELETE_0 */
  461 	"DELETE FROM session WHERE id = ?",
  462 };
  463 
  464 const struct kvalid valid_keys[VALID__MAX] = {
  465 	{ valid_company_name, "company-name" },
  466 	{ valid_company_id, "company-id" },
  467 	{ valid_company_somenum, "company-somenum" },
  468 	{ valid_user_cid, "user-cid" },
  469 	{ valid_user_sex, "user-sex" },
  470 	{ valid_user_hash, "user-hash" },
  471 	{ valid_user_email, "user-email" },
  472 	{ valid_user_image, "user-image" },
  473 	{ valid_user_name, "user-name" },
  474 	{ valid_user_uid, "user-uid" },
  475 	{ valid_session_userid, "session-userid" },
  476 	{ valid_session_token, "session-token" },
  477 	{ valid_session_mtime, "session-mtime" },
  478 	{ valid_session_id, "session-id" },
  479 };
  480 
  481 /*
  482  * Finally, all of the functions we'll use.
  483  */
  484 
  485 void
  486 db_trans_open(struct ksql *p, size_t id, int mode)
  487 {
  488 	if (mode < 0)
  489 		ksql_trans_exclopen(p, id);
  490 	else if (mode > 0)
  491 		ksql_trans_singleopen(p, id);
  492 	else
  493 		ksql_trans_open(p, id);
  494 }
  495 
  496 void
  497 db_trans_rollback(struct ksql *p, size_t id)
  498 {
  499 	ksql_trans_rollback(p, id);
  500 }
  501 
  502 void
  503 db_trans_commit(struct ksql *p, size_t id)
  504 {
  505 	ksql_trans_commit(p, id);
  506 }
  507 
  508 struct ksql *
  509 db_open(const char *file)
  510 {
  511 	struct ksqlcfg cfg;
  512 	struct ksql *db;
  513 
  514 	ksql_cfg_defaults(&cfg);
  515 	cfg.flags |= KSQL_FOREIGN_KEYS;
  516 
  517 	db = ksql_alloc_child(&cfg, NULL, NULL);
  518 	if (db == NULL)
  519 		return NULL;
  520 	ksql_open(db, file);
  521 	return db;
  522 }
  523 
  524 void
  525 db_close(struct ksql *p)
  526 {
  527 	if (p == NULL)
  528 		return;
  529 	ksql_close(p);
  530 	ksql_free(p);
  531 }
  532 
  533 void
  534 db_company_fill(struct company *p, struct ksqlstmt *stmt, size_t *pos)
  535 {
  536 	size_t i = 0;
  537 	enum ksqlc c;
  538 	int hasval;
  539 
  540 	if (pos == NULL)
  541 		pos = &i;
  542 	memset(p, 0, sizeof(*p));
  543 	c = ksql_result_str_alloc(stmt, &p->name, (*pos)++);
  544 	if (c != KSQL_OK)
  545 		exit(EXIT_FAILURE);
  546 	c = ksql_result_int(stmt, &p->id, (*pos)++);
  547 	if (c != KSQL_OK)
  548 		exit(EXIT_FAILURE);
  549 	c = ksql_result_isnull(stmt, &hasval, *pos);
  550 	if (c != KSQL_OK)
  551 		exit(EXIT_FAILURE);
  552 	p->has_somenum = !hasval;
  553 	if (p->has_somenum) {
  554 		c = ksql_result_int(stmt, &p->somenum, (*pos)++);
  555 		if (c != KSQL_OK)
  556 			exit(EXIT_FAILURE);
  557 	} else
  558 		(*pos)++;
  559 }
  560 
  561 static void
  562 db_company_fill_r(struct company *p, struct ksqlstmt *stmt, size_t *pos)
  563 {
  564 	size_t i = 0;
  565 
  566 	if (pos == NULL)
  567 		pos = &i;
  568 	db_company_fill(p, stmt, pos);
  569 }
  570 
  571 void
  572 db_company_unfill(struct company *p)
  573 {
  574 	if (p == NULL)
  575 		return;
  576 	free(p->name);
  577 }
  578 
  579 static void
  580 db_company_unfill_r(struct company *p)
  581 {
  582 	if (p == NULL)
  583 		return;
  584 
  585 	db_company_unfill(p);
  586 }
  587 
  588 void
  589 db_company_free(struct company *p)
  590 {
  591 	db_company_unfill_r(p);
  592 	free(p);
  593 }
  594 
  595 void
  596 db_company_freeq(struct company_q *q)
  597 {
  598 	struct company *p;
  599 
  600 	if (q == NULL)
  601 		return;
  602 	while ((p = TAILQ_FIRST(q)) != NULL) {
  603 		TAILQ_REMOVE(q, p, _entries);
  604 		db_company_free(p);
  605 	}
  606 
  607 	free(q);
  608 }
  609 
  610 int64_t
  611 db_company_insert(struct ksql *db, const char *v1, int64_t *v2)
  612 {
  613 	struct ksqlstmt *stmt;
  614 	int64_t id = -1;
  615 
  616 	ksql_stmt_alloc(db, &stmt,
  617 		stmts[STMT_COMPANY_INSERT],
  618 		STMT_COMPANY_INSERT);
  619 	ksql_bind_str(stmt, 0, v1);
  620 	if (v2 == NULL)
  621 		ksql_bind_null(stmt, 1);
  622 	else
  623 		ksql_bind_int(stmt, 1, *v2);
  624 	if (ksql_stmt_cstep(stmt) == KSQL_DONE)
  625 		ksql_lastid(db, &id);
  626 	ksql_stmt_free(stmt);
  627 	return id;
  628 }
  629 
  630 void
  631 json_company_data(struct kjsonreq *r, const struct company *p)
  632 {
  633 	kjson_putstringp(r, "name", p->name);
  634 	kjson_putintp(r, "id", p->id);
  635 
  636 	if (!p->has_somenum)
  637 		kjson_putnullp(r, "somenum");
  638 	else
  639 		kjson_putintp(r, "somenum", p->somenum);
  640 
  641 }
  642 
  643 void
  644 json_company_obj(struct kjsonreq *r, const struct company *p)
  645 {
  646 	kjson_objp_open(r, "company");
  647 	json_company_data(r, p);
  648 	kjson_obj_close(r);
  649 }
  650 
  651 void
  652 json_company_array(struct kjsonreq *r, const struct company_q *q)
  653 {
  654 	struct company *p;
  655 
  656 	kjson_arrayp_open(r, "company_q");
  657 	TAILQ_FOREACH(p, q, _entries) {
  658 		kjson_obj_open(r);
  659 		json_company_data(r, p);
  660 		kjson_obj_close(r);
  661 	}
  662 	kjson_array_close(r);
  663 }
  664 
  665 int
  666 jsmn_company(struct company *p, const char *buf, const jsmntok_t *t, size_t toksz)
  667 {
  668 	int i;
  669 	size_t j;
  670 
  671 	if (toksz < 1 || t[0].type != JSMN_OBJECT)
  672 		return 0;
  673 
  674 	for (i = 0, j = 0; i < t[0].size; i++) {
  675 		if (jsmn_eq(buf, &t[j+1], "name")) {
  676 			j++;
  677 			if (t[j+1].type != JSMN_STRING)
  678 				return 0;
  679 			p->name = strndup
  680 				(buf + t[j+1].start,
  681 				 t[j+1].end - t[j+1].start);
  682 			if (p->name == NULL)
  683 				return -1;
  684 			j++;
  685 			continue;
  686 		}
  687 		if (jsmn_eq(buf, &t[j+1], "id")) {
  688 			j++;
  689 			if (t[j+1].type != JSMN_PRIMITIVE ||
  690 			    ('-' != buf[t[j+1].start] &&
  691 			    ! isdigit((unsigned int)buf[t[j+1].start])))
  692 				return 0;
  693 			if (!jsmn_parse_int(buf + t[j+1].start,
  694 			    t[j+1].end - t[j+1].start, &p->id))
  695 				return 0;
  696 			j++;
  697 			continue;
  698 		}
  699 		if (jsmn_eq(buf, &t[j+1], "somenum")) {
  700 			j++;
  701 			if (t[j+1].type == JSMN_PRIMITIVE &&
  702 			    'n' == buf[t[j+1].start]) {
  703 				p->has_somenum = 0;
  704 				j++;
  705 				continue;
  706 			} else
  707 				p->has_somenum = 1;
  708 			if (t[j+1].type != JSMN_PRIMITIVE ||
  709 			    ('-' != buf[t[j+1].start] &&
  710 			    ! isdigit((unsigned int)buf[t[j+1].start])))
  711 				return 0;
  712 			if (!jsmn_parse_int(buf + t[j+1].start,
  713 			    t[j+1].end - t[j+1].start, &p->somenum))
  714 				return 0;
  715 			j++;
  716 			continue;
  717 		}
  718 
  719 		/* Anything else is unexpected. */
  720 
  721 		return 0;
  722 	}
  723 	return j+1;
  724 }
  725 
  726 void
  727 jsmn_company_clear(struct company *p)
  728 
  729 {
  730 	if (p == NULL)
  731 		return;
  732 	free(p->name);
  733 }
  734 
  735 void
  736 jsmn_company_free_array(struct company *p, size_t sz)
  737 {
  738 	size_t i;
  739 	for (i = 0; i < sz; i++)
  740 		jsmn_company_clear(&p[i]);
  741 	free(p);
  742 }
  743 
  744 int
  745 jsmn_company_array(struct company **p, size_t *sz, const char *buf, const jsmntok_t *t, size_t toksz)
  746 {
  747 	size_t i, j;
  748 	int rc;
  749 
  750 	*sz = 0;
  751 	*p = NULL;
  752 
  753 	if (toksz < 1 || t[0].type != JSMN_ARRAY)
  754 		return 0;
  755 
  756 	*sz = t[0].size;
  757 	if ((*p = calloc(*sz, sizeof(struct company))) == NULL)
  758 		return -1;
  759 
  760 	for (i = j = 0; i < *sz; i++) {
  761 		rc = jsmn_company(&(*p)[i], buf, &t[j+1], toksz - j);
  762 		if (rc <= 0)
  763 			return rc;
  764 		j += rc;
  765 	}
  766 	return j + 1;
  767 }
  768 
  769 int
  770 valid_company_name(struct kpair *p)
  771 {
  772 	if (!kvalid_string(p))
  773 		return 0;
  774 	if (p->valsz <= 0)
  775 		return 0;
  776 	return 1;
  777 }
  778 
  779 int
  780 valid_company_id(struct kpair *p)
  781 {
  782 	if (!kvalid_int(p))
  783 		return 0;
  784 	return 1;
  785 }
  786 
  787 int
  788 valid_company_somenum(struct kpair *p)
  789 {
  790 	if (!kvalid_int(p))
  791 		return 0;
  792 	return 1;
  793 }
  794 
  795 struct company_q *
  796 db_company_list_by_somenum_isnull(struct ksql *db)
  797 {
  798 	struct ksqlstmt *stmt;
  799 	struct company_q *q;
  800 	struct company *p;
  801 
  802 	q = malloc(sizeof(struct company_q));
  803 	if (q == NULL) {
  804 		perror(NULL);
  805 		exit(EXIT_FAILURE);
  806 	}
  807 	TAILQ_INIT(q);
  808 
  809 	ksql_stmt_alloc(db, &stmt,
  810 		stmts[STMT_COMPANY_BY_SEARCH_0],
  811 		STMT_COMPANY_BY_SEARCH_0);
  812 	while (ksql_stmt_step(stmt) == KSQL_ROW) {
  813 		p = malloc(sizeof(struct company));
  814 		if (p == NULL) {
  815 			perror(NULL);
  816 			exit(EXIT_FAILURE);
  817 		}
  818 		db_company_fill_r(p, stmt, NULL);
  819 		TAILQ_INSERT_TAIL(q, p, _entries);
  820 	}
  821 	ksql_stmt_free(stmt);
  822 	return q;
  823 }
  824 
  825 void
  826 db_user_fill(struct user *p, struct ksqlstmt *stmt, size_t *pos)
  827 {
  828 	size_t i = 0;
  829 	enum ksqlc c;
  830 	int64_t tmpint;
  831 	int hasval;
  832 
  833 	if (pos == NULL)
  834 		pos = &i;
  835 	memset(p, 0, sizeof(*p));
  836 	c = ksql_result_int(stmt, &p->cid, (*pos)++);
  837 	if (c != KSQL_OK)
  838 		exit(EXIT_FAILURE);
  839 	c = ksql_result_int(stmt, &tmpint, (*pos)++);
  840 	if (c != KSQL_OK)
  841 		exit(EXIT_FAILURE);
  842 	p->sex = tmpint;
  843 	c = ksql_result_str_alloc(stmt, &p->hash, (*pos)++);
  844 	if (c != KSQL_OK)
  845 		exit(EXIT_FAILURE);
  846 	c = ksql_result_str_alloc(stmt, &p->email, (*pos)++);
  847 	if (c != KSQL_OK)
  848 		exit(EXIT_FAILURE);
  849 	c = ksql_result_isnull(stmt, &hasval, *pos);
  850 	if (c != KSQL_OK)
  851 		exit(EXIT_FAILURE);
  852 	p->has_image = !hasval;
  853 	if (p->has_image) {
  854 		c = ksql_result_blob_alloc(stmt, &p->image, &p->image_sz, (*pos)++);
  855 		if (c != KSQL_OK)
  856 			exit(EXIT_FAILURE);
  857 	} else
  858 		(*pos)++;
  859 	c = ksql_result_str_alloc(stmt, &p->name, (*pos)++);
  860 	if (c != KSQL_OK)
  861 		exit(EXIT_FAILURE);
  862 	c = ksql_result_int(stmt, &p->uid, (*pos)++);
  863 	if (c != KSQL_OK)
  864 		exit(EXIT_FAILURE);
  865 }
  866 
  867 static void
  868 db_user_fill_r(struct user *p, struct ksqlstmt *stmt, size_t *pos)
  869 {
  870 	size_t i = 0;
  871 
  872 	if (pos == NULL)
  873 		pos = &i;
  874 	db_user_fill(p, stmt, pos);
  875 	db_company_fill_r(&p->company, stmt, pos);
  876 }
  877 
  878 void
  879 db_user_unfill(struct user *p)
  880 {
  881 	if (p == NULL)
  882 		return;
  883 	free(p->hash);
  884 	free(p->email);
  885 	free(p->image);
  886 	free(p->name);
  887 }
  888 
  889 static void
  890 db_user_unfill_r(struct user *p)
  891 {
  892 	if (p == NULL)
  893 		return;
  894 
  895 	db_user_unfill(p);
  896 	db_company_unfill_r(&p->company);
  897 }
  898 
  899 void
  900 db_user_free(struct user *p)
  901 {
  902 	db_user_unfill_r(p);
  903 	free(p);
  904 }
  905 
  906 int64_t
  907 db_user_insert(struct ksql *db, int64_t v1, enum sex v2, const char *v3,
  908      const char *v4, size_t v5_sz, const void **v5, const char *v6)
  909 {
  910 	struct ksqlstmt *stmt;
  911 	int64_t id = -1;
  912 	char hash1[64];
  913 
  914 	crypt_newhash(v3, "blowfish,a", hash1, sizeof(hash1));
  915 
  916 	ksql_stmt_alloc(db, &stmt,
  917 		stmts[STMT_USER_INSERT],
  918 		STMT_USER_INSERT);
  919 	ksql_bind_int(stmt, 0, v1);
  920 	ksql_bind_int(stmt, 1, v2);
  921 	ksql_bind_str(stmt, 2, hash1);
  922 	ksql_bind_str(stmt, 3, v4);
  923 	if (v5 == NULL)
  924 		ksql_bind_null(stmt, 4);
  925 	else
  926 		ksql_bind_blob(stmt, 4, *v5, v5_sz);
  927 	ksql_bind_str(stmt, 5, v6);
  928 	if (ksql_stmt_cstep(stmt) == KSQL_DONE)
  929 		ksql_lastid(db, &id);
  930 	ksql_stmt_free(stmt);
  931 	return id;
  932 }
  933 
  934 void
  935 json_user_data(struct kjsonreq *r, const struct user *p)
  936 {
  937 	char *buf1;
  938 	size_t sz;
  939 
  940 	/*
  941 	 * We need to base64 encode the binary buffers prior to 
  942 	 * serialisation.
  943 	 * Allocate space for these buffers and do so now.
  944 	 * We'll free the buffers at the epilogue of the function.
  945 	 */
  946 
  947 	sz = (p->image_sz + 2) / 3 * 4 + 1;
  948 	buf1 = malloc(sz);
  949 	if (buf1 == NULL) {
  950 		perror(NULL);
  951 		exit(EXIT_FAILURE);
  952 	}
  953 	if (p->has_image)
  954 		b64_ntop(p->image, p->image_sz, buf1, sz);
  955 
  956 	kjson_objp_open(r, "company");
  957 	json_company_data(r, &p->company);
  958 	kjson_obj_close(r);
  959 	kjson_putintp(r, "cid", p->cid);
  960 	kjson_putintp(r, "sex", p->sex);
  961 
  962 	/* Omitting hash: is a password hash. */
  963 
  964 	kjson_putstringp(r, "email", p->email);
  965 
  966 	if (!p->has_image)
  967 		kjson_putnullp(r, "image");
  968 	else
  969 		kjson_putstringp(r, "image", buf1);
  970 
  971 	kjson_putstringp(r, "name", p->name);
  972 	kjson_putintp(r, "uid", p->uid);
  973 
  974 	free(buf1);
  975 }
  976 
  977 void
  978 json_user_obj(struct kjsonreq *r, const struct user *p)
  979 {
  980 	kjson_objp_open(r, "user");
  981 	json_user_data(r, p);
  982 	kjson_obj_close(r);
  983 }
  984 
  985 void
  986 json_user_iterate(const struct user *p, void *arg)
  987 {
  988 	struct kjsonreq *r = arg;
  989 
  990 	kjson_obj_open(r);
  991 	json_user_data(r, p);
  992 	kjson_obj_close(r);
  993 }
  994 
  995 int
  996 jsmn_user(struct user *p, const char *buf, const jsmntok_t *t, size_t toksz)
  997 {
  998 	int i;
  999 	size_t j;
 1000 	int64_t tmpint;
 1001 	int rc;
 1002 	char *tmpbuf;
 1003 
 1004 	if (toksz < 1 || t[0].type != JSMN_OBJECT)
 1005 		return 0;
 1006 
 1007 	for (i = 0, j = 0; i < t[0].size; i++) {
 1008 		if (jsmn_eq(buf, &t[j+1], "company")) {
 1009 			j++;
 1010 			if (t[j+1].type != JSMN_OBJECT)
 1011 				return 0;
 1012 			rc = jsmn_company
 1013 				(&p->company, buf,
 1014 				 &t[j+1], toksz - j);
 1015 			if (rc <= 0)
 1016 				return rc;
 1017 			j += rc;
 1018 			continue;
 1019 		}
 1020 		if (jsmn_eq(buf, &t[j+1], "cid")) {
 1021 			j++;
 1022 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1023 			    ('-' != buf[t[j+1].start] &&
 1024 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1025 				return 0;
 1026 			if (!jsmn_parse_int(buf + t[j+1].start,
 1027 			    t[j+1].end - t[j+1].start, &p->cid))
 1028 				return 0;
 1029 			j++;
 1030 			continue;
 1031 		}
 1032 		if (jsmn_eq(buf, &t[j+1], "sex")) {
 1033 			j++;
 1034 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1035 			    ('-' != buf[t[j+1].start] &&
 1036 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1037 				return 0;
 1038 			if (!jsmn_parse_int(buf + t[j+1].start,
 1039 			    t[j+1].end - t[j+1].start, &tmpint))
 1040 				return 0;
 1041 			p->sex = tmpint;
 1042 			j++;
 1043 			continue;
 1044 		}
 1045 		if (jsmn_eq(buf, &t[j+1], "hash")) {
 1046 			j++;
 1047 			if (t[j+1].type != JSMN_STRING)
 1048 				return 0;
 1049 			p->hash = strndup
 1050 				(buf + t[j+1].start,
 1051 				 t[j+1].end - t[j+1].start);
 1052 			if (p->hash == NULL)
 1053 				return -1;
 1054 			j++;
 1055 			continue;
 1056 		}
 1057 		if (jsmn_eq(buf, &t[j+1], "email")) {
 1058 			j++;
 1059 			if (t[j+1].type != JSMN_STRING)
 1060 				return 0;
 1061 			p->email = strndup
 1062 				(buf + t[j+1].start,
 1063 				 t[j+1].end - t[j+1].start);
 1064 			if (p->email == NULL)
 1065 				return -1;
 1066 			j++;
 1067 			continue;
 1068 		}
 1069 		if (jsmn_eq(buf, &t[j+1], "image")) {
 1070 			j++;
 1071 			if (t[j+1].type == JSMN_PRIMITIVE &&
 1072 			    'n' == buf[t[j+1].start]) {
 1073 				p->has_image = 0;
 1074 				j++;
 1075 				continue;
 1076 			} else
 1077 				p->has_image = 1;
 1078 			if (t[j+1].type != JSMN_STRING)
 1079 				return 0;
 1080 			tmpbuf = strndup
 1081 				(buf + t[j+1].start,
 1082 				 t[j+1].end - t[j+1].start);
 1083 			if (tmpbuf == NULL)
 1084 				return -1;
 1085 			p->image = malloc((t[j+1].end - t[j+1].start) + 1);
 1086 			if (p->image == NULL) {
 1087 				free(tmpbuf);
 1088 				return -1;
 1089 			}
 1090 			rc = b64_pton(tmpbuf, p->image,
 1091 				(t[j+1].end - t[j+1].start) + 1);
 1092 			free(tmpbuf);
 1093 			if (rc < 0)
 1094 				return -1;
 1095 			p->image_sz = rc;
 1096 			j++;
 1097 			continue;
 1098 		}
 1099 		if (jsmn_eq(buf, &t[j+1], "name")) {
 1100 			j++;
 1101 			if (t[j+1].type != JSMN_STRING)
 1102 				return 0;
 1103 			p->name = strndup
 1104 				(buf + t[j+1].start,
 1105 				 t[j+1].end - t[j+1].start);
 1106 			if (p->name == NULL)
 1107 				return -1;
 1108 			j++;
 1109 			continue;
 1110 		}
 1111 		if (jsmn_eq(buf, &t[j+1], "uid")) {
 1112 			j++;
 1113 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1114 			    ('-' != buf[t[j+1].start] &&
 1115 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1116 				return 0;
 1117 			if (!jsmn_parse_int(buf + t[j+1].start,
 1118 			    t[j+1].end - t[j+1].start, &p->uid))
 1119 				return 0;
 1120 			j++;
 1121 			continue;
 1122 		}
 1123 
 1124 		/* Anything else is unexpected. */
 1125 
 1126 		return 0;
 1127 	}
 1128 	return j+1;
 1129 }
 1130 
 1131 void
 1132 jsmn_user_clear(struct user *p)
 1133 
 1134 {
 1135 	if (p == NULL)
 1136 		return;
 1137 	jsmn_company_clear(&p->company);
 1138 	free(p->hash);
 1139 	free(p->email);
 1140 	free(p->image);
 1141 	free(p->name);
 1142 }
 1143 
 1144 void
 1145 jsmn_user_free_array(struct user *p, size_t sz)
 1146 {
 1147 	size_t i;
 1148 	for (i = 0; i < sz; i++)
 1149 		jsmn_user_clear(&p[i]);
 1150 	free(p);
 1151 }
 1152 
 1153 int
 1154 jsmn_user_array(struct user **p, size_t *sz, const char *buf, const jsmntok_t *t, size_t toksz)
 1155 {
 1156 	size_t i, j;
 1157 	int rc;
 1158 
 1159 	*sz = 0;
 1160 	*p = NULL;
 1161 
 1162 	if (toksz < 1 || t[0].type != JSMN_ARRAY)
 1163 		return 0;
 1164 
 1165 	*sz = t[0].size;
 1166 	if ((*p = calloc(*sz, sizeof(struct user))) == NULL)
 1167 		return -1;
 1168 
 1169 	for (i = j = 0; i < *sz; i++) {
 1170 		rc = jsmn_user(&(*p)[i], buf, &t[j+1], toksz - j);
 1171 		if (rc <= 0)
 1172 			return rc;
 1173 		j += rc;
 1174 	}
 1175 	return j + 1;
 1176 }
 1177 
 1178 int
 1179 valid_user_cid(struct kpair *p)
 1180 {
 1181 	if (!kvalid_int(p))
 1182 		return 0;
 1183 	return 1;
 1184 }
 1185 
 1186 int
 1187 valid_user_sex(struct kpair *p)
 1188 {
 1189 	if (!kvalid_int(p))
 1190 		return 0;
 1191 	switch(p->parsed.i) {
 1192 	case 0:
 1193 	case 1:
 1194 	case 2:
 1195 		break;
 1196 	default:
 1197 		return 0;
 1198 	}
 1199 	return 1;
 1200 }
 1201 
 1202 int
 1203 valid_user_hash(struct kpair *p)
 1204 {
 1205 	if (!kvalid_string(p))
 1206 		return 0;
 1207 	if (p->valsz <= 0)
 1208 		return 0;
 1209 	return 1;
 1210 }
 1211 
 1212 int
 1213 valid_user_email(struct kpair *p)
 1214 {
 1215 	if (!kvalid_email(p))
 1216 		return 0;
 1217 	return 1;
 1218 }
 1219 
 1220 int
 1221 valid_user_image(struct kpair *p)
 1222 {
 1223 	return 1;
 1224 }
 1225 
 1226 int
 1227 valid_user_name(struct kpair *p)
 1228 {
 1229 	if (!kvalid_string(p))
 1230 		return 0;
 1231 	return 1;
 1232 }
 1233 
 1234 int
 1235 valid_user_uid(struct kpair *p)
 1236 {
 1237 	if (!kvalid_int(p))
 1238 		return 0;
 1239 	return 1;
 1240 }
 1241 
 1242 void
 1243 db_user_iterate_by_name_eq(struct ksql *db, user_cb cb, void *arg, const char *v1)
 1244 {
 1245 	struct ksqlstmt *stmt;
 1246 	struct user p;
 1247 
 1248 	ksql_stmt_alloc(db, &stmt,
 1249 		stmts[STMT_USER_BY_SEARCH_0],
 1250 		STMT_USER_BY_SEARCH_0);
 1251 	ksql_bind_str(stmt, 0, v1);
 1252 	while (ksql_stmt_step(stmt) == KSQL_ROW) {
 1253 		db_user_fill_r(&p, stmt, NULL);
 1254 		(*cb)(&p, arg);
 1255 		db_user_unfill_r(&p);
 1256 	}
 1257 	ksql_stmt_free(stmt);
 1258 }
 1259 
 1260 struct user *
 1261 db_user_get_creds(struct ksql *db, const char *v1, const char *v2)
 1262 {
 1263 	struct ksqlstmt *stmt;
 1264 	struct user *p = NULL;
 1265 
 1266 	ksql_stmt_alloc(db, &stmt,
 1267 		stmts[STMT_USER_BY_SEARCH_1],
 1268 		STMT_USER_BY_SEARCH_1);
 1269 	ksql_bind_str(stmt, 0, v1);
 1270 	if (ksql_stmt_step(stmt) == KSQL_ROW) {
 1271 		p = malloc(sizeof(struct user));
 1272 		if (p == NULL) {
 1273 			perror(NULL);
 1274 			exit(EXIT_FAILURE);
 1275 		}
 1276 		db_user_fill_r(p, stmt, NULL);
 1277 		if (p != NULL && (crypt_checkpass(v2, p->hash) == -1)) {
 1278 			db_user_free(p);
 1279 			p = NULL;
 1280 		}
 1281 	}
 1282 	ksql_stmt_free(stmt);
 1283 	return p;
 1284 }
 1285 
 1286 struct user *
 1287 db_user_get_by_uid_eq(struct ksql *db, int64_t v1)
 1288 {
 1289 	struct ksqlstmt *stmt;
 1290 	struct user *p = NULL;
 1291 
 1292 	ksql_stmt_alloc(db, &stmt,
 1293 		stmts[STMT_USER_BY_SEARCH_2],
 1294 		STMT_USER_BY_SEARCH_2);
 1295 	ksql_bind_int(stmt, 0, v1);
 1296 	if (ksql_stmt_step(stmt) == KSQL_ROW) {
 1297 		p = malloc(sizeof(struct user));
 1298 		if (p == NULL) {
 1299 			perror(NULL);
 1300 			exit(EXIT_FAILURE);
 1301 		}
 1302 		db_user_fill_r(p, stmt, NULL);
 1303 	}
 1304 	ksql_stmt_free(stmt);
 1305 	return p;
 1306 }
 1307 
 1308 int
 1309 db_user_update_hash_by_uid_eq(struct ksql *db, const char *v1, int64_t v2)
 1310 {
 1311 	struct ksqlstmt *stmt;
 1312 	enum ksqlc c;
 1313 	char hash1[64];
 1314 
 1315 	crypt_newhash(v1, "blowfish,a", hash1, sizeof(hash1));
 1316 
 1317 	ksql_stmt_alloc(db, &stmt,
 1318 		stmts[STMT_USER_UPDATE_0],
 1319 		STMT_USER_UPDATE_0);
 1320 	ksql_bind_str(stmt, 0, hash1);
 1321 	ksql_bind_int(stmt, 1, v2);
 1322 	c = ksql_stmt_cstep(stmt);
 1323 	ksql_stmt_free(stmt);
 1324 	return(KSQL_DONE == c ? 1 : (KSQL_CONSTRAINT == c ? 0 : -1));
 1325 }
 1326 
 1327 int
 1328 db_user_update_email_by_uid_eq(struct ksql *db, const char *v1, int64_t v2)
 1329 {
 1330 	struct ksqlstmt *stmt;
 1331 	enum ksqlc c;
 1332 
 1333 	ksql_stmt_alloc(db, &stmt,
 1334 		stmts[STMT_USER_UPDATE_1],
 1335 		STMT_USER_UPDATE_1);
 1336 	ksql_bind_str(stmt, 0, v1);
 1337 	ksql_bind_int(stmt, 1, v2);
 1338 	c = ksql_stmt_cstep(stmt);
 1339 	ksql_stmt_free(stmt);
 1340 	return(KSQL_DONE == c ? 1 : (KSQL_CONSTRAINT == c ? 0 : -1));
 1341 }
 1342 
 1343 void
 1344 db_session_fill(struct session *p, struct ksqlstmt *stmt, size_t *pos)
 1345 {
 1346 	size_t i = 0;
 1347 	enum ksqlc c;
 1348 
 1349 	if (pos == NULL)
 1350 		pos = &i;
 1351 	memset(p, 0, sizeof(*p));
 1352 	c = ksql_result_int(stmt, &p->userid, (*pos)++);
 1353 	if (c != KSQL_OK)
 1354 		exit(EXIT_FAILURE);
 1355 	c = ksql_result_int(stmt, &p->token, (*pos)++);
 1356 	if (c != KSQL_OK)
 1357 		exit(EXIT_FAILURE);
 1358 	c = ksql_result_int(stmt, &p->mtime, (*pos)++);
 1359 	if (c != KSQL_OK)
 1360 		exit(EXIT_FAILURE);
 1361 	c = ksql_result_int(stmt, &p->id, (*pos)++);
 1362 	if (c != KSQL_OK)
 1363 		exit(EXIT_FAILURE);
 1364 }
 1365 
 1366 static void
 1367 db_session_fill_r(struct session *p, struct ksqlstmt *stmt, size_t *pos)
 1368 {
 1369 	size_t i = 0;
 1370 
 1371 	if (pos == NULL)
 1372 		pos = &i;
 1373 	db_session_fill(p, stmt, pos);
 1374 	db_user_fill_r(&p->user, stmt, pos);
 1375 }
 1376 
 1377 void
 1378 db_session_unfill(struct session *p)
 1379 {
 1380 	if (p == NULL)
 1381 		return;
 1382 }
 1383 
 1384 static void
 1385 db_session_unfill_r(struct session *p)
 1386 {
 1387 	if (p == NULL)
 1388 		return;
 1389 
 1390 	db_session_unfill(p);
 1391 	db_user_unfill_r(&p->user);
 1392 }
 1393 
 1394 void
 1395 db_session_free(struct session *p)
 1396 {
 1397 	db_session_unfill_r(p);
 1398 	free(p);
 1399 }
 1400 
 1401 int64_t
 1402 db_session_insert(struct ksql *db, int64_t v1, int64_t v2, time_t v3)
 1403 {
 1404 	struct ksqlstmt *stmt;
 1405 	int64_t id = -1;
 1406 
 1407 	ksql_stmt_alloc(db, &stmt,
 1408 		stmts[STMT_SESSION_INSERT],
 1409 		STMT_SESSION_INSERT);
 1410 	ksql_bind_int(stmt, 0, v1);
 1411 	ksql_bind_int(stmt, 1, v2);
 1412 	ksql_bind_int(stmt, 2, v3);
 1413 	if (ksql_stmt_cstep(stmt) == KSQL_DONE)
 1414 		ksql_lastid(db, &id);
 1415 	ksql_stmt_free(stmt);
 1416 	return id;
 1417 }
 1418 
 1419 void
 1420 json_session_data(struct kjsonreq *r, const struct session *p)
 1421 {
 1422 	kjson_objp_open(r, "user");
 1423 	json_user_data(r, &p->user);
 1424 	kjson_obj_close(r);
 1425 	kjson_putintp(r, "userid", p->userid);
 1426 	kjson_putintp(r, "token", p->token);
 1427 	kjson_putintp(r, "mtime", p->mtime);
 1428 	kjson_putintp(r, "id", p->id);
 1429 }
 1430 
 1431 void
 1432 json_session_obj(struct kjsonreq *r, const struct session *p)
 1433 {
 1434 	kjson_objp_open(r, "session");
 1435 	json_session_data(r, p);
 1436 	kjson_obj_close(r);
 1437 }
 1438 
 1439 void
 1440 json_session_iterate(const struct session *p, void *arg)
 1441 {
 1442 	struct kjsonreq *r = arg;
 1443 
 1444 	kjson_obj_open(r);
 1445 	json_session_data(r, p);
 1446 	kjson_obj_close(r);
 1447 }
 1448 
 1449 int
 1450 jsmn_session(struct session *p, const char *buf, const jsmntok_t *t, size_t toksz)
 1451 {
 1452 	int i;
 1453 	size_t j;
 1454 	int rc;
 1455 
 1456 	if (toksz < 1 || t[0].type != JSMN_OBJECT)
 1457 		return 0;
 1458 
 1459 	for (i = 0, j = 0; i < t[0].size; i++) {
 1460 		if (jsmn_eq(buf, &t[j+1], "user")) {
 1461 			j++;
 1462 			if (t[j+1].type != JSMN_OBJECT)
 1463 				return 0;
 1464 			rc = jsmn_user
 1465 				(&p->user, buf,
 1466 				 &t[j+1], toksz - j);
 1467 			if (rc <= 0)
 1468 				return rc;
 1469 			j += rc;
 1470 			continue;
 1471 		}
 1472 		if (jsmn_eq(buf, &t[j+1], "userid")) {
 1473 			j++;
 1474 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1475 			    ('-' != buf[t[j+1].start] &&
 1476 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1477 				return 0;
 1478 			if (!jsmn_parse_int(buf + t[j+1].start,
 1479 			    t[j+1].end - t[j+1].start, &p->userid))
 1480 				return 0;
 1481 			j++;
 1482 			continue;
 1483 		}
 1484 		if (jsmn_eq(buf, &t[j+1], "token")) {
 1485 			j++;
 1486 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1487 			    ('-' != buf[t[j+1].start] &&
 1488 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1489 				return 0;
 1490 			if (!jsmn_parse_int(buf + t[j+1].start,
 1491 			    t[j+1].end - t[j+1].start, &p->token))
 1492 				return 0;
 1493 			j++;
 1494 			continue;
 1495 		}
 1496 		if (jsmn_eq(buf, &t[j+1], "mtime")) {
 1497 			j++;
 1498 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1499 			    ('-' != buf[t[j+1].start] &&
 1500 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1501 				return 0;
 1502 			if (!jsmn_parse_int(buf + t[j+1].start,
 1503 			    t[j+1].end - t[j+1].start, &p->mtime))
 1504 				return 0;
 1505 			j++;
 1506 			continue;
 1507 		}
 1508 		if (jsmn_eq(buf, &t[j+1], "id")) {
 1509 			j++;
 1510 			if (t[j+1].type != JSMN_PRIMITIVE ||
 1511 			    ('-' != buf[t[j+1].start] &&
 1512 			    ! isdigit((unsigned int)buf[t[j+1].start])))
 1513 				return 0;
 1514 			if (!jsmn_parse_int(buf + t[j+1].start,
 1515 			    t[j+1].end - t[j+1].start, &p->id))
 1516 				return 0;
 1517 			j++;
 1518 			continue;
 1519 		}
 1520 
 1521 		/* Anything else is unexpected. */
 1522 
 1523 		return 0;
 1524 	}
 1525 	return j+1;
 1526 }
 1527 
 1528 void
 1529 jsmn_session_clear(struct session *p)
 1530 
 1531 {
 1532 	if (p == NULL)
 1533 		return;
 1534 	jsmn_user_clear(&p->user);
 1535 }
 1536 
 1537 void
 1538 jsmn_session_free_array(struct session *p, size_t sz)
 1539 {
 1540 	size_t i;
 1541 	for (i = 0; i < sz; i++)
 1542 		jsmn_session_clear(&p[i]);
 1543 	free(p);
 1544 }
 1545 
 1546 int
 1547 jsmn_session_array(struct session **p, size_t *sz, const char *buf, const jsmntok_t *t, size_t toksz)
 1548 {
 1549 	size_t i, j;
 1550 	int rc;
 1551 
 1552 	*sz = 0;
 1553 	*p = NULL;
 1554 
 1555 	if (toksz < 1 || t[0].type != JSMN_ARRAY)
 1556 		return 0;
 1557 
 1558 	*sz = t[0].size;
 1559 	if ((*p = calloc(*sz, sizeof(struct session))) == NULL)
 1560 		return -1;
 1561 
 1562 	for (i = j = 0; i < *sz; i++) {
 1563 		rc = jsmn_session(&(*p)[i], buf, &t[j+1], toksz - j);
 1564 		if (rc <= 0)
 1565 			return rc;
 1566 		j += rc;
 1567 	}
 1568 	return j + 1;
 1569 }
 1570 
 1571 int
 1572 valid_session_userid(struct kpair *p)
 1573 {
 1574 	if (!kvalid_int(p))
 1575 		return 0;
 1576 	return 1;
 1577 }
 1578 
 1579 int
 1580 valid_session_token(struct kpair *p)
 1581 {
 1582 	if (!kvalid_int(p))
 1583 		return 0;
 1584 	return 1;
 1585 }
 1586 
 1587 int
 1588 valid_session_mtime(struct kpair *p)
 1589 {
 1590 	if (!kvalid_int(p))
 1591 		return 0;
 1592 	return 1;
 1593 }
 1594 
 1595 int
 1596 valid_session_id(struct kpair *p)
 1597 {
 1598 	if (!kvalid_int(p))
 1599 		return 0;
 1600 	return 1;
 1601 }
 1602 
 1603 void
 1604 db_session_iterate_foo(struct ksql *db, session_cb cb, void *arg, const char *v1,
 1605      time_t v2)
 1606 {
 1607 	struct ksqlstmt *stmt;
 1608 	struct session p;
 1609 
 1610 	ksql_stmt_alloc(db, &stmt,
 1611 		stmts[STMT_SESSION_BY_SEARCH_0],
 1612 		STMT_SESSION_BY_SEARCH_0);
 1613 	ksql_bind_str(stmt, 0, v1);
 1614 	ksql_bind_int(stmt, 1, v2);
 1615 	while (ksql_stmt_step(stmt) == KSQL_ROW) {
 1616 		db_session_fill_r(&p, stmt, NULL);
 1617 		(*cb)(&p, arg);
 1618 		db_session_unfill_r(&p);
 1619 	}
 1620 	ksql_stmt_free(stmt);
 1621 }
 1622 
 1623 int
 1624 db_session_delete_by_id_eq(struct ksql *db, int64_t v1)
 1625 {
 1626 	struct ksqlstmt *stmt;
 1627 	enum ksqlc c;
 1628 
 1629 	ksql_stmt_alloc(db, &stmt,
 1630 		stmts[STMT_SESSION_DELETE_0],
 1631 		STMT_SESSION_DELETE_0);
 1632 	ksql_bind_int(stmt, 0, v1);
 1633 	c = ksql_stmt_cstep(stmt);
 1634 	ksql_stmt_free(stmt);
 1635 	return(KSQL_DONE == c ? 1 : (KSQL_CONSTRAINT == c ? 0 : -1));
 1636 }
 1637