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