2 * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (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
)
31 if ((buf
= BUF_MEM_new()) == NULL
)
33 if (!BUF_MEM_grow(buf
, size
))
36 if ((ret
= OPENSSL_malloc(sizeof(*ret
))) == NULL
)
38 ret
->num_fields
= num
;
41 if ((ret
->data
= sk_OPENSSL_PSTRING_new_null()) == NULL
)
43 if ((ret
->index
= OPENSSL_malloc(sizeof(*ret
->index
) * num
)) == NULL
)
45 if ((ret
->qual
= OPENSSL_malloc(sizeof(*(ret
->qual
)) * num
)) == NULL
)
47 for (i
= 0; i
< num
; i
++) {
52 add
= (num
+ 1) * sizeof(char *);
53 buf
->data
[size
- 1] = '\0';
58 if (!BUF_MEM_grow_clean(buf
, size
))
61 buf
->data
[offset
] = '\0';
62 BIO_gets(in
, &(buf
->data
[offset
]), size
- offset
);
63 if (buf
->data
[offset
] == '\0')
65 if ((offset
== 0) && (buf
->data
[0] == '#'))
67 i
= strlen(&(buf
->data
[offset
]));
69 if (buf
->data
[offset
- 1] != '\n')
72 buf
->data
[offset
- 1] = '\0'; /* blat the '\n' */
73 if ((p
= OPENSSL_malloc(add
+ offset
)) == NULL
)
103 if ((n
!= num
) || (*f
!= '\0')) {
105 ret
->error
= DB_ERROR_WRONG_NUM_FIELDS
;
109 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
;
151 OPENSSL_STRING
*r
, *k
;
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 ((k
= lh_OPENSSL_STRING_insert(idx
, r
)) != NULL
) {
169 db
->error
= DB_ERROR_INDEX_CLASH
;
170 db
->arg1
= sk_OPENSSL_PSTRING_find(db
->data
, k
);
172 lh_OPENSSL_STRING_free(idx
);
175 if (lh_OPENSSL_STRING_retrieve(idx
, r
) == NULL
) {
176 db
->error
= DB_ERROR_MALLOC
;
177 lh_OPENSSL_STRING_free(idx
);
181 lh_OPENSSL_STRING_free(db
->index
[field
]);
182 db
->index
[field
] = idx
;
183 db
->qual
[field
] = qual
;
187 long TXT_DB_write(BIO
*out
, TXT_DB
*db
)
189 long i
, j
, n
, nn
, l
, tot
= 0;
194 if ((buf
= BUF_MEM_new()) == NULL
)
196 n
= sk_OPENSSL_PSTRING_num(db
->data
);
198 for (i
= 0; i
< n
; i
++) {
199 pp
= sk_OPENSSL_PSTRING_value(db
->data
, i
);
202 for (j
= 0; j
< nn
; j
++) {
206 if (!BUF_MEM_grow_clean(buf
, (int)(l
* 2 + nn
)))
210 for (j
= 0; j
< nn
; j
++) {
224 if (BIO_write(out
, buf
->data
, (int)j
) != j
)
234 int TXT_DB_insert(TXT_DB
*db
, OPENSSL_STRING
*row
)
239 for (i
= 0; i
< db
->num_fields
; i
++) {
240 if (db
->index
[i
] != NULL
) {
241 if ((db
->qual
[i
] != NULL
) && (db
->qual
[i
] (row
) == 0))
243 r
= lh_OPENSSL_STRING_retrieve(db
->index
[i
], row
);
245 db
->error
= DB_ERROR_INDEX_CLASH
;
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
);
258 if (lh_OPENSSL_STRING_retrieve(db
->index
[i
], row
) == NULL
)
262 if (!sk_OPENSSL_PSTRING_push(db
->data
, row
))
267 db
->error
= DB_ERROR_MALLOC
;
269 if (db
->index
[i
] != NULL
) {
270 if ((db
->qual
[i
] != NULL
) && (db
->qual
[i
] (row
) == 0))
272 (void)lh_OPENSSL_STRING_delete(db
->index
[i
], row
);
279 void TXT_DB_free(TXT_DB
*db
)
286 if (db
->index
!= NULL
) {
287 for (i
= db
->num_fields
- 1; i
>= 0; i
--)
288 lh_OPENSSL_STRING_free(db
->index
[i
]);
289 OPENSSL_free(db
->index
);
291 OPENSSL_free(db
->qual
);
292 if (db
->data
!= NULL
) {
293 for (i
= sk_OPENSSL_PSTRING_num(db
->data
) - 1; i
>= 0; i
--) {
295 * check if any 'fields' have been allocated from outside of the
298 p
= sk_OPENSSL_PSTRING_value(db
->data
, i
);
299 max
= p
[db
->num_fields
]; /* last address */
300 if (max
== NULL
) { /* new row */
301 for (n
= 0; n
< db
->num_fields
; n
++)
304 for (n
= 0; n
< db
->num_fields
; n
++) {
305 if (((p
[n
] < (char *)p
) || (p
[n
] > max
)))
309 OPENSSL_free(sk_OPENSSL_PSTRING_value(db
->data
, i
));
311 sk_OPENSSL_PSTRING_free(db
->data
);