Allow indicating recurring SEPA donations in payproc-post.
[payproc.git] / src / preorder.c
1 /* preorder.c - Access to the preorder database.
2  * Copyright (C) 2015 g10 Code GmbH
3  *
4  * This file is part of Payproc.
5  *
6  * Payproc 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 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Payproc 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 /* The Database used for preorders is pretty simple:  Just a single table:
21
22    CREATE TABLE preorder (
23      ref   TEXT NOT NULL PRIMARY KEY,  -- The "ABCDE" part of ABCDE-NN.
24      refnn INTEGER NOT NULL,           -- The "NN"    part of ABCDE-NN
25      created TEXT NOT NULL,            -- Timestamp
26      paid TEXT,                        -- Timestamp of last payment
27      npaid INTEGER NOT NULL,           -- Total number of payments
28      amount TEXT NOT NULL,             -- with decimal digit; thus TEXT.
29      currency TEXT NOT NULL,
30      desc TEXT,   -- Description of the order
31      email TEXT,  -- Optional mail address.
32      meta TEXT    -- Using the format from the journal.
33    )
34
35
36   Expiring entries can be done using
37
38      DELETE from preorder
39      WHERE julianday(created) < julianday('now', '-30 days')
40            AND paid IS NULL;
41
42   this has not been implemented here but should be done at startup and
43   once a day.  Note that 'paid' tracks actual payments using this ref.
44   We do not delete it from the DB so that the ref can be used for
45   recurring payments.
46
47  */
48
49 #include <config.h>
50
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
54 #include <time.h>
55 #include <npth.h>
56 #include <gcrypt.h>
57 #include <sqlite3.h>
58
59 #include "util.h"
60 #include "logging.h"
61 #include "payprocd.h"
62 #include "journal.h"
63 #include "membuf.h"
64 #include "dbutil.h"
65 #include "currency.h"
66 #include "preorder.h"
67
68
69
70 /* The name of the preorder database file.  */
71 static const char preorder_db_fname[] = "/var/lib/payproc/preorder.db";
72 static const char preorder_test_db_fname[] = "/var/lib/payproc-test/preorder.db";
73
74 /* The database handle used for the preorder database.  This handle
75    may only used after a successful open_preorder_db call and not
76    after a close_preorder_db call.  The lock variable is maintained by
77    the mentioned open and close functions. */
78 static sqlite3 *preorder_db;
79 static npth_mutex_t preorder_db_lock = NPTH_MUTEX_INITIALIZER;
80
81 /* This is a prepared statement for the INSERT operation.  It is
82    protected by preorder_db_lock.  */
83 static sqlite3_stmt *preorder_insert_stmt;
84
85 /* This is a prepared statement for the UPDATE operation.  It is
86    protected by preorder_db_lock.  */
87 static sqlite3_stmt *preorder_update_stmt;
88
89 /* This is a prepared statement for the SELECT by REF operation.  It
90    is protected by preorder_db_lock.  */
91 static sqlite3_stmt *preorder_select_stmt;
92
93 /* This is a prepared statement for the SELECT by REFNN operation.  It
94    is protected by preorder_db_lock.  */
95 static sqlite3_stmt *preorder_selectrefnn_stmt;
96
97 /* This is a prepared statement for the SELECT all operation.  It
98    is protected by preorder_db_lock.  */
99 static sqlite3_stmt *preorder_selectlist_stmt;
100
101
102
103 \f
104 /* Create a Sepa-Ref field and store it in BUFFER.  The format is:
105
106      AAAAA-NN
107
108   with AAAAA being uppercase letters or digits and NN a value between
109   10 and 99.  Thus the entire length of the returned string is 8.  We
110   use a base 28 alphabet for the A values with the first A restricted
111   to a letter.  Some letters are left out because they might be
112   misrepresented due to OCR scanning.  There are about 11 million
113   different values for AAAAA. */
114 static void
115 make_sepa_ref (char *buffer, size_t bufsize)
116 {
117   static char codes[28] = { 'A', 'B', 'C', 'D', 'E', 'G', 'H', 'J',
118                             'K', 'L', 'N', 'R', 'S', 'T', 'W', 'X',
119                             'Y', 'Z', '0', '1', '2', '3', '4', '5',
120                             '6', '7', '8', '9' };
121   unsigned char nonce[5];
122   int i;
123   unsigned int n;
124
125   if (bufsize < 9)
126     BUG ();
127
128   gcry_create_nonce (nonce, sizeof nonce);
129   buffer[0] = codes[nonce[0] % 18];
130   for (i=1; i < 5; i++)
131     buffer[i] = codes[nonce[i] % 28];
132   buffer[5] = '-';
133   n = (((unsigned int)nonce[0] << 24) | (nonce[1] << 16)
134        | (nonce[2] << 8) | nonce[3]);
135   i = 10 + (n % 90);
136   buffer [6] = '0' + i / 10;
137   buffer [7] = '0' + i % 10;
138   buffer [8] = 0;
139 }
140
141
142 /* Relinquishes the lock on the database handle and if DO_CLOSE is
143    true also close the database handle.  Note that we usually keep the
144    database open for the lifetime of the process.  */
145 static void
146 close_preorder_db (int do_close)
147 {
148   int res;
149
150   if (do_close && preorder_db)
151     {
152       res = sqlite3_close (preorder_db);
153       if (res == SQLITE_BUSY)
154         {
155           sqlite3_finalize (preorder_insert_stmt);
156           preorder_insert_stmt = NULL;
157           sqlite3_finalize (preorder_update_stmt);
158           preorder_update_stmt = NULL;
159           sqlite3_finalize (preorder_select_stmt);
160           preorder_select_stmt = NULL;
161           sqlite3_finalize (preorder_selectrefnn_stmt);
162           preorder_selectrefnn_stmt = NULL;
163           sqlite3_finalize (preorder_selectlist_stmt);
164           preorder_selectlist_stmt = NULL;
165           res = sqlite3_close (preorder_db);
166         }
167       if (res)
168         log_error ("failed to close the preorder db: %s\n",
169                    sqlite3_errstr (res));
170       preorder_db = NULL;
171     }
172
173   res = npth_mutex_unlock (&preorder_db_lock);
174   if (res)
175     log_fatal ("failed to release preorder db lock: %s\n",
176                gpg_strerror (gpg_error_from_errno (res)));
177 }
178
179
180 /* This function opens or creates the preorder database.  If the
181    database is already open it merly takes a lock ion the handle. */
182 static gpg_error_t
183 open_preorder_db (void)
184 {
185   int res;
186   sqlite3_stmt *stmt;
187   const char *db_fname = opt.livemode? preorder_db_fname:preorder_test_db_fname;
188
189   res = npth_mutex_lock (&preorder_db_lock);
190   if (res)
191     log_fatal ("failed to acquire preorder db lock: %s\n",
192                gpg_strerror (gpg_error_from_errno (res)));
193   if (preorder_db)
194     return 0; /* Good: Already open.  */
195
196   /* Database has not yet been opened.  Open or create it, make sure
197      the tables exist, and prepare the required statements.  We use
198      our own locking instead of the more complex serialization sqlite
199      would have to do. */
200
201   res = sqlite3_open_v2 (db_fname,
202                          &preorder_db,
203                          (SQLITE_OPEN_READWRITE
204                           | SQLITE_OPEN_CREATE
205                           | SQLITE_OPEN_NOMUTEX),
206                          NULL);
207   if (res)
208     {
209       log_error ("error opening '%s': %s\n",
210                  db_fname, sqlite3_errstr (res));
211       close_preorder_db (1);
212       return gpg_error (GPG_ERR_GENERAL);
213     }
214   sqlite3_extended_result_codes (preorder_db, 1);
215
216
217   /* Create the tables if needed.  */
218   res = sqlite3_prepare_v2 (preorder_db,
219                             "CREATE TABLE IF NOT EXISTS preorder ("
220                             "ref      TEXT NOT NULL PRIMARY KEY,"
221                             "refnn    INTEGER NOT NULL,"
222                             "created  TEXT NOT NULL,"
223                             "paid TEXT,"
224                             "npaid INTEGER NOT NULL,"
225                             "amount   TEXT NOT NULL,"
226                             "currency TEXT NOT NULL,"
227                             "desc     TEXT,"
228                             "email    TEXT,"
229                             "meta     TEXT,"
230                             "recur    INTEGER"
231                             ")",
232                             -1, &stmt, NULL);
233   if (res)
234     {
235       log_error ("error creating preorder table (prepare): %s\n",
236                  sqlite3_errstr (res));
237       close_preorder_db (1);
238       return gpg_error (GPG_ERR_GENERAL);
239     }
240
241   res = sqlite3_step (stmt);
242   sqlite3_finalize (stmt);
243   if (res != SQLITE_DONE)
244     {
245       log_error ("error creating preorder table: %s\n", sqlite3_errstr (res));
246       close_preorder_db (1);
247       return gpg_error (GPG_ERR_GENERAL);
248     }
249
250   /* Add the new column recur to the table.  */
251   res = sqlite3_prepare_v2 (preorder_db,
252                             "ALTER TABLE preorder ADD COLUMN \n"
253                             "recur INTEGER",
254                             -1, &stmt, NULL);
255   if (!res)
256     {
257       res = sqlite3_step (stmt);
258       sqlite3_finalize (stmt);
259       if (res != SQLITE_DONE)
260         {
261           log_error ("error adding column to preorder table: %s\n",
262                      sqlite3_errstr (res));
263           close_preorder_db (1);
264           return gpg_error (GPG_ERR_GENERAL);
265         }
266     }
267
268
269   /* Prepare an insert statement.  */
270   res = sqlite3_prepare_v2 (preorder_db,
271                             "INSERT INTO preorder VALUES ("
272                             "?1,?2,?3,NULL,0,?4,?5,?6,?7,?8,?9"
273                             ")",
274                             -1, &stmt, NULL);
275   if (res)
276     {
277       log_error ("error preparing insert statement: %s\n",
278                  sqlite3_errstr (res));
279       close_preorder_db (1);
280       return gpg_error (GPG_ERR_GENERAL);
281     }
282   preorder_insert_stmt = stmt;
283
284   /* Prepare an update statement.  */
285   res = sqlite3_prepare_v2 (preorder_db,
286                             "UPDATE preorder SET"
287                             " paid = ?2,"
288                             " npaid = npaid + 1"
289                             " WHERE ref=?1",
290                             -1, &stmt, NULL);
291   if (res)
292     {
293       log_error ("error preparing update statement: %s\n",
294                  sqlite3_errstr (res));
295       close_preorder_db (1);
296       return gpg_error (GPG_ERR_GENERAL);
297     }
298   preorder_update_stmt = stmt;
299
300   /* Prepare a select statement.  */
301   res = sqlite3_prepare_v2 (preorder_db,
302                             "SELECT * FROM preorder WHERE ref=?1",
303                             -1, &stmt, NULL);
304   if (res)
305     {
306       log_error ("error preparing select statement: %s\n",
307                  sqlite3_errstr (res));
308       close_preorder_db (1);
309       return gpg_error (GPG_ERR_GENERAL);
310     }
311   preorder_select_stmt = stmt;
312
313   /* Prepare a select-refnn statement.  */
314   res = sqlite3_prepare_v2 (preorder_db,
315                             "SELECT * FROM preorder "
316                             "WHERE refnn=?1 ORDER BY ref",
317                             -1, &stmt, NULL);
318   if (res)
319     {
320       log_error ("error preparing selectrefnn statement: %s\n",
321                  sqlite3_errstr (res));
322       close_preorder_db (1);
323       return gpg_error (GPG_ERR_GENERAL);
324     }
325   preorder_selectrefnn_stmt = stmt;
326
327   /* Prepare a select-list statement.  */
328   res = sqlite3_prepare_v2 (preorder_db,
329                             "SELECT * FROM preorder "
330                             "ORDER BY created DESC, refnn ASC",
331                             -1, &stmt, NULL);
332   if (res)
333     {
334       log_error ("error preparing select statement: %s\n",
335                  sqlite3_errstr (res));
336       close_preorder_db (1);
337       return gpg_error (GPG_ERR_GENERAL);
338     }
339   preorder_selectlist_stmt = stmt;
340
341   return 0;
342 }
343
344
345 /* Insert a record into the preorder table.  The values are taken from
346    the dictionary at DICTP.  On return a Sepa-Ref value will have been
347    inserted into it; that may happen even on error.  */
348 static gpg_error_t
349 insert_preorder_record (keyvalue_t *dictp)
350 {
351   gpg_error_t err;
352   int res;
353   keyvalue_t dict = *dictp;
354   char separef[9];
355   char *buf;
356   char datetime_buf [DB_DATETIME_SIZE];
357   int retrycount = 0;
358
359  retry:
360   make_sepa_ref (separef, sizeof separef);
361   err = keyvalue_put (dictp, "Sepa-Ref", separef);
362   if (err)
363     return err;
364   dict = *dictp;
365
366   sqlite3_reset (preorder_insert_stmt);
367
368   separef[5] = 0;
369   res = sqlite3_bind_text (preorder_insert_stmt,
370                            1, separef, -1, SQLITE_TRANSIENT);
371   if (!res)
372     res = sqlite3_bind_int (preorder_insert_stmt,
373                             2, atoi (separef + 6));
374   if (!res)
375     res = sqlite3_bind_text (preorder_insert_stmt,
376                              3, db_datetime_now (datetime_buf),
377                              -1, SQLITE_TRANSIENT);
378   if (!res)
379     res = sqlite3_bind_text (preorder_insert_stmt,
380                              4, keyvalue_get_string (dict, "Amount"),
381                              -1, SQLITE_TRANSIENT);
382   if (!res)
383     res = sqlite3_bind_text (preorder_insert_stmt,
384                              5, "EUR", -1, SQLITE_STATIC);
385   if (!res)
386     res = sqlite3_bind_text (preorder_insert_stmt,
387                              6, keyvalue_get (dict, "Desc"),
388                              -1, SQLITE_TRANSIENT);
389   if (!res)
390     res = sqlite3_bind_text (preorder_insert_stmt,
391                              7, keyvalue_get (dict, "Email"),
392                              -1, SQLITE_TRANSIENT);
393   if (!res)
394     {
395       buf = meta_field_to_string (dict);
396       if (!buf)
397         res = sqlite3_bind_null (preorder_insert_stmt, 8);
398       else
399         res = sqlite3_bind_text (preorder_insert_stmt, 8, buf, -1, es_free);
400     }
401   if (!res)
402     res = sqlite3_bind_int (preorder_insert_stmt,
403                             9, atoi (keyvalue_get_string (dict, "Recur")));
404
405   if (res)
406     {
407       log_error ("error binding a value for the preorder table: %s\n",
408                  sqlite3_errstr (res));
409       return gpg_error (GPG_ERR_GENERAL);
410     }
411
412   res = sqlite3_step (preorder_insert_stmt);
413   if (res == SQLITE_DONE)
414     return 0;
415
416   /* In case we hit the same primary key we need to retry.  This is
417      limited to 11000 retries (~0.1% of the primary key space).  */
418   if (res == SQLITE_CONSTRAINT_PRIMARYKEY && ++retrycount < 11000)
419     goto retry;
420
421   log_error ("error inserting into preorder table: %s (%d)\n",
422              sqlite3_errstr (res), res);
423   return gpg_error (GPG_ERR_GENERAL);
424 }
425
426
427 static gpg_error_t
428 get_text_column (sqlite3_stmt *stmt, int idx, int icol, const char *name,
429                  keyvalue_t *dictp)
430 {
431   gpg_error_t err;
432   const char *s;
433
434   s = sqlite3_column_text (stmt, icol);
435   if (!s && sqlite3_errcode (preorder_db) == SQLITE_NOMEM)
436     err = gpg_error (GPG_ERR_ENOMEM);
437   else if (!strcmp (name, "Meta"))
438     err = s? keyvalue_put_meta (dictp, s) : 0;
439   else
440     err = keyvalue_put_idx (dictp, name, idx, s);
441
442   return err;
443 }
444
445
446 /* Put all columns into DICTP.  */
447 static gpg_error_t
448 get_columns (sqlite3_stmt *stmt, int idx, keyvalue_t *dictp)
449 {
450   gpg_error_t err;
451   char separef[9];
452   const char *s;
453   int i;
454
455   s = sqlite3_column_text (stmt, 0);
456   if (!s && sqlite3_errcode (preorder_db) == SQLITE_NOMEM)
457     err = gpg_error (GPG_ERR_ENOMEM);
458   else
459     {
460       strncpy (separef, s, 5);
461       i = sqlite3_column_int (stmt, 1);
462       if (!i && sqlite3_errcode (preorder_db) == SQLITE_NOMEM)
463         err = gpg_error (GPG_ERR_ENOMEM);
464       else if (i < 0 || i > 99)
465         err = gpg_error (GPG_ERR_INV_DATA);
466       else
467         {
468           snprintf (separef+5, 4, "-%02d", i);
469           err = keyvalue_put_idx (dictp, "Sepa-Ref", idx, separef);
470         }
471     }
472
473   if (!err)
474     err = get_text_column (stmt, idx, 2, "Created", dictp);
475   if (!err)
476     err = get_text_column (stmt, idx, 3, "Paid", dictp);
477   if (!err)
478     err = get_text_column (stmt, idx, 4, "N-Paid", dictp);
479   if (!err)
480     err = get_text_column (stmt, idx, 5, "Amount", dictp);
481   if (!err)
482     err = get_text_column (stmt, idx, 6, "Currency", dictp);
483   if (!err)
484     err = get_text_column (stmt, idx, 7, "Desc", dictp);
485   if (!err)
486     err = get_text_column (stmt, idx, 8, "Email", dictp);
487   if (!err)
488     err = get_text_column (stmt, idx, 9, "Meta", dictp);
489   if (!err)
490     err = get_text_column (stmt, idx, 10, "Recur", dictp);
491
492   return err;
493 }
494
495
496 /* Format columns and put the formatted line into DICTP under the
497    key "D[idx]".  */
498 static gpg_error_t
499 format_columns (sqlite3_stmt *stmt, int idx, keyvalue_t *dictp)
500 {
501   gpg_error_t err;
502   membuf_t mb;
503   const char *s;
504   int i;
505
506   init_membuf (&mb, 512);
507
508   s = sqlite3_column_text (stmt, 0);
509   if (!s && sqlite3_errcode (preorder_db) == SQLITE_NOMEM)
510     {
511       err = gpg_error (GPG_ERR_ENOMEM);
512       goto leave;
513     }
514
515   i = sqlite3_column_int (stmt, 1);
516   if (!i && sqlite3_errcode (preorder_db) == SQLITE_NOMEM)
517     {
518       err = gpg_error (GPG_ERR_ENOMEM);
519       goto leave;
520     }
521   put_membuf_printf (&mb, "|%s-%02d", s, i);
522
523   for (i = 2; i <= 9; i++)
524     {
525       put_membuf_chr (&mb, '|');
526       s = sqlite3_column_text (stmt, i);
527       if (!s && sqlite3_errcode (preorder_db) == SQLITE_NOMEM)
528         {
529           err = gpg_error (GPG_ERR_ENOMEM);
530           goto leave;
531         }
532       if (!s)
533         ;
534       else if (strchr (s, '|'))
535         {
536           for (; *s; s++)
537             if (*s == '|')
538               put_membuf_str (&mb, "=7C");
539             else
540               put_membuf_chr (&mb, *s);
541         }
542       else
543         put_membuf_str (&mb, s);
544     }
545
546   i = sqlite3_column_int (stmt, 10);
547   if (!i && sqlite3_errcode (preorder_db) == SQLITE_NOMEM)
548     {
549       err = gpg_error (GPG_ERR_ENOMEM);
550       goto leave;
551     }
552   put_membuf_printf (&mb, "|%d", i);
553
554   put_membuf_chr (&mb, '|');
555
556
557   {
558     char *p;
559
560     put_membuf_chr (&mb, 0);
561     p = get_membuf (&mb, NULL);
562     if (!p)
563       err = gpg_error_from_syserror ();
564     else
565       {
566         err = keyvalue_put_idx (dictp, "D", idx, p);
567         xfree (p);
568       }
569   }
570
571  leave:
572   xfree (get_membuf (&mb, NULL));
573   return err;
574 }
575
576
577 /* Get a record from the preorder table.  The values are stored at the
578    dictionary at DICTP.  */
579 static gpg_error_t
580 get_preorder_record (const char *ref, keyvalue_t *dictp)
581 {
582   gpg_error_t err;
583   int res;
584
585   if (strlen (ref) != 5)
586     return gpg_error (GPG_ERR_INV_LENGTH);
587
588   sqlite3_reset (preorder_select_stmt);
589
590   res = sqlite3_bind_text (preorder_select_stmt,
591                            1, ref, 5, SQLITE_TRANSIENT);
592   if (res)
593     {
594       log_error ("error binding a value for the preorder table: %s\n",
595                  sqlite3_errstr (res));
596       return gpg_error (GPG_ERR_GENERAL);
597     }
598
599   res = sqlite3_step (preorder_select_stmt);
600   if (res == SQLITE_ROW)
601     {
602       res = SQLITE_OK;
603       err = get_columns (preorder_select_stmt, -1, dictp);
604     }
605   else if (res == SQLITE_DONE)
606     {
607       res = SQLITE_OK;
608       err = gpg_error (GPG_ERR_NOT_FOUND);
609     }
610   else
611     err = gpg_error (GPG_ERR_GENERAL);
612
613   if (err)
614     {
615       if (res == SQLITE_OK)
616         log_error ("error selecting from preorder table: %s\n",
617                    gpg_strerror (err));
618       else
619         log_error ("error selecting from preorder table: %s [%s (%d)]\n",
620                    gpg_strerror (err), sqlite3_errstr (res), res);
621     }
622   return err;
623 }
624
625
626 /* List records from the preorder table.  The values are stored at the
627    dictionary at DICTP with a D[n] key.  The number of records is
628    stored at R_COUNT.  */
629 static gpg_error_t
630 list_preorder_records (const char *refnn,
631                        keyvalue_t *dictp, unsigned int *r_count)
632 {
633   gpg_error_t err;
634   sqlite3_stmt *stmt;
635   int count = 0;
636   int res;
637
638   stmt = *refnn? preorder_selectrefnn_stmt : preorder_selectlist_stmt;
639
640   sqlite3_reset (stmt);
641
642   if (*refnn)
643     {
644       res = sqlite3_bind_text (stmt, 1, refnn, -1, SQLITE_TRANSIENT);
645       if (res)
646         {
647           log_error ("error binding a value for the preorder table: %s\n",
648                      sqlite3_errstr (res));
649           return gpg_error (GPG_ERR_GENERAL);
650         }
651     }
652
653  next:
654   res = sqlite3_step (stmt);
655   if (res == SQLITE_ROW)
656     {
657       res = SQLITE_OK;
658       err = format_columns (stmt, count, dictp);
659       if (!err)
660         {
661           if (++count)
662             goto next;
663           err = gpg_error (GPG_ERR_WOULD_WRAP);
664         }
665     }
666   else if (res == SQLITE_DONE)
667     {
668       res = SQLITE_OK;
669       err = 0;
670     }
671   else
672     err = gpg_error (GPG_ERR_GENERAL);
673
674   if (err)
675     {
676       if (res == SQLITE_OK)
677         log_error ("error selecting from preorder table: %s\n",
678                    gpg_strerror (err));
679       else
680         log_error ("error selecting from preorder table: %s [%s (%d)]\n",
681                    gpg_strerror (err), sqlite3_errstr (res), res);
682     }
683   else
684     *r_count = count;
685   return err;
686 }
687
688
689 /* Update a row specified by REF in the preorder table.  Also update
690    the timestamp field at DICTP. */
691 static gpg_error_t
692 update_preorder_record (const char *ref, keyvalue_t *dictp)
693 {
694   gpg_error_t err;
695   int res;
696   char datetime_buf [DB_DATETIME_SIZE];
697
698   if (strlen (ref) != 5)
699     return gpg_error (GPG_ERR_INV_LENGTH);
700
701   sqlite3_reset (preorder_update_stmt);
702
703   res = sqlite3_bind_text (preorder_update_stmt,
704                            1, ref, 5,
705                            SQLITE_TRANSIENT);
706   if (!res)
707     res = sqlite3_bind_text (preorder_update_stmt,
708                              2, db_datetime_now (datetime_buf), -1,
709                              SQLITE_TRANSIENT);
710   if (res)
711     {
712       log_error ("error binding a value for the preorder table: %s\n",
713                  sqlite3_errstr (res));
714       return gpg_error (GPG_ERR_GENERAL);
715     }
716
717   res = sqlite3_step (preorder_update_stmt);
718   if (res == SQLITE_DONE)
719     {
720       if (!sqlite3_changes (preorder_db))
721         err = gpg_error (GPG_ERR_NOT_FOUND);
722       else
723         err = 0;
724     }
725   else
726     err = gpg_error (GPG_ERR_GENERAL);
727
728   if (!err)
729     err = keyvalue_put (dictp, "_timestamp", datetime_buf);
730
731   if (gpg_err_code (err) == GPG_ERR_GENERAL)
732     log_error ("error updating preorder table: %s [%s (%d)]\n",
733                gpg_strerror (err), sqlite3_errstr (res), res);
734   else
735     log_error ("error updating preorder table: %s\n",
736                gpg_strerror (err));
737   return err;
738 }
739
740
741 /* Create a new preorder record and store it.  Inserts a "Sepa-Ref"
742    into DICT.  */
743 gpg_error_t
744 preorder_store_record (keyvalue_t *dictp)
745 {
746   gpg_error_t err;
747
748   err = open_preorder_db ();
749   if (err)
750     return err;
751
752   err = insert_preorder_record (dictp);
753   close_preorder_db (0);
754
755   return err;
756 }
757
758
759 /* Take the Sepa-Ref from DICTP, fetch the row, and update DICTP with
760    that data.  On error return an error code.  Note that DICTP may
761    even be changed on error.  */
762 gpg_error_t
763 preorder_get_record (keyvalue_t *dictp)
764 {
765   gpg_error_t err;
766   char separef[9];
767   const char *s;
768   char *p;
769
770   s = keyvalue_get (*dictp, "Sepa-Ref");
771   if (!s || strlen (s) >= sizeof separef)
772     return gpg_error (GPG_ERR_INV_LENGTH);
773   strcpy (separef, s);
774   p = strchr (separef, '-');
775   if (p)
776     *p = 0;
777
778   err = open_preorder_db ();
779   if (err)
780     return err;
781
782   err = get_preorder_record (separef, dictp);
783
784   close_preorder_db (0);
785
786   return err;
787 }
788
789
790 /* Take the number Sepa-Ref from DICTP, fetch the row, and update DICTP with
791    that data.  On error return an error code.  Note that DICTP may
792    even be changed on error.  */
793 gpg_error_t
794 preorder_list_records (keyvalue_t *dictp, unsigned int *r_count)
795 {
796   gpg_error_t err;
797   char refnn[3];
798   const char *s;
799
800   *r_count = 0;
801   s = keyvalue_get (*dictp, "Refnn");
802   if (s)
803     {
804       if (strlen (s) != 2)
805         return gpg_error (GPG_ERR_INV_LENGTH);
806       strcpy (refnn, s);
807     }
808   else
809     *refnn = 0;
810
811   err = open_preorder_db ();
812   if (err)
813     return err;
814
815   err = list_preorder_records (refnn, dictp, r_count);
816
817   close_preorder_db (0);
818
819   return err;
820 }
821
822
823 /* Take the Sepa-Ref from NEWDATA and update the corresponding row with
824    the other data from NEWDATA.  On error return an error code.  */
825 gpg_error_t
826 preorder_update_record (keyvalue_t *newdata)
827 {
828   gpg_error_t err;
829   char separef[9];
830   const char *s;
831   char *p;
832   keyvalue_t olddata = NULL;
833   int recur;
834
835   s = keyvalue_get (*newdata, "Sepa-Ref");
836   if (!s || strlen (s) >= sizeof separef)
837     return gpg_error (GPG_ERR_INV_LENGTH);
838   strcpy (separef, s);
839   p = strchr (separef, '-');
840   if (p)
841     *p = 0;
842
843   err = open_preorder_db ();
844   if (err)
845     return err;
846
847   err = get_preorder_record (separef, &olddata);
848   if (err)
849     goto leave;
850
851   s = keyvalue_get_string (olddata, "Recur");
852   if (!valid_recur_p (s, &recur))
853     {
854       err = keyvalue_put (newdata, "failure-mesg",
855                           "Invalid value for 'Recur' in preorder record");
856       if (!err)
857         err = gpg_error (GPG_ERR_MISSING_VALUE);
858       goto leave;
859     }
860
861   /* Get the supplied Recur value and macth it with the preorder.  */
862   s = keyvalue_get_string (*newdata, "Recur");
863   if (!strcmp (s, "*") && !recur)
864     {
865       err = keyvalue_put (newdata, "failure-mesg",
866                           "Recurring donation but not claimed in preorder");
867       if (!err)
868         err = gpg_error (GPG_ERR_CONFLICT);
869       goto leave;
870     }
871   else if (!*s && recur)
872     {
873       err = keyvalue_put (newdata, "failure-mesg",
874                           "Single donation but preorder claims recurring");
875       if (!err)
876         err = gpg_error (GPG_ERR_CONFLICT);
877       goto leave;
878     }
879   else if (valid_recur_p (s, &recur))
880     {
881       /* RECUR updated - this overrides what we have in the preorder
882        * record.  */
883     }
884   else
885     {
886       err = keyvalue_put (newdata, "failure-mesg",
887                           "Invalid value for 'Recur' supplied");
888       if (!err)
889         err = gpg_error (GPG_ERR_MISSING_VALUE);
890       goto leave;
891     }
892
893
894   /* Update OLDDATA with the actual amount so that we can put the
895      correct amount into the log.  */
896   err = keyvalue_put (&olddata, "Amount",
897                       keyvalue_get_string (*newdata, "Amount"));
898   if (err)
899     goto leave;
900
901   /* We pass OLDDATA so that _timestamp will be set.  */
902   err = update_preorder_record (separef, &olddata);
903   if (err)
904     goto leave;
905
906   /* FIXME: Unfortunately the journal function creates its own
907      timestamp.  */
908   jrnl_store_charge_record (&olddata, PAYMENT_SERVICE_SEPA, recur);
909
910
911  leave:
912   close_preorder_db (0);
913   keyvalue_release (olddata);
914
915   return err;
916 }