• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include <libwebsockets.h>
26 #include <private-lib-core.h>
27 
28 #include <sqlite3.h>
29 
30 /*
31  * we get one of these per matching result from the query
32  */
33 
34 static int
lws_struct_sq3_deser_cb(void * priv,int cols,char ** cv,char ** cn)35 lws_struct_sq3_deser_cb(void *priv, int cols, char **cv, char **cn)
36 {
37 	lws_struct_args_t *a = (lws_struct_args_t *)priv;
38 	char *u = lwsac_use_zero(&a->ac, a->dest_len, a->ac_block_size);
39 	lws_dll2_owner_t *o = (lws_dll2_owner_t *)a->cb_arg;
40 	const lws_struct_map_t *map = a->map_st[0];
41 	int n, mems = a->map_entries_st[0];
42 	long long li;
43 	size_t lim;
44 	char **pp;
45 	char *s;
46 
47 	if (!u) {
48 		lwsl_err("OOM\n");
49 
50 		return 1;
51 	}
52 
53 	lws_dll2_add_tail((lws_dll2_t *)((char *)u + a->toplevel_dll2_ofs), o);
54 
55 	while (mems--) {
56 		for (n = 0; n < cols; n++) {
57 			if (!cv[n] || strcmp(cn[n], map->colname))
58 				continue;
59 
60 			switch (map->type) {
61 			case LSMT_SIGNED:
62 				if (map->aux == sizeof(signed char)) {
63 					signed char *pc;
64 					pc = (signed char *)(u + map->ofs);
65 					*pc = atoi(cv[n]);
66 					break;
67 				}
68 				if (map->aux == sizeof(short)) {
69 					short *ps;
70 					ps = (short *)(u + map->ofs);
71 					*ps = atoi(cv[n]);
72 					break;
73 				}
74 				if (map->aux == sizeof(int)) {
75 					int *pi;
76 					pi = (int *)(u + map->ofs);
77 					*pi = atoi(cv[n]);
78 					break;
79 				}
80 				if (map->aux == sizeof(long)) {
81 					long *pl;
82 					pl = (long *)(u + map->ofs);
83 					*pl = atol(cv[n]);
84 					break;
85 				}
86 				{
87 					long long *pll;
88 					pll = (long long *)(u + map->ofs);
89 					*pll = atoll(cv[n]);
90 				}
91 				break;
92 
93 			case LSMT_UNSIGNED:
94 				if (map->aux == sizeof(unsigned char)) {
95 					unsigned char *pc;
96 					pc = (unsigned char *)(u + map->ofs);
97 					*pc = atoi(cv[n]);
98 					break;
99 				}
100 				if (map->aux == sizeof(unsigned short)) {
101 					unsigned short *ps;
102 					ps = (unsigned short *)(u + map->ofs);
103 					*ps = atoi(cv[n]);
104 					break;
105 				}
106 				if (map->aux == sizeof(unsigned int)) {
107 					unsigned int *pi;
108 					pi = (unsigned int *)(u + map->ofs);
109 					*pi = atoi(cv[n]);
110 					break;
111 				}
112 				if (map->aux == sizeof(unsigned long)) {
113 					unsigned long *pl;
114 					pl = (unsigned long *)(u + map->ofs);
115 					*pl = atol(cv[n]);
116 					break;
117 				}
118 				{
119 					unsigned long long *pll;
120 					pll = (unsigned long long *)(u + map->ofs);
121 					*pll = atoll(cv[n]);
122 				}
123 				break;
124 
125 			case LSMT_BOOLEAN:
126 				li = 0;
127 				if (!strcmp(cv[n], "true") ||
128 				    !strcmp(cv[n], "TRUE") || cv[n][0] == '1')
129 					li = 1;
130 				if (map->aux == sizeof(char)) {
131 					char *pc;
132 					pc = (char *)(u + map->ofs);
133 					*pc = (char)li;
134 					break;
135 				}
136 				if (map->aux == sizeof(int)) {
137 					int *pi;
138 					pi = (int *)(u + map->ofs);
139 					*pi = (int)li;
140 				} else {
141 					uint64_t *p64;
142 					p64 = (uint64_t *)(u + map->ofs);
143 					*p64 = li;
144 				}
145 				break;
146 
147 			case LSMT_STRING_CHAR_ARRAY:
148 				s = (char *)(u + map->ofs);
149 				lim = map->aux;
150 				lws_strncpy(s, cv[n], lim);
151 				break;
152 
153 			case LSMT_STRING_PTR:
154 				pp = (char **)(u + map->ofs);
155 				lim = strlen(cv[n]);
156 				s = lwsac_use(&a->ac, lim + 1, a->ac_block_size);
157 				if (!s)
158 					return 1;
159 				*pp = s;
160 				memcpy(s, cv[n], lim);
161 				s[lim] = '\0';
162 				break;
163 			default:
164 				break;
165 			}
166 		}
167 		map++;
168 	}
169 
170 	return 0;
171 }
172 
173 /*
174  * Call this with an LSM_SCHEMA map, its colname is the table name and its
175  * type information describes the toplevel type.  Schema is dereferenced and
176  * put in args before the actual sq3 query, which is given the child map.
177  */
178 
179 int
lws_struct_sq3_deserialize(sqlite3 * pdb,const char * filter,const char * order,const lws_struct_map_t * schema,lws_dll2_owner_t * o,struct lwsac ** ac,int start,int _limit)180 lws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order,
181 			   const lws_struct_map_t *schema, lws_dll2_owner_t *o,
182 			   struct lwsac **ac, int start, int _limit)
183 {
184 	char s[250], where[250];
185 	lws_struct_args_t a;
186 	int limit = _limit < 0 ? -_limit : _limit;
187 
188 	memset(&a, 0, sizeof(a));
189 	a.cb_arg = o; /* lws_dll2_owner tracking query result objects */
190 	a.map_st[0]  = schema->child_map;
191 	a.map_entries_st[0] = schema->child_map_size;
192 	a.dest_len = schema->aux; /* size of toplevel object to allocate */
193 	a.toplevel_dll2_ofs = schema->ofs;
194 
195 	lws_dll2_owner_clear(o);
196 
197 	where[0] = '\0';
198 	lws_snprintf(where, sizeof(where), " where _lws_idx >= %llu %s",
199 			     (unsigned long long)start, filter ? filter : "");
200 
201 	lws_snprintf(s, sizeof(s) - 1, "select * "
202 		     "from %s %s order by _lws_idx%s %slimit %d;",
203 		     schema->colname, where, order ? order : "",
204 				     _limit < 0 ? "desc " : "", limit);
205 
206 	if (sqlite3_exec(pdb, s, lws_struct_sq3_deser_cb, &a, NULL) != SQLITE_OK) {
207 		lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb));
208 		lwsac_free(&a.ac);
209 		return -1;
210 	}
211 
212 	*ac = a.ac;
213 
214 	return 0;
215 }
216 
217 /*
218  * This takes a struct and turns it into an sqlite3 UPDATE, using the given
219  * schema... which has one LSM_SCHEMA_DLL2 entry wrapping the actual schema
220  */
221 
222 static int
_lws_struct_sq3_ser_one(sqlite3 * pdb,const lws_struct_map_t * schema,uint32_t idx,void * st)223 _lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema,
224 			uint32_t idx, void *st)
225 {
226 	const lws_struct_map_t *map = schema->child_map;
227 	int n, m, pk = 0, nentries = schema->child_map_size;
228 	size_t sql_est = 46 + strlen(schema->colname) + 1;
229 		/* "insert into  (_lws_idx, ) values (00000001,);" ...
230 		 * plus the table name */
231 	uint8_t *stb = (uint8_t *)st;
232 	const char *p;
233 	char *sql;
234 
235 	/*
236 	 * Figure out an estimate for the length of the populated sqlite
237 	 * command, and then malloc it up
238 	 */
239 
240 	for (n = 0; n < nentries; n++) {
241 		sql_est += strlen(map[n].colname) + 2;
242 		switch (map[n].type) {
243 		case LSMT_SIGNED:
244 		case LSMT_UNSIGNED:
245 		case LSMT_BOOLEAN:
246 
247 			switch (map[n].aux) {
248 			case 1:
249 				sql_est += 3 + 2;
250 				break;
251 			case 2:
252 				sql_est += 5 + 2;
253 				break;
254 			case 4:
255 				sql_est += 10 + 2;
256 				break;
257 			case 8:
258 				sql_est += 20 + 2;
259 				break;
260 			}
261 
262 			if (map[n].type == LSMT_SIGNED)
263 				sql_est++; /* minus sign */
264 
265 			break;
266 		case LSMT_STRING_CHAR_ARRAY:
267 			sql_est += lws_sql_purify_len((const char *)st +
268 							map[n].ofs) + 2;
269 			break;
270 
271 		case LSMT_STRING_PTR:
272 			p = *((const char * const *)&stb[map[n].ofs]);
273 			sql_est += (p ? lws_sql_purify_len(p) : 0) + 2;
274 			break;
275 
276 		default:
277 			lwsl_err("%s: unsupported type\n", __func__);
278 			assert(0);
279 			break;
280 		}
281 	}
282 
283 	sql = malloc(sql_est);
284 	if (!sql)
285 		return -1;
286 
287 	m = lws_snprintf(sql, sql_est, "insert into %s(_lws_idx, ",
288 			 schema->colname);
289 
290 	/*
291 	 * First explicit integer type is primary key autoincrement, should
292 	 * not be specified
293 	 */
294 
295 	for (n = 0; n < nentries; n++) {
296 		if (!pk && map[n].type == LSMT_UNSIGNED) {
297 			pk = 1;
298 			continue;
299 		}
300 		m += lws_snprintf(sql + m, sql_est - m,
301 				  n == nentries - 1 ? "%s" : "%s, ",
302 				  map[n].colname);
303 	}
304 
305 	m += lws_snprintf(sql + m, sql_est - m, ") values(%u, ", idx);
306 
307 	pk = 0;
308 	for (n = 0; n < nentries; n++) {
309 		uint64_t uu64;
310 		size_t q;
311 
312 		if (!pk && map[n].type == LSMT_UNSIGNED) {
313 			pk = 1;
314 			continue;
315 		}
316 
317 		switch (map[n].type) {
318 		case LSMT_SIGNED:
319 		case LSMT_UNSIGNED:
320 		case LSMT_BOOLEAN:
321 
322 			uu64 = 0;
323 			for (q = 0; q < map[n].aux; q++)
324 				uu64 |= ((uint64_t)stb[map[n].ofs + q] <<
325 								(q << 3));
326 
327 			if (map[n].type == LSMT_SIGNED)
328 				m += lws_snprintf(sql + m, sql_est - m, "%lld",
329 						  (long long)(int64_t)uu64);
330 			else
331 				m += lws_snprintf(sql + m, sql_est - m, "%llu",
332 						  (unsigned long long)uu64);
333 			break;
334 
335 		case LSMT_STRING_CHAR_ARRAY:
336 			sql[m++] = '\'';
337 			lws_sql_purify(sql + m, (const char *)&stb[map[n].ofs],
338 				       sql_est - m - 4);
339 			m += strlen(sql + m);
340 			sql[m++] = '\'';
341 			break;
342 		case LSMT_STRING_PTR:
343 			p = *((const char * const *)&stb[map[n].ofs]);
344 			sql[m++] = '\'';
345 			if (p) {
346 				lws_sql_purify(sql + m, p, sql_est - m - 4);
347 				m += strlen(sql + m);
348 			}
349 			sql[m++] = '\'';
350 			break;
351 		default:
352 			lwsl_err("%s: unsupported type\n", __func__);
353 			assert(0);
354 			break;
355 		}
356 
357 		if (n != nentries - 1) {
358 			if (sql_est - m < 6)
359 				return -1;
360 			sql[m++] = ',';
361 			sql[m++] = ' ';
362 		}
363 	}
364 
365 	lws_snprintf(sql + m, sql_est - m, ");");
366 
367 	n = sqlite3_exec(pdb, sql, NULL, NULL, NULL);
368 	free(sql);
369 	if (n != SQLITE_OK) {
370 		lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb));
371 		return -1;
372 	}
373 
374 	return 0;
375 }
376 
377 int
lws_struct_sq3_serialize(sqlite3 * pdb,const lws_struct_map_t * schema,lws_dll2_owner_t * owner,uint32_t manual_idx)378 lws_struct_sq3_serialize(sqlite3 *pdb, const lws_struct_map_t *schema,
379 			 lws_dll2_owner_t *owner, uint32_t manual_idx)
380 {
381 	uint32_t idx = manual_idx;
382 
383 	lws_start_foreach_dll(struct lws_dll2 *, p, owner->head) {
384 		void *item = (void *)((uint8_t *)p - schema->ofs_clist);
385 		if (_lws_struct_sq3_ser_one(pdb, schema, idx++, item))
386 			return 1;
387 
388 	} lws_end_foreach_dll(p);
389 
390 	return 0;
391 }
392 
393 int
lws_struct_sq3_create_table(sqlite3 * pdb,const lws_struct_map_t * schema)394 lws_struct_sq3_create_table(sqlite3 *pdb, const lws_struct_map_t *schema)
395 {
396 	const lws_struct_map_t *map = schema->child_map;
397 	int map_size = schema->child_map_size, subsequent = 0;
398 	char s[2048], *p = s, *end = &s[sizeof(s) - 1],
399 	     *pri = " primary key autoincrement", *use;
400 
401 	p += lws_snprintf(p, end - p,
402 			  "create table if not exists %s (_lws_idx integer, ",
403 			  schema->colname);
404 
405 	while (map_size--) {
406 		if (map->type > LSMT_STRING_PTR) {
407 			map++;
408 			continue;
409 		}
410 		if (subsequent && (end - p) > 4) {
411 			*p++ = ',';
412 			*p++ = ' ';
413 		}
414 		subsequent = 1;
415 		if (map->type < LSMT_STRING_CHAR_ARRAY) {
416 			use = "";
417 			if (map->colname[0] != '_') /* _lws_idx is not primary key */
418 				use = pri;
419 			p += lws_snprintf(p, end - p, "%s integer%s",
420 					  map->colname, use);
421 			if (map->colname[0] != '_')
422 				pri = "";
423 		} else
424 			p += lws_snprintf(p, end - p, "%s varchar",
425 					  map->colname);
426 
427 		map++;
428 	}
429 
430 	p += lws_snprintf(p, end - p, ");");
431 
432 	if (sqlite3_exec(pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
433 		lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb));
434 
435 		return -1;
436 	}
437 
438 	return 0;
439 }
440 
441 int
lws_struct_sq3_open(struct lws_context * context,const char * sqlite3_path,sqlite3 ** pdb)442 lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path,
443 		    sqlite3 **pdb)
444 {
445 	int uid = 0, gid = 0;
446 
447 	if (sqlite3_open_v2(sqlite3_path, pdb,
448 			    SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
449 			    NULL) != SQLITE_OK) {
450 		lwsl_err("%s: Unable to open db %s: %s\n",
451 			 __func__, sqlite3_path, sqlite3_errmsg(*pdb));
452 
453 		return 1;
454 	}
455 
456 	lws_get_effective_uid_gid(context, &uid, &gid);
457 	if (uid)
458 		chown(sqlite3_path, uid, gid);
459 	chmod(sqlite3_path, 0600);
460 
461 	lwsl_notice("%s: created %s owned by %u:%u mode 0600\n", __func__,
462 			sqlite3_path, (unsigned int)uid, (unsigned int)gid);
463 
464 	sqlite3_extended_result_codes(*pdb, 1);
465 
466 	return 0;
467 }
468 
469 int
lws_struct_sq3_close(sqlite3 ** pdb)470 lws_struct_sq3_close(sqlite3 **pdb)
471 {
472 	if (!*pdb)
473 		return 0;
474 
475 	sqlite3_close(*pdb);
476 	*pdb = NULL;
477 
478 	return 0;
479 }
480