2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
13 #include "internal/cryptlib.h"
14 #include <openssl/buffer.h>
15 #include <openssl/txt_db.h>
20 TXT_DB *TXT_DB_read(BIO *in, int num)
32 if ((buf = BUF_MEM_new()) == NULL)
34 if (!BUF_MEM_grow(buf, size))
37 if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
39 ret->num_fields = num;
42 if ((ret->data = sk_OPENSSL_PSTRING_new_null()) == NULL)
44 if ((ret->index = OPENSSL_malloc(sizeof(*ret->index) * num)) == NULL)
46 if ((ret->qual = OPENSSL_malloc(sizeof(*(ret->qual)) * num)) == NULL)
48 for (i = 0; i < num; i++) {
53 add = (num + 1) * sizeof(char *);
54 buf->data[size - 1] = '\0';
59 if (!BUF_MEM_grow_clean(buf, size))
62 buf->data[offset] = '\0';
63 BIO_gets(in, &(buf->data[offset]), size - offset);
65 if (buf->data[offset] == '\0')
67 if ((offset == 0) && (buf->data[0] == '#'))
69 i = strlen(&(buf->data[offset]));
71 if (buf->data[offset - 1] != '\n')
74 buf->data[offset - 1] = '\0'; /* blat the '\n' */
75 if ((p = OPENSSL_malloc(add + offset)) == NULL)
106 if ((n != num) || (*f != '\0')) {
108 ret->error = DB_ERROR_WRONG_NUM_FIELDS;
112 if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) {
122 sk_OPENSSL_PSTRING_free(ret->data);
123 OPENSSL_free(ret->index);
124 OPENSSL_free(ret->qual);
130 OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx,
131 OPENSSL_STRING *value)
134 LHASH_OF(OPENSSL_STRING) *lh;
136 if (idx >= db->num_fields) {
137 db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
142 db->error = DB_ERROR_NO_INDEX;
145 ret = lh_OPENSSL_STRING_retrieve(lh, value);
146 db->error = DB_ERROR_OK;
150 int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *),
151 OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC cmp)
153 LHASH_OF(OPENSSL_STRING) *idx;
154 OPENSSL_STRING *r, *k;
157 if (field >= db->num_fields) {
158 db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
161 /* FIXME: we lose type checking at this point */
162 if ((idx = (LHASH_OF(OPENSSL_STRING) *)OPENSSL_LH_new(hash, cmp)) == NULL) {
163 db->error = DB_ERROR_MALLOC;
166 n = sk_OPENSSL_PSTRING_num(db->data);
167 for (i = 0; i < n; i++) {
168 r = sk_OPENSSL_PSTRING_value(db->data, i);
169 if ((qual != NULL) && (qual(r) == 0))
171 if ((k = lh_OPENSSL_STRING_insert(idx, r)) != NULL) {
172 db->error = DB_ERROR_INDEX_CLASH;
173 db->arg1 = sk_OPENSSL_PSTRING_find(db->data, k);
175 lh_OPENSSL_STRING_free(idx);
178 if (lh_OPENSSL_STRING_retrieve(idx, r) == NULL) {
179 db->error = DB_ERROR_MALLOC;
180 lh_OPENSSL_STRING_free(idx);
184 lh_OPENSSL_STRING_free(db->index[field]);
185 db->index[field] = idx;
186 db->qual[field] = qual;
190 long TXT_DB_write(BIO *out, TXT_DB *db)
192 long i, j, n, nn, l, tot = 0;
197 if ((buf = BUF_MEM_new()) == NULL)
199 n = sk_OPENSSL_PSTRING_num(db->data);
201 for (i = 0; i < n; i++) {
202 pp = sk_OPENSSL_PSTRING_value(db->data, i);
205 for (j = 0; j < nn; j++) {
209 if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn)))
213 for (j = 0; j < nn; j++) {
227 if (BIO_write(out, buf->data, (int)j) != j)
237 int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row)
242 for (i = 0; i < db->num_fields; i++) {
243 if (db->index[i] != NULL) {
244 if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
246 r = lh_OPENSSL_STRING_retrieve(db->index[i], row);
248 db->error = DB_ERROR_INDEX_CLASH;
256 for (i = 0; i < db->num_fields; i++) {
257 if (db->index[i] != NULL) {
258 if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
260 (void)lh_OPENSSL_STRING_insert(db->index[i], row);
261 if (lh_OPENSSL_STRING_retrieve(db->index[i], row) == NULL)
265 if (!sk_OPENSSL_PSTRING_push(db->data, row))
270 db->error = DB_ERROR_MALLOC;
272 if (db->index[i] != NULL) {
273 if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
275 (void)lh_OPENSSL_STRING_delete(db->index[i], row);
282 void TXT_DB_free(TXT_DB *db)
290 if (db->index != NULL) {
291 for (i = db->num_fields - 1; i >= 0; i--)
292 lh_OPENSSL_STRING_free(db->index[i]);
293 OPENSSL_free(db->index);
295 OPENSSL_free(db->qual);
296 if (db->data != NULL) {
297 for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) {
299 * check if any 'fields' have been allocated from outside of the
302 p = sk_OPENSSL_PSTRING_value(db->data, i);
303 max = p[db->num_fields]; /* last address */
304 if (max == NULL) { /* new row */
305 for (n = 0; n < db->num_fields; n++)
308 for (n = 0; n < db->num_fields; n++) {
309 if (((p[n] < (char *)p) || (p[n] > max)))
313 OPENSSL_free(sk_OPENSSL_PSTRING_value(db->data, i));
315 sk_OPENSSL_PSTRING_free(db->data);