source: src/router/proftpd/contrib/mod_sql_sqlite.c @ 17876

Last change on this file since 17876 was 17876, checked in by BrainSlayer, 18 months ago

update proftp

File size: 31.5 KB
Line 
1/*
2 * ProFTPD: mod_sql_sqlite -- Support for connecting to SQLite databases
3 *
4 * Copyright (c) 2004-2011 TJ Saunders
5 * 
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
19 *
20 * As a special exemption, TJ Saunders gives permission to link this program
21 * with OpenSSL, and distribute the resulting executable, without including
22 * the source code for OpenSSL in the source distribution.
23 *
24 * $Id: mod_sql_sqlite.c,v 1.23 2011/05/23 20:56:40 castaglia Exp $
25 * $Libraries: -lsqlite3 $
26 */
27
28#define MOD_SQL_SQLITE_VERSION          "mod_sql_sqlite/0.4"
29
30#include "conf.h"
31#include "privs.h"
32#include "mod_sql.h"
33
34#include <sqlite3.h>
35
36/* Make sure the version of proftpd is as necessary. */
37#if PROFTPD_VERSION_NUMBER < 0x0001030001
38# error "ProFTPD 1.3.0rc1 or later required"
39#endif
40
41module sql_sqlite_module;
42
43#define SQL_SQLITE_START_FL_NOW         1
44#define SQL_SQLITE_START_FL_EXCL        2
45
46typedef struct db_conn_struct {
47  char *dsn;
48  char *user;
49  char *pass;
50
51  sqlite3 *dbh;
52
53} db_conn_t;
54
55typedef struct conn_entry_struct {
56  char *name;
57  void *data;
58
59  /* Timer handling */
60  int timer;
61  int ttl;
62
63  /* Connection handling */
64  unsigned int nconn;
65
66} conn_entry_t;
67
68#define DEF_CONN_POOL_SIZE      10
69
70static pool *conn_pool = NULL;
71static array_header *conn_cache = NULL;
72
73MODRET sql_sqlite_close(cmd_rec *);
74
75static conn_entry_t *sql_sqlite_get_conn(char *name) {
76  register unsigned int i = 0;
77
78  if (!name)
79    return NULL;
80
81  for (i = 0; i < conn_cache->nelts; i++) {
82    conn_entry_t *entry = ((conn_entry_t **) conn_cache->elts)[i];
83
84    if (strcmp(name, entry->name) == 0)
85      return entry;
86  }
87
88  return NULL;
89}
90
91static void *sql_sqlite_add_conn(pool *p, char *name, db_conn_t *conn) {
92  conn_entry_t *entry = NULL;
93
94  if (!name || !conn || !p)
95    return NULL;
96 
97  if (sql_sqlite_get_conn(name))
98    return NULL;
99
100  entry = (conn_entry_t *) pcalloc(p, sizeof(conn_entry_t));
101  entry->name = name;
102  entry->data = conn;
103
104  *((conn_entry_t **) push_array(conn_cache)) = entry;
105
106  return entry;
107}
108
109static int sql_sqlite_timer_cb(CALLBACK_FRAME) {
110  register unsigned int i = 0;
111 
112  for (i = 0; i < conn_cache->nelts; i++) {
113    conn_entry_t *entry = ((conn_entry_t **) conn_cache->elts)[i];
114
115    if (entry->timer == p2) {
116      cmd_rec *cmd = NULL;
117
118      sql_log(DEBUG_INFO, "timer expired for connection '%s'", entry->name);
119
120      cmd = pr_cmd_alloc(conn_pool, 2, entry->name, "1");
121      sql_sqlite_close(cmd);
122      destroy_pool(cmd->pool);
123
124      entry->timer = 0;
125    }
126  }
127
128  return 0;
129}
130
131/* The result set from handling SQLite queries is built up by the callback
132 * function exec_cb(), and stored here.
133 */
134static int result_ncols = 0;
135static array_header *result_list = NULL;
136
137static int exec_cb(void *n, int ncols, char **cols,
138    char **colnames) {
139  register unsigned int i;
140  char ***row;
141  cmd_rec *cmd = n;
142
143  if (result_list == NULL) {
144    result_ncols = ncols;
145    result_list = make_array(cmd->tmp_pool, ncols, sizeof(char **));
146  }
147
148  row = push_array(result_list);
149  *row = pcalloc(cmd->tmp_pool, sizeof(char *) * ncols);
150
151  for (i = 0; i < ncols; i++) {
152    char *val = cols[i];
153    (*row)[i] = pstrdup(cmd->tmp_pool, val ? val : "NULL");
154  }
155
156  return 0;
157}
158
159static int exec_stmt(cmd_rec *cmd, db_conn_t *conn, char *stmt, char **errstr) {
160  int res;
161  char *ptr = NULL;
162  unsigned int nretries = 0;
163
164  PRIVS_ROOT
165  res = sqlite3_exec(conn->dbh, stmt, exec_cb, cmd, &ptr);
166  PRIVS_RELINQUISH
167
168  while (res != SQLITE_OK) {
169    if (res == SQLITE_BUSY) {
170      struct timeval tv;
171
172      sqlite3_free(ptr);
173
174      nretries++;
175      sql_log(DEBUG_FUNC, "attempt #%u, database busy, trying '%s' again",
176        nretries, stmt);
177
178      /* Sleep for short bit, then try again. */
179      tv.tv_sec = 0;
180      tv.tv_usec = 500000L;
181
182      if (select(0, NULL, NULL, NULL, &tv) < 0) {
183        if (errno == EINTR) {
184          pr_signals_handle();
185        }
186      }
187
188      PRIVS_ROOT
189      res = sqlite3_exec(conn->dbh, stmt, exec_cb, cmd, &ptr);
190      PRIVS_RELINQUISH
191
192      continue;
193    }
194
195    *errstr = pstrdup(cmd->pool, ptr);
196    sqlite3_free(ptr);
197
198    sql_log(DEBUG_FUNC, "error executing '%s': (%d) %s", stmt, res, *errstr);
199    return -1;
200  }
201
202  if (ptr)
203    sqlite3_free(ptr);
204
205  return 0;
206}
207
208static int query_start(cmd_rec *cmd, db_conn_t *conn, int flags,
209    char **errstr) {
210  char *start_txn = NULL;
211
212  switch (flags) {
213    case SQL_SQLITE_START_FL_NOW:
214      start_txn = pstrdup(cmd->tmp_pool, "BEGIN IMMEDIATE");
215      break;
216
217    case SQL_SQLITE_START_FL_EXCL:
218      start_txn = pstrdup(cmd->tmp_pool, "BEGIN EXCLUSIVE");
219      break;
220
221    default:
222      start_txn = pstrdup(cmd->tmp_pool, "BEGIN");
223      break;
224  }
225
226  return exec_stmt(cmd, conn, start_txn, errstr);
227}
228
229static int query_run(cmd_rec *cmd, db_conn_t *conn, char *query,
230    char **errstr) {
231  return exec_stmt(cmd, conn, query, errstr);
232}
233
234static int query_finish(cmd_rec *cmd, db_conn_t *conn, char **errstr) {
235  return exec_stmt(cmd, conn, pstrdup(cmd->tmp_pool, "COMMIT"), errstr);
236}
237
238static modret_t *sql_sqlite_get_data(cmd_rec *cmd) {
239  register unsigned int i;
240  unsigned int count, k = 0;
241  char **data;
242  sql_data_t *sd = pcalloc(cmd->tmp_pool, sizeof(sql_data_t));
243
244  if (result_list == NULL)
245    return mod_create_data(cmd, sd);
246
247  sd->rnum = result_list->nelts;
248  sd->fnum = result_ncols;
249  count = sd->rnum * sd->fnum;
250  data = pcalloc(cmd->tmp_pool, sizeof(char *) * (count + 1));
251
252  for (i = 0; i < result_list->nelts; i++) {
253    register unsigned int j;
254    char **row = ((char ***) result_list->elts)[i];
255
256    for (j = 0; j < result_ncols; j++)
257      data[k++] = pstrdup(cmd->tmp_pool, row[j]);
258  }
259
260  data[k] = NULL;
261  sd->data = data;
262
263  /* Reset these variables.  The memory in them is allocated from this
264   * same cmd_rec, and will be recovered when the cmd_rec is destroyed.
265   */
266  result_ncols = 0;
267  result_list = NULL;
268
269  return mod_create_data(cmd, sd);
270}
271
272MODRET sql_sqlite_open(cmd_rec *cmd) {
273  conn_entry_t *entry = NULL;
274  db_conn_t *conn = NULL;
275  int res;
276
277  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_open");
278
279  if (cmd->argc < 1) {
280    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_open");
281    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
282  }   
283
284  /* Get the named connection. */
285  entry = sql_sqlite_get_conn(cmd->argv[0]);
286  if (entry == NULL) {
287    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_open");
288    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
289      "unknown named connection");
290  }
291
292  conn = (db_conn_t *) entry->data;
293
294  /* If we're already open (nconn > 0), increment the number of connections.
295   * Reset our timer if we have one, and return HANDLED.
296   */
297  if (entry->nconn > 0) {
298    entry->nconn++;
299
300    if (entry->timer)
301      pr_timer_reset(entry->timer, &sql_sqlite_module);
302
303    sql_log(DEBUG_INFO, "'%s' connection count is now %u", entry->name,
304      entry->nconn);
305    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_open");
306    return PR_HANDLED(cmd);
307  }
308
309  PRIVS_ROOT
310  res = sqlite3_open(conn->dsn, &(conn->dbh));
311  PRIVS_RELINQUISH
312
313  if (res != SQLITE_OK) {
314    char *errstr = pstrdup(cmd->pool, sqlite3_errmsg(conn->dbh));
315
316    sql_log(DEBUG_FUNC, "error opening SQLite database '%s': %s",
317      conn->dsn, errstr);
318
319    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_open");
320
321    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
322  }
323
324  /* Tell SQLite to only use in-memory journals.  This is necessary for
325   * mod_sql_sqlite to work properly, for SQLLog statements, when a chroot
326   * is used.  Note that the MEMORY journal mode of SQLite is supported
327   * only for SQLite-3.6.5 and later.
328   */
329  res = sqlite3_exec(conn->dbh, "PRAGMA journal_mode = MEMORY;", NULL, NULL,
330    NULL);
331  if (res != SQLITE_OK) {
332    sql_log(DEBUG_FUNC, "error setting MEMORY journal mode: %s",
333      sqlite3_errmsg(conn->dbh));
334  }
335
336  /* Add some SQLite information to the logs. */
337  sql_log(DEBUG_INFO, MOD_SQL_SQLITE_VERSION ": SQLite version: %s",
338    sqlite3_libversion());
339
340  entry->nconn++;
341
342  if (pr_sql_conn_policy == SQL_CONN_POLICY_PERSESSION) {
343    /* If the connection policy is PERSESSION... */
344    if (entry->nconn == 1) {
345      /* ...and we are actually opening the first connection to the database;
346       * we want to make sure this connection stays open, after this first use
347       * (as per Bug#3290).  To do this, we re-bump the connection count.
348       */
349      entry->nconn++;
350    }
351
352  } else if (entry->ttl > 0) {
353    /* Set up our timer, if necessary. */
354    entry->timer = pr_timer_add(entry->ttl, -1, &sql_sqlite_module,
355      sql_sqlite_timer_cb, "sqlite connection ttl");
356
357    sql_log(DEBUG_INFO, "'%s' connection: %d second timer started",
358      entry->name, entry->ttl);
359
360    /* Timed connections get re-bumped so they don't go away when
361     * sql_sqlite_close() is called.
362     */
363    entry->nconn++;
364  }
365
366  sql_log(DEBUG_INFO, "'%s' connection opened", entry->name);
367  sql_log(DEBUG_INFO, "'%s' connection count is now %u", entry->name,
368    entry->nconn);
369
370  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_open");
371  return PR_HANDLED(cmd);
372}
373
374MODRET sql_sqlite_close(cmd_rec *cmd) {
375  conn_entry_t *entry = NULL;
376  db_conn_t *conn = NULL;
377
378  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_close");
379
380  if (cmd->argc < 1 || cmd->argc > 2) {
381    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_close");
382    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
383  }
384
385  /* Get the named connection. */
386  entry = sql_sqlite_get_conn(cmd->argv[0]);
387  if (entry == NULL) {
388    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_close");
389    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
390      "unknown named connection");
391  }
392
393  conn = (db_conn_t *) entry->data;
394
395  /* If we're closed already (nconn == 0), return HANDLED. */
396  if (entry->nconn == 0) {
397    sql_log(DEBUG_INFO, "'%s' connection count is now %u", entry->name,
398      entry->nconn);
399    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_close");
400    return PR_HANDLED(cmd);
401  }
402
403  /* Decrement nconn. If our count is 0 or we received a second arg, close
404   * the connection, explicitly set the counter to 0, and remove any timers.
405   */
406  if ((--entry->nconn) == 0 ||
407      (cmd->argc == 2 && cmd->argv[1])) {
408
409    if (conn->dbh) {
410      if (sqlite3_close(conn->dbh) != SQLITE_OK) {
411        sql_log(DEBUG_FUNC, "error closing SQLite database: %s",
412          sqlite3_errmsg(conn->dbh));
413      }
414
415      conn->dbh = NULL;
416    }
417
418    entry->nconn = 0;
419
420    if (entry->timer) {
421      pr_timer_remove(entry->timer, &sql_sqlite_module);
422      entry->timer = 0;
423      sql_log(DEBUG_INFO, "'%s' connection timer stopped", entry->name);
424    }
425
426    sql_log(DEBUG_INFO, "'%s' connection closed", entry->name);
427  }
428
429  sql_log(DEBUG_INFO, "'%s' connection count is now %u", entry->name,
430    entry->nconn);
431  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_close");
432 
433  return PR_HANDLED(cmd);
434}
435
436MODRET sql_sqlite_cleanup(cmd_rec *cmd) {
437  destroy_pool(conn_pool);
438  conn_pool = NULL;
439  conn_cache = NULL;
440
441  return mod_create_data(cmd, NULL);
442}
443
444MODRET sql_sqlite_def_conn(cmd_rec *cmd) {
445  char *name = NULL;
446  conn_entry_t *entry = NULL;
447  db_conn_t *conn = NULL;
448
449  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_defineconnection");
450
451  if (cmd->argc < 4 || cmd->argc > 5 || !cmd->argv[0]) {
452    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_defineconnection");
453    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
454  }
455
456  if (!conn_pool) {
457    pr_log_pri(PR_LOG_WARNING, "warning: the mod_sql_sqlite module has not "
458      "been properly intialized.  Please make sure your --with-modules "
459      "configure option lists mod_sql *before* mod_sql_sqlite, and recompile.");
460
461    sql_log(DEBUG_FUNC, "%s", "The mod_sql_sqlite module has not been properly "
462      "intialized.  Please make sure your --with-modules configure option "
463      "lists mod_sql *before* mod_sql_sqlite, and recompile.");
464    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_defineconnection");
465
466    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "uninitialized module");
467  }
468
469  conn = (db_conn_t *) palloc(conn_pool, sizeof(db_conn_t));
470
471  name = pstrdup(conn_pool, cmd->argv[0]);
472  conn->user = pstrdup(conn_pool, cmd->argv[1]);
473  conn->pass = pstrdup(conn_pool, cmd->argv[2]);
474  conn->dsn = pstrdup(conn_pool, cmd->argv[3]);
475
476  /* Insert the new conn_info into the connection hash */
477  entry = sql_sqlite_add_conn(conn_pool, name, (void *) conn);
478  if (entry == NULL) {
479    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_defineconnection");
480    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
481      "named connection already exists");
482  }
483
484  if (cmd->argc == 5) {
485    entry->ttl = (int) strtol(cmd->argv[4], (char **) NULL, 10);
486    if (entry->ttl >= 1) {
487      pr_sql_conn_policy = SQL_CONN_POLICY_TIMER;
488
489    } else {
490      entry->ttl = 0;
491    }
492  }
493
494  entry->timer = 0;
495  entry->nconn = 0;
496
497  sql_log(DEBUG_INFO, " name: '%s'", entry->name);
498  sql_log(DEBUG_INFO, "  dsn: '%s'", conn->dsn);
499  sql_log(DEBUG_INFO, "  ttl: '%d'", entry->ttl);
500
501  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_defineconnection");
502  return PR_HANDLED(cmd);
503}
504
505MODRET sql_sqlite_exit(cmd_rec *cmd) {
506  register unsigned int i = 0;
507
508  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_exit");
509
510  for (i = 0; i < conn_cache->nelts; i++) {
511    conn_entry_t *entry = ((conn_entry_t **) conn_cache->elts)[i];
512
513    if (entry->nconn > 0) {
514      cmd_rec *tmp = pr_cmd_alloc(conn_pool, 2, entry->name, "1");
515      sql_sqlite_close(tmp);
516      destroy_pool(tmp->pool);
517    }
518  }
519
520  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_exit");
521
522  return PR_HANDLED(cmd);
523}
524
525MODRET sql_sqlite_select(cmd_rec *cmd) {
526  conn_entry_t *entry = NULL;
527  db_conn_t *conn = NULL;
528  modret_t *mr = NULL;
529  char *errstr = NULL, *query = NULL;
530  cmd_rec *close_cmd;
531
532  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_select");
533
534  if (cmd->argc < 2) {
535    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_select");
536    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
537  }
538
539  /* Get the named connection. */
540  entry = sql_sqlite_get_conn(cmd->argv[0]);
541  if (entry == NULL) {
542    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_select");
543    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
544      "unknown named connection");
545  }
546 
547  conn = (db_conn_t *) entry->data;
548
549  mr = sql_sqlite_open(cmd);
550  if (MODRET_ERROR(mr)) {
551    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_select");
552    return mr;
553  }
554
555  /* Construct the query string. */
556  if (cmd->argc == 2) {
557    query = pstrcat(cmd->tmp_pool, "SELECT ", cmd->argv[1], NULL);
558
559  } else {
560    query = pstrcat(cmd->tmp_pool, cmd->argv[2], " FROM ", cmd->argv[1], NULL);
561
562    if (cmd->argc > 3 && cmd->argv[3])
563      query = pstrcat(cmd->tmp_pool, query, " WHERE ", cmd->argv[3], NULL);
564
565    if (cmd->argc > 4 && cmd->argv[4])
566      query = pstrcat(cmd->tmp_pool, query, " LIMIT ", cmd->argv[4], NULL);
567
568    if (cmd->argc > 5) {
569      register unsigned int i = 0;
570
571      /* Handle the optional arguments -- they're rare, so in this case
572       * we'll play with the already constructed query string, but in
573       * general we should probably take optional arguments into account
574       * and put the query string together later once we know what they are.
575       */
576   
577      for (i = 5; i < cmd->argc; i++) {
578        if (cmd->argv[i] &&
579            strcasecmp("DISTINCT", cmd->argv[i]) == 0)
580          query = pstrcat(cmd->tmp_pool, "DISTINCT ", query, NULL);
581      }
582    }
583
584    query = pstrcat(cmd->tmp_pool, "SELECT ", query, NULL);
585  }
586
587  /* Log the query string */
588  sql_log(DEBUG_INFO, "query \"%s\"", query);
589
590  /* Perform the query.  If it doesn't work, log the error, close the
591   * connection, then return the error from the query processing.
592   */
593
594  if (query_start(cmd, conn, 0, &errstr) < 0) {
595    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
596    sql_sqlite_close(close_cmd);
597    destroy_pool(close_cmd->pool);
598
599    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_select");
600    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
601  }
602
603  if (query_run(cmd, conn, query, &errstr) < 0) {
604    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
605    sql_sqlite_close(close_cmd);
606    destroy_pool(close_cmd->pool);
607
608    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_select");
609    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
610  }
611
612  if (query_finish(cmd, conn, &errstr) < 0) {
613    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
614    sql_sqlite_close(close_cmd);
615    destroy_pool(close_cmd->pool);
616
617    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_select");
618    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
619  }
620
621  mr = sql_sqlite_get_data(cmd);
622 
623  /* Close the connection, return the data. */
624  close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
625  sql_sqlite_close(close_cmd);
626  destroy_pool(close_cmd->pool);
627
628  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_select");
629  return mr;
630}
631
632MODRET sql_sqlite_insert(cmd_rec *cmd) {
633  conn_entry_t *entry = NULL;
634  db_conn_t *conn = NULL;
635  modret_t *mr = NULL;
636  char *errstr = NULL, *query = NULL;
637  cmd_rec *close_cmd;
638
639  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_insert");
640
641  if (cmd->argc != 2 &&
642      cmd->argc != 4) {
643    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_insert");
644    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
645  }
646
647  /* Get the named connection. */
648  entry = sql_sqlite_get_conn(cmd->argv[0]);
649  if (entry == NULL) {
650    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_insert");
651    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
652      "unknown named connection");
653  }
654
655  conn = (db_conn_t *) entry->data;
656
657  mr = sql_sqlite_open(cmd);
658  if (MODRET_ERROR(mr)) {
659    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_insert");
660    return mr;
661  }
662
663  /* Construct the query string. */
664  if (cmd->argc == 2) {
665    query = pstrcat(cmd->tmp_pool, "INSERT ", cmd->argv[1], NULL);
666
667  } else {
668    query = pstrcat(cmd->tmp_pool, "INSERT INTO ", cmd->argv[1],
669      " (", cmd->argv[2], ") VALUES (", cmd->argv[3], ")", NULL);
670  }
671
672  /* Log the query string */
673  sql_log(DEBUG_INFO, "query \"%s\"", query);
674
675  /* Perform the query.  If it doesn't work, log the error, close the
676   * connection (and log any errors there, too) then return the error
677   * from the query processing.
678   */
679
680  if (query_start(cmd, conn, SQL_SQLITE_START_FL_NOW, &errstr) < 0) {
681    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
682    sql_sqlite_close(close_cmd);
683    destroy_pool(close_cmd->pool);
684
685    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_insert");
686    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
687  }
688
689  if (query_run(cmd, conn, query, &errstr) < 0) {
690    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
691    sql_sqlite_close(close_cmd);
692    destroy_pool(close_cmd->pool);
693
694    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_insert");
695    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
696  }
697
698  if (query_finish(cmd, conn, &errstr) < 0) {
699    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
700    sql_sqlite_close(close_cmd);
701    destroy_pool(close_cmd->pool);
702
703    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_insert");
704    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
705  }
706
707  /* Reset these variables.  The memory in them is allocated from this
708   * same cmd_rec, and will be recovered when the cmd_rec is destroyed.
709   */
710  result_ncols = 0;
711  result_list = NULL;
712
713  /* Close the connection and return HANDLED. */
714  close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
715  sql_sqlite_close(close_cmd);
716  destroy_pool(close_cmd->pool);
717
718  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_insert");
719  return PR_HANDLED(cmd);
720}
721
722MODRET sql_sqlite_update(cmd_rec *cmd) {
723  conn_entry_t *entry = NULL;
724  db_conn_t *conn = NULL;
725  modret_t *mr = NULL;
726  char *errstr = NULL, *query = NULL;
727  cmd_rec *close_cmd;
728
729  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_update");
730
731  if (cmd->argc < 2 || cmd->argc > 4) {
732    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_update");
733    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
734  }
735
736  /* Get the named connection. */
737  entry = sql_sqlite_get_conn(cmd->argv[0]);
738  if (entry == NULL) {
739    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_update");
740    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
741      "unknown named connection");
742  }
743
744  conn = (db_conn_t *) entry->data;
745
746  mr = sql_sqlite_open(cmd);
747  if (MODRET_ERROR(mr)) {
748    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_update");
749    return mr;
750  }
751
752  /* Construct the query string. */
753  if (cmd->argc == 2) {
754    query = pstrcat(cmd->tmp_pool, "UPDATE ", cmd->argv[1], NULL);
755
756  } else {
757    query = pstrcat(cmd->tmp_pool, "UPDATE ", cmd->argv[1], " SET ",
758      cmd->argv[2], NULL);
759
760    if (cmd->argc > 3 &&
761        cmd->argv[3]) {
762      query = pstrcat(cmd->tmp_pool, query, " WHERE ", cmd->argv[3], NULL);
763    }
764  }
765
766  /* Log the query string. */
767  sql_log(DEBUG_INFO, "query \"%s\"", query);
768
769  /* Perform the query.  If it doesn't work close the connection, then
770   * return the error from the query processing.
771   */
772
773  if (query_start(cmd, conn, SQL_SQLITE_START_FL_NOW, &errstr) < 0) {
774    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
775    sql_sqlite_close(close_cmd);
776    destroy_pool(close_cmd->pool);
777
778    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_update");
779    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
780  }
781
782  if (query_run(cmd, conn, query, &errstr) < 0) {
783    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
784    sql_sqlite_close(close_cmd);
785    destroy_pool(close_cmd->pool);
786
787    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_update");
788    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
789  }
790
791  if (query_finish(cmd, conn, &errstr) < 0) {
792    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
793    sql_sqlite_close(close_cmd);
794    destroy_pool(close_cmd->pool);
795
796    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_update");
797    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
798  }
799
800  /* Reset these variables.  The memory in them is allocated from this
801   * same cmd_rec, and will be recovered when the cmd_rec is destroyed.
802   */
803  result_ncols = 0;
804  result_list = NULL;
805
806  /* Close the connection, return HANDLED.  */
807  close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
808  sql_sqlite_close(close_cmd);
809  destroy_pool(close_cmd->pool);
810
811  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_update");
812  return PR_HANDLED(cmd);
813}
814
815MODRET sql_sqlite_prepare(cmd_rec *cmd) {
816  if (cmd->argc != 1) {
817    return PR_ERROR(cmd);
818  }
819
820  conn_pool = (pool *) cmd->argv[0];
821
822  if (conn_cache == NULL) {
823    conn_cache = make_array(conn_pool, DEF_CONN_POOL_SIZE,
824      sizeof(conn_entry_t *));
825  }
826
827  return mod_create_data(cmd, NULL);
828}
829
830MODRET sql_sqlite_procedure(cmd_rec *cmd) {
831  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_procedure");
832
833  if (cmd->argc != 3) {
834    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_procedure");
835    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
836  }
837
838  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_procedure");
839  return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
840    "backend does not support procedures");
841}
842
843MODRET sql_sqlite_query(cmd_rec *cmd) {
844  conn_entry_t *entry = NULL;
845  db_conn_t *conn = NULL;
846  modret_t *mr = NULL;
847  char *errstr = NULL, *query = NULL;
848  cmd_rec *close_cmd;
849
850  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_query");
851
852  if (cmd->argc != 2) {
853    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_query");
854    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
855  }
856
857  /* Get the named connection. */
858  entry = sql_sqlite_get_conn(cmd->argv[0]);
859  if (entry == NULL) {
860    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_query");
861    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
862      "unknown named connection");
863  }
864
865  conn = (db_conn_t *) entry->data;
866
867  mr = sql_sqlite_open(cmd);
868  if (MODRET_ERROR(mr)) {
869    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_query");
870    return mr;
871  }
872
873  query = pstrdup(cmd->tmp_pool, cmd->argv[1]);
874
875  /* Log the query string */
876  sql_log(DEBUG_INFO, "query \"%s\"", query);
877
878  /* Perform the query.  If it doesn't work close the connection, then
879   * return the error from the query processing.
880   */
881
882  if (query_start(cmd, conn, 0, &errstr) < 0) {
883    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
884    sql_sqlite_close(close_cmd);
885    destroy_pool(close_cmd->pool);
886
887    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_query");
888    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
889  }
890
891  if (query_run(cmd, conn, query, &errstr) < 0) {
892    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
893    sql_sqlite_close(close_cmd);
894    destroy_pool(close_cmd->pool);
895
896    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_query");
897    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
898  }
899
900  if (query_finish(cmd, conn, &errstr) < 0) {
901    close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
902    sql_sqlite_close(close_cmd);
903    destroy_pool(close_cmd->pool);
904
905    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_query");
906    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr);
907  }
908
909  mr = sql_sqlite_get_data(cmd);
910 
911  /* Close the connection, return the data. */
912  close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
913  sql_sqlite_close(close_cmd);
914  destroy_pool(close_cmd->pool);
915
916  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_query");
917  return mr;
918}
919
920MODRET sql_sqlite_quote(cmd_rec *cmd) {
921  conn_entry_t *entry = NULL;
922  db_conn_t *conn = NULL;
923  modret_t *mr = NULL;
924  char *unescaped = NULL;
925  char *escaped = NULL;
926  char *tmp;
927  cmd_rec *close_cmd;
928
929  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_escapestring");
930
931  if (cmd->argc != 2) {
932    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_escapestring");
933    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
934  }
935
936  /* Get the named connection. */
937  entry = sql_sqlite_get_conn(cmd->argv[0]);
938  if (entry == NULL) {
939    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_escapestring");
940    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
941      "unknown named connection");
942  }
943
944  /* Make sure the connection is open. */
945  mr = sql_sqlite_open(cmd);
946  if (MODRET_ERROR(mr)) {
947    sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_escapestring");
948    return mr;
949  }
950
951  conn = (db_conn_t *) entry->data;
952
953  unescaped = cmd->argv[1];
954  tmp = sqlite3_mprintf("%q", unescaped);
955  escaped = pstrdup(cmd->pool, tmp);
956  sqlite3_free(tmp);
957
958  close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name);
959  sql_sqlite_close(close_cmd);
960  destroy_pool(close_cmd->pool);
961
962  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_escapestring");
963  return mod_create_data(cmd, escaped);
964}
965
966MODRET sql_sqlite_checkauth(cmd_rec *cmd) {
967  sql_log(DEBUG_FUNC, "%s", "entering \tsqlite cmd_checkauth");
968
969  if (cmd->argc != 3) {
970    sql_log(DEBUG_FUNC, "exiting \tsqlite cmd_checkauth");
971    return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "badly formed request");
972  }
973
974  sql_log(DEBUG_WARN, MOD_SQL_SQLITE_VERSION
975    ": SQLite does not support the 'Backend' SQLAuthType");
976  sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_checkauth");
977
978  /* SQLite doesn't provide this functionality. */
979  return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION,
980    "SQLite does not support the 'Backend' SQLAuthType");
981}
982
983MODRET sql_sqlite_identify(cmd_rec * cmd) {
984  sql_data_t *sd = NULL;
985
986  sd = (sql_data_t *) pcalloc(cmd->tmp_pool, sizeof(sql_data_t));
987  sd->data = (char **) pcalloc(cmd->tmp_pool, sizeof(char *) * 2);
988
989  sd->rnum = 1;
990  sd->fnum = 2;
991
992  sd->data[0] = MOD_SQL_SQLITE_VERSION;
993  sd->data[1] = MOD_SQL_API_V1;
994
995  return mod_create_data(cmd, (void *) sd);
996
997
998static cmdtable sql_sqlite_cmdtable[] = {
999  { CMD, "sql_checkauth",       G_NONE, sql_sqlite_checkauth,   FALSE, FALSE },
1000  { CMD, "sql_close",           G_NONE, sql_sqlite_close,       FALSE, FALSE },
1001  { CMD, "sql_cleanup",         G_NONE, sql_sqlite_cleanup,     FALSE, FALSE },
1002  { CMD, "sql_defineconnection",G_NONE, sql_sqlite_def_conn,    FALSE, FALSE },
1003  { CMD, "sql_escapestring",    G_NONE, sql_sqlite_quote,       FALSE, FALSE },
1004  { CMD, "sql_exit",            G_NONE, sql_sqlite_exit,        FALSE, FALSE },
1005  { CMD, "sql_identify",        G_NONE, sql_sqlite_identify,    FALSE, FALSE },
1006  { CMD, "sql_insert",          G_NONE, sql_sqlite_insert,      FALSE, FALSE },
1007  { CMD, "sql_open",            G_NONE, sql_sqlite_open,        FALSE, FALSE },
1008  { CMD, "sql_prepare",         G_NONE, sql_sqlite_prepare,     FALSE, FALSE },
1009  { CMD, "sql_procedure",       G_NONE, sql_sqlite_procedure,   FALSE, FALSE },
1010  { CMD, "sql_query",           G_NONE, sql_sqlite_query,       FALSE, FALSE },
1011  { CMD, "sql_select",          G_NONE, sql_sqlite_select,      FALSE, FALSE },
1012  { CMD, "sql_update",          G_NONE, sql_sqlite_update,      FALSE, FALSE },
1013  { 0, NULL }
1014};
1015
1016/* Event handlers
1017 */
1018
1019static void sql_sqlite_mod_load_ev(const void *event_data, void *user_data) {
1020  if (strcmp("mod_sql_sqlite.c", (const char *) event_data) == 0) {
1021    /* Register ourselves with mod_sql. */
1022    if (sql_register_backend("sqlite3", sql_sqlite_cmdtable) < 0) {
1023      pr_log_pri(PR_LOG_NOTICE, MOD_SQL_SQLITE_VERSION
1024        ": notice: error registering backend: %s", strerror(errno));
1025      pr_session_end(0);
1026    }
1027  }
1028}
1029
1030static void sql_sqlite_mod_unload_ev(const void *event_data, void *user_data) {
1031  if (strcmp("mod_sql_sqlite.c", (const char *) event_data) == 0) {
1032    /* Unegister ourselves with mod_sql. */
1033    if (sql_unregister_backend("sqlite3") < 0) {
1034      pr_log_pri(PR_LOG_NOTICE, MOD_SQL_SQLITE_VERSION
1035        ": notice: error unregistering backend: %s", strerror(errno));
1036      pr_session_end(0);
1037    }
1038
1039    pr_event_unregister(&sql_sqlite_module, NULL, NULL);
1040
1041    /* Note that we do NOT call sqlite3_shutdown() here, as SQLite may
1042     * also be being used by other modules.
1043     */
1044  }
1045}
1046
1047/* Initialization routines
1048 */
1049
1050static int sql_sqlite_init(void) {
1051
1052  /* Register listeners for the load and unload events. */
1053  pr_event_register(&sql_sqlite_module, "core.module-load",
1054    sql_sqlite_mod_load_ev, NULL);
1055  pr_event_register(&sql_sqlite_module, "core.module-unload",
1056    sql_sqlite_mod_unload_ev, NULL);
1057
1058  /* Check that the SQLite headers used match the version of the SQLite
1059   * library used.
1060   *
1061   * For now, we only log if there is a difference.
1062   */
1063  if (strcmp(sqlite3_libversion(), SQLITE_VERSION) != 0) {
1064    pr_log_pri(PR_LOG_ERR, MOD_SQL_SQLITE_VERSION
1065      ": compiled using SQLite version '%s' headers, but linked to "
1066      "SQLite version '%s' library", SQLITE_VERSION, sqlite3_libversion());
1067  }
1068
1069  pr_log_debug(DEBUG3, MOD_SQL_SQLITE_VERSION ": using SQLite %s",
1070    sqlite3_libversion());
1071
1072  return 0;
1073}
1074
1075static int sql_sqlite_sess_init(void) {
1076  if (conn_pool == NULL) {
1077    conn_pool = make_sub_pool(session.pool);
1078    pr_pool_tag(conn_pool, "SQLite connection pool");
1079  }
1080
1081  if (conn_cache == NULL) {
1082    conn_cache = make_array(make_sub_pool(session.pool), DEF_CONN_POOL_SIZE,
1083      sizeof(conn_entry_t *));
1084  }
1085
1086  return 0;
1087}
1088
1089/* Module API tables
1090 */
1091
1092module sql_sqlite_module = {
1093  NULL, NULL,
1094
1095  /* Module API version */
1096  0x20,
1097
1098  /* Module name */
1099  "sql_sqlite",
1100
1101  /* Module configuration directive table */
1102  NULL,
1103
1104  /* Module command handler table */
1105  NULL,
1106
1107  /* Module authentication handler table */
1108  NULL,
1109
1110  /* Module initialization */
1111  sql_sqlite_init,
1112
1113  /* Session initialization */
1114  sql_sqlite_sess_init,
1115
1116  /* Module version */
1117  MOD_SQL_SQLITE_VERSION
1118};
Note: See TracBrowser for help on using the repository browser.