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')) {
107 ret
->error
= DB_ERROR_WRONG_NUM_FIELDS
;
111 if (!sk_OPENSSL_PSTRING_push(ret
->data
, pp
))
119 sk_OPENSSL_PSTRING_free(ret
->data
);
120 OPENSSL_free(ret
->index
);
121 OPENSSL_free(ret
->qual
);
127 OPENSSL_STRING
*TXT_DB_get_by_index(TXT_DB
*db
, int idx
,
128 OPENSSL_STRING
*value
)
131 LHASH_OF(OPENSSL_STRING
) *lh
;
133 if (idx
>= db
->num_fields
) {
134 db
->error
= DB_ERROR_INDEX_OUT_OF_RANGE
;
139 db
->error
= DB_ERROR_NO_INDEX
;
142 ret
= lh_OPENSSL_STRING_retrieve(lh
, value
);
143 db
->error
= DB_ERROR_OK
;
147 int TXT_DB_create_index(TXT_DB
*db
, int field
, int (*qual
) (OPENSSL_STRING
*),
148 OPENSSL_LH_HASHFUNC hash
, OPENSSL_LH_COMPFUNC cmp
)
150 LHASH_OF(OPENSSL_STRING
) *idx
;
154 if (field
>= db
->num_fields
) {
155 db
->error
= DB_ERROR_INDEX_OUT_OF_RANGE
;
158 /* FIXME: we lose type checking at this point */
159 if ((idx
= (LHASH_OF(OPENSSL_STRING
) *)OPENSSL_LH_new(hash
, cmp
)) == NULL
) {
160 db
->error
= DB_ERROR_MALLOC
;
163 n
= sk_OPENSSL_PSTRING_num(db
->data
);
164 for (i
= 0; i
< n
; i
++) {
165 r
= sk_OPENSSL_PSTRING_value(db
->data
, i
);
166 if ((qual
!= NULL
) && (qual(r
) == 0))
168 if ((r
= lh_OPENSSL_STRING_insert(idx
, r
)) != NULL
) {
169 db
->error
= DB_ERROR_INDEX_CLASH
;
170 db
->arg1
= sk_OPENSSL_PSTRING_find(db
->data
, r
);
172 lh_OPENSSL_STRING_free(idx
);
176 lh_OPENSSL_STRING_free(db
->index
[field
]);
177 db
->index
[field
] = idx
;
178 db
->qual
[field
] = qual
;
182 long TXT_DB_write(BIO
*out
, TXT_DB
*db
)
184 long i
, j
, n
, nn
, l
, tot
= 0;
189 if ((buf
= BUF_MEM_new()) == NULL
)
191 n
= sk_OPENSSL_PSTRING_num(db
->data
);
193 for (i
= 0; i
< n
; i
++) {
194 pp
= sk_OPENSSL_PSTRING_value(db
->data
, i
);
197 for (j
= 0; j
< nn
; j
++) {
201 if (!BUF_MEM_grow_clean(buf
, (int)(l
* 2 + nn
)))
205 for (j
= 0; j
< nn
; j
++) {
219 if (BIO_write(out
, buf
->data
, (int)j
) != j
)
229 int TXT_DB_insert(TXT_DB
*db
, OPENSSL_STRING
*row
)
234 for (i
= 0; i
< db
->num_fields
; i
++) {
235 if (db
->index
[i
] != NULL
) {
236 if ((db
->qual
[i
] != NULL
) && (db
->qual
[i
] (row
) == 0))
238 r
= lh_OPENSSL_STRING_retrieve(db
->index
[i
], row
);
240 db
->error
= DB_ERROR_INDEX_CLASH
;
247 /* We have passed the index checks, now just append and insert */
248 if (!sk_OPENSSL_PSTRING_push(db
->data
, row
)) {
249 db
->error
= DB_ERROR_MALLOC
;
253 for (i
= 0; i
< db
->num_fields
; i
++) {
254 if (db
->index
[i
] != NULL
) {
255 if ((db
->qual
[i
] != NULL
) && (db
->qual
[i
] (row
) == 0))
257 (void)lh_OPENSSL_STRING_insert(db
->index
[i
], row
);
265 void TXT_DB_free(TXT_DB
*db
)
273 if (db
->index
!= NULL
) {
274 for (i
= db
->num_fields
- 1; i
>= 0; i
--)
275 lh_OPENSSL_STRING_free(db
->index
[i
]);
276 OPENSSL_free(db
->index
);
278 OPENSSL_free(db
->qual
);
279 if (db
->data
!= NULL
) {
280 for (i
= sk_OPENSSL_PSTRING_num(db
->data
) - 1; i
>= 0; i
--) {
282 * check if any 'fields' have been allocated from outside of the
285 p
= sk_OPENSSL_PSTRING_value(db
->data
, i
);
286 max
= p
[db
->num_fields
]; /* last address */
287 if (max
== NULL
) { /* new row */
288 for (n
= 0; n
< db
->num_fields
; n
++)
291 for (n
= 0; n
< db
->num_fields
; n
++) {
292 if (((p
[n
] < (char *)p
) || (p
[n
] > max
)))
296 OPENSSL_free(sk_OPENSSL_PSTRING_value(db
->data
, i
));
298 sk_OPENSSL_PSTRING_free(db
->data
);