155714Skris/* crypto/txt_db/txt_db.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8296465Sdelphij * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296465Sdelphij * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22296465Sdelphij * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296465Sdelphij * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52296465Sdelphij * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include <stdlib.h> 6155714Skris#include <string.h> 6255714Skris#include "cryptlib.h" 6355714Skris#include <openssl/buffer.h> 6455714Skris#include <openssl/txt_db.h> 6555714Skris 6655714Skris#undef BUFSIZE 67296465Sdelphij#define BUFSIZE 512 6855714Skris 69296465Sdelphijconst char TXT_DB_version[] = "TXT_DB" OPENSSL_VERSION_PTEXT; 7055714Skris 7155714SkrisTXT_DB *TXT_DB_read(BIO *in, int num) 72296465Sdelphij{ 73296465Sdelphij TXT_DB *ret = NULL; 74296465Sdelphij int er = 1; 75296465Sdelphij int esc = 0; 76296465Sdelphij long ln = 0; 77296465Sdelphij int i, add, n; 78296465Sdelphij int size = BUFSIZE; 79296465Sdelphij int offset = 0; 80296465Sdelphij char *p, **pp, *f; 81296465Sdelphij BUF_MEM *buf = NULL; 8255714Skris 83296465Sdelphij if ((buf = BUF_MEM_new()) == NULL) 84296465Sdelphij goto err; 85296465Sdelphij if (!BUF_MEM_grow(buf, size)) 86296465Sdelphij goto err; 8755714Skris 88296465Sdelphij if ((ret = (TXT_DB *)OPENSSL_malloc(sizeof(TXT_DB))) == NULL) 89296465Sdelphij goto err; 90296465Sdelphij ret->num_fields = num; 91296465Sdelphij ret->index = NULL; 92296465Sdelphij ret->qual = NULL; 93296465Sdelphij if ((ret->data = sk_new_null()) == NULL) 94296465Sdelphij goto err; 95296465Sdelphij if ((ret->index = 96296465Sdelphij (LHASH **)OPENSSL_malloc(sizeof(LHASH *) * num)) == NULL) 97296465Sdelphij goto err; 98296465Sdelphij if ((ret->qual = 99296465Sdelphij (int (**)(char **))OPENSSL_malloc(sizeof(int (**)(char **)) * 100296465Sdelphij num)) == NULL) 101296465Sdelphij goto err; 102296465Sdelphij for (i = 0; i < num; i++) { 103296465Sdelphij ret->index[i] = NULL; 104296465Sdelphij ret->qual[i] = NULL; 105296465Sdelphij } 10655714Skris 107296465Sdelphij add = (num + 1) * sizeof(char *); 108296465Sdelphij buf->data[size - 1] = '\0'; 109296465Sdelphij offset = 0; 110296465Sdelphij for (;;) { 111296465Sdelphij if (offset != 0) { 112296465Sdelphij size += BUFSIZE; 113296465Sdelphij if (!BUF_MEM_grow_clean(buf, size)) 114296465Sdelphij goto err; 115296465Sdelphij } 116296465Sdelphij buf->data[offset] = '\0'; 117296465Sdelphij BIO_gets(in, &(buf->data[offset]), size - offset); 118296465Sdelphij ln++; 119296465Sdelphij if (buf->data[offset] == '\0') 120296465Sdelphij break; 121296465Sdelphij if ((offset == 0) && (buf->data[0] == '#')) 122296465Sdelphij continue; 123296465Sdelphij i = strlen(&(buf->data[offset])); 124296465Sdelphij offset += i; 125296465Sdelphij if (buf->data[offset - 1] != '\n') 126296465Sdelphij continue; 127296465Sdelphij else { 128296465Sdelphij buf->data[offset - 1] = '\0'; /* blat the '\n' */ 129296465Sdelphij if (!(p = (char *)OPENSSL_malloc(add + offset))) 130296465Sdelphij goto err; 131296465Sdelphij offset = 0; 132296465Sdelphij } 133296465Sdelphij pp = (char **)p; 134296465Sdelphij p += add; 135296465Sdelphij n = 0; 136296465Sdelphij pp[n++] = p; 137296465Sdelphij i = 0; 138296465Sdelphij f = buf->data; 13955714Skris 140296465Sdelphij esc = 0; 141296465Sdelphij for (;;) { 142296465Sdelphij if (*f == '\0') 143296465Sdelphij break; 144296465Sdelphij if (*f == '\t') { 145296465Sdelphij if (esc) 146296465Sdelphij p--; 147296465Sdelphij else { 148296465Sdelphij *(p++) = '\0'; 149296465Sdelphij f++; 150296465Sdelphij if (n >= num) 151296465Sdelphij break; 152296465Sdelphij pp[n++] = p; 153296465Sdelphij continue; 154296465Sdelphij } 155296465Sdelphij } 156296465Sdelphij esc = (*f == '\\'); 157296465Sdelphij *(p++) = *(f++); 158296465Sdelphij } 159296465Sdelphij *(p++) = '\0'; 160296465Sdelphij if ((n != num) || (*f != '\0')) { 161296465Sdelphij#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty 162296465Sdelphij * fix :-( */ 163296465Sdelphij fprintf(stderr, 164296465Sdelphij "wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n", 165296465Sdelphij ln, num, n, f); 16655714Skris#endif 167296465Sdelphij er = 2; 168296465Sdelphij goto err; 169296465Sdelphij } 170296465Sdelphij pp[n] = p; 171296465Sdelphij if (!sk_push(ret->data, (char *)pp)) { 172296465Sdelphij#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty 173296465Sdelphij * fix :-( */ 174296465Sdelphij fprintf(stderr, "failure in sk_push\n"); 17555714Skris#endif 176296465Sdelphij er = 2; 177296465Sdelphij goto err; 178296465Sdelphij } 179296465Sdelphij } 180296465Sdelphij er = 0; 181296465Sdelphij err: 182296465Sdelphij BUF_MEM_free(buf); 183296465Sdelphij if (er) { 184109998Smarkm#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) 185296465Sdelphij if (er == 1) 186296465Sdelphij fprintf(stderr, "OPENSSL_malloc failure\n"); 18755714Skris#endif 188296465Sdelphij if (ret != NULL) { 189296465Sdelphij if (ret->data != NULL) 190296465Sdelphij sk_free(ret->data); 191296465Sdelphij if (ret->index != NULL) 192296465Sdelphij OPENSSL_free(ret->index); 193296465Sdelphij if (ret->qual != NULL) 194296465Sdelphij OPENSSL_free(ret->qual); 195296465Sdelphij if (ret != NULL) 196296465Sdelphij OPENSSL_free(ret); 197296465Sdelphij } 198296465Sdelphij return (NULL); 199296465Sdelphij } else 200296465Sdelphij return (ret); 201296465Sdelphij} 20255714Skris 20355714Skrischar **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value) 204296465Sdelphij{ 205296465Sdelphij char **ret; 206296465Sdelphij LHASH *lh; 20755714Skris 208296465Sdelphij if (idx >= db->num_fields) { 209296465Sdelphij db->error = DB_ERROR_INDEX_OUT_OF_RANGE; 210296465Sdelphij return (NULL); 211296465Sdelphij } 212296465Sdelphij lh = db->index[idx]; 213296465Sdelphij if (lh == NULL) { 214296465Sdelphij db->error = DB_ERROR_NO_INDEX; 215296465Sdelphij return (NULL); 216296465Sdelphij } 217296465Sdelphij ret = (char **)lh_retrieve(lh, value); 218296465Sdelphij db->error = DB_ERROR_OK; 219296465Sdelphij return (ret); 220296465Sdelphij} 22155714Skris 222296465Sdelphijint TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (char **), 223296465Sdelphij LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp) 224296465Sdelphij{ 225296465Sdelphij LHASH *idx; 226296465Sdelphij char **r; 227296465Sdelphij int i, n; 22855714Skris 229296465Sdelphij if (field >= db->num_fields) { 230296465Sdelphij db->error = DB_ERROR_INDEX_OUT_OF_RANGE; 231296465Sdelphij return (0); 232296465Sdelphij } 233296465Sdelphij if ((idx = lh_new(hash, cmp)) == NULL) { 234296465Sdelphij db->error = DB_ERROR_MALLOC; 235296465Sdelphij return (0); 236296465Sdelphij } 237296465Sdelphij n = sk_num(db->data); 238296465Sdelphij for (i = 0; i < n; i++) { 239296465Sdelphij r = (char **)sk_value(db->data, i); 240296465Sdelphij if ((qual != NULL) && (qual(r) == 0)) 241296465Sdelphij continue; 242296465Sdelphij if ((r = lh_insert(idx, r)) != NULL) { 243296465Sdelphij db->error = DB_ERROR_INDEX_CLASH; 244296465Sdelphij db->arg1 = sk_find(db->data, (char *)r); 245296465Sdelphij db->arg2 = i; 246296465Sdelphij lh_free(idx); 247296465Sdelphij return (0); 248296465Sdelphij } 249296465Sdelphij } 250296465Sdelphij if (db->index[field] != NULL) 251296465Sdelphij lh_free(db->index[field]); 252296465Sdelphij db->index[field] = idx; 253296465Sdelphij db->qual[field] = qual; 254296465Sdelphij return (1); 255296465Sdelphij} 25655714Skris 25755714Skrislong TXT_DB_write(BIO *out, TXT_DB *db) 258296465Sdelphij{ 259296465Sdelphij long i, j, n, nn, l, tot = 0; 260296465Sdelphij char *p, **pp, *f; 261296465Sdelphij BUF_MEM *buf = NULL; 262296465Sdelphij long ret = -1; 26355714Skris 264296465Sdelphij if ((buf = BUF_MEM_new()) == NULL) 265296465Sdelphij goto err; 266296465Sdelphij n = sk_num(db->data); 267296465Sdelphij nn = db->num_fields; 268296465Sdelphij for (i = 0; i < n; i++) { 269296465Sdelphij pp = (char **)sk_value(db->data, i); 27055714Skris 271296465Sdelphij l = 0; 272296465Sdelphij for (j = 0; j < nn; j++) { 273296465Sdelphij if (pp[j] != NULL) 274296465Sdelphij l += strlen(pp[j]); 275296465Sdelphij } 276296465Sdelphij if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn))) 277296465Sdelphij goto err; 27855714Skris 279296465Sdelphij p = buf->data; 280296465Sdelphij for (j = 0; j < nn; j++) { 281296465Sdelphij f = pp[j]; 282296465Sdelphij if (f != NULL) 283296465Sdelphij for (;;) { 284296465Sdelphij if (*f == '\0') 285296465Sdelphij break; 286296465Sdelphij if (*f == '\t') 287296465Sdelphij *(p++) = '\\'; 288296465Sdelphij *(p++) = *(f++); 289296465Sdelphij } 290296465Sdelphij *(p++) = '\t'; 291296465Sdelphij } 292296465Sdelphij p[-1] = '\n'; 293296465Sdelphij j = p - buf->data; 294296465Sdelphij if (BIO_write(out, buf->data, (int)j) != j) 295296465Sdelphij goto err; 296296465Sdelphij tot += j; 297296465Sdelphij } 298296465Sdelphij ret = tot; 299296465Sdelphij err: 300296465Sdelphij if (buf != NULL) 301296465Sdelphij BUF_MEM_free(buf); 302296465Sdelphij return (ret); 303296465Sdelphij} 30455714Skris 30555714Skrisint TXT_DB_insert(TXT_DB *db, char **row) 306296465Sdelphij{ 307296465Sdelphij int i; 308296465Sdelphij char **r; 30955714Skris 310296465Sdelphij for (i = 0; i < db->num_fields; i++) { 311296465Sdelphij if (db->index[i] != NULL) { 312296465Sdelphij if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0)) 313296465Sdelphij continue; 314296465Sdelphij r = (char **)lh_retrieve(db->index[i], row); 315296465Sdelphij if (r != NULL) { 316296465Sdelphij db->error = DB_ERROR_INDEX_CLASH; 317296465Sdelphij db->arg1 = i; 318296465Sdelphij db->arg_row = r; 319296465Sdelphij goto err; 320296465Sdelphij } 321296465Sdelphij } 322296465Sdelphij } 323296465Sdelphij /* We have passed the index checks, now just append and insert */ 324296465Sdelphij if (!sk_push(db->data, (char *)row)) { 325296465Sdelphij db->error = DB_ERROR_MALLOC; 326296465Sdelphij goto err; 327296465Sdelphij } 32855714Skris 329296465Sdelphij for (i = 0; i < db->num_fields; i++) { 330296465Sdelphij if (db->index[i] != NULL) { 331296465Sdelphij if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0)) 332296465Sdelphij continue; 333296465Sdelphij lh_insert(db->index[i], row); 334296465Sdelphij } 335296465Sdelphij } 336296465Sdelphij return (1); 337296465Sdelphij err: 338296465Sdelphij return (0); 339296465Sdelphij} 34055714Skris 34155714Skrisvoid TXT_DB_free(TXT_DB *db) 342296465Sdelphij{ 343296465Sdelphij int i, n; 344296465Sdelphij char **p, *max; 34555714Skris 346296465Sdelphij if (db == NULL) 347296465Sdelphij return; 34855714Skris 349296465Sdelphij if (db->index != NULL) { 350296465Sdelphij for (i = db->num_fields - 1; i >= 0; i--) 351296465Sdelphij if (db->index[i] != NULL) 352296465Sdelphij lh_free(db->index[i]); 353296465Sdelphij OPENSSL_free(db->index); 354296465Sdelphij } 355296465Sdelphij if (db->qual != NULL) 356296465Sdelphij OPENSSL_free(db->qual); 357296465Sdelphij if (db->data != NULL) { 358296465Sdelphij for (i = sk_num(db->data) - 1; i >= 0; i--) { 359296465Sdelphij /* 360296465Sdelphij * check if any 'fields' have been allocated from outside of the 361296465Sdelphij * initial block 362296465Sdelphij */ 363296465Sdelphij p = (char **)sk_value(db->data, i); 364296465Sdelphij max = p[db->num_fields]; /* last address */ 365296465Sdelphij if (max == NULL) { /* new row */ 366296465Sdelphij for (n = 0; n < db->num_fields; n++) 367296465Sdelphij if (p[n] != NULL) 368296465Sdelphij OPENSSL_free(p[n]); 369296465Sdelphij } else { 370296465Sdelphij for (n = 0; n < db->num_fields; n++) { 371296465Sdelphij if (((p[n] < (char *)p) || (p[n] > max)) 372296465Sdelphij && (p[n] != NULL)) 373296465Sdelphij OPENSSL_free(p[n]); 374296465Sdelphij } 375296465Sdelphij } 376296465Sdelphij OPENSSL_free(sk_value(db->data, i)); 377296465Sdelphij } 378296465Sdelphij sk_free(db->data); 379296465Sdelphij } 380296465Sdelphij OPENSSL_free(db); 381296465Sdelphij} 382