sl@0: /* crypto/txt_db/txt_db.c */ sl@0: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) sl@0: * All rights reserved. sl@0: * sl@0: * This package is an SSL implementation written sl@0: * by Eric Young (eay@cryptsoft.com). sl@0: * The implementation was written so as to conform with Netscapes SSL. sl@0: * sl@0: * This library is free for commercial and non-commercial use as long as sl@0: * the following conditions are aheared to. The following conditions sl@0: * apply to all code found in this distribution, be it the RC4, RSA, sl@0: * lhash, DES, etc., code; not just the SSL code. The SSL documentation sl@0: * included with this distribution is covered by the same copyright terms sl@0: * except that the holder is Tim Hudson (tjh@cryptsoft.com). sl@0: * sl@0: * Copyright remains Eric Young's, and as such any Copyright notices in sl@0: * the code are not to be removed. sl@0: * If this package is used in a product, Eric Young should be given attribution sl@0: * as the author of the parts of the library used. sl@0: * This can be in the form of a textual message at program startup or sl@0: * in documentation (online or textual) provided with the package. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * 1. Redistributions of source code must retain the copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in the sl@0: * documentation and/or other materials provided with the distribution. sl@0: * 3. All advertising materials mentioning features or use of this software sl@0: * must display the following acknowledgement: sl@0: * "This product includes cryptographic software written by sl@0: * Eric Young (eay@cryptsoft.com)" sl@0: * The word 'cryptographic' can be left out if the rouines from the library sl@0: * being used are not cryptographic related :-). sl@0: * 4. If you include any Windows specific code (or a derivative thereof) from sl@0: * the apps directory (application code) you must include an acknowledgement: sl@0: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND sl@0: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE sl@0: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE sl@0: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL sl@0: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS sl@0: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT sl@0: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY sl@0: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF sl@0: * SUCH DAMAGE. sl@0: * sl@0: * The licence and distribution terms for any publically available version or sl@0: * derivative of this code cannot be changed. i.e. this code cannot simply be sl@0: * copied and put under another distribution licence sl@0: * [including the GNU Public Licence.] sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include "cryptlib.h" sl@0: #include sl@0: #include sl@0: sl@0: #undef BUFSIZE sl@0: #define BUFSIZE 512 sl@0: sl@0: const char TXT_DB_version[]="TXT_DB" OPENSSL_VERSION_PTEXT; sl@0: sl@0: EXPORT_C TXT_DB *TXT_DB_read(BIO *in, int num) sl@0: { sl@0: TXT_DB *ret=NULL; sl@0: int er=1; sl@0: int esc=0; sl@0: long ln=0; sl@0: int i,add,n; sl@0: int size=BUFSIZE; sl@0: int offset=0; sl@0: char *p,**pp,*f; sl@0: BUF_MEM *buf=NULL; sl@0: sl@0: if ((buf=BUF_MEM_new()) == NULL) goto err; sl@0: if (!BUF_MEM_grow(buf,size)) goto err; sl@0: sl@0: if ((ret=(TXT_DB *)OPENSSL_malloc(sizeof(TXT_DB))) == NULL) sl@0: goto err; sl@0: ret->num_fields=num; sl@0: ret->index=NULL; sl@0: ret->qual=NULL; sl@0: if ((ret->data=sk_new_null()) == NULL) sl@0: goto err; sl@0: if ((ret->index=(LHASH **)OPENSSL_malloc(sizeof(LHASH *)*num)) == NULL) sl@0: goto err; sl@0: if ((ret->qual=(int (**)(char **))OPENSSL_malloc(sizeof(int (**)(char **))*num)) == NULL) sl@0: goto err; sl@0: for (i=0; iindex[i]=NULL; sl@0: ret->qual[i]=NULL; sl@0: } sl@0: sl@0: add=(num+1)*sizeof(char *); sl@0: buf->data[size-1]='\0'; sl@0: offset=0; sl@0: for (;;) sl@0: { sl@0: if (offset != 0) sl@0: { sl@0: size+=BUFSIZE; sl@0: if (!BUF_MEM_grow_clean(buf,size)) goto err; sl@0: } sl@0: buf->data[offset]='\0'; sl@0: BIO_gets(in,&(buf->data[offset]),size-offset); sl@0: ln++; sl@0: if (buf->data[offset] == '\0') break; sl@0: if ((offset == 0) && (buf->data[0] == '#')) continue; sl@0: i=strlen(&(buf->data[offset])); sl@0: offset+=i; sl@0: if (buf->data[offset-1] != '\n') sl@0: continue; sl@0: else sl@0: { sl@0: buf->data[offset-1]='\0'; /* blat the '\n' */ sl@0: if (!(p=(char *)OPENSSL_malloc(add+offset))) goto err; sl@0: offset=0; sl@0: } sl@0: pp=(char **)p; sl@0: p+=add; sl@0: n=0; sl@0: pp[n++]=p; sl@0: i=0; sl@0: f=buf->data; sl@0: sl@0: esc=0; sl@0: for (;;) sl@0: { sl@0: if (*f == '\0') break; sl@0: if (*f == '\t') sl@0: { sl@0: if (esc) sl@0: p--; sl@0: else sl@0: { sl@0: *(p++)='\0'; sl@0: f++; sl@0: if (n >= num) break; sl@0: pp[n++]=p; sl@0: continue; sl@0: } sl@0: } sl@0: esc=(*f == '\\'); sl@0: *(p++)= *(f++); sl@0: } sl@0: *(p++)='\0'; sl@0: if ((n != num) || (*f != '\0')) sl@0: { sl@0: #if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty fix :-( */ sl@0: fprintf(stderr,"wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n",ln,num,n,f); sl@0: #endif sl@0: er=2; sl@0: goto err; sl@0: } sl@0: pp[n]=p; sl@0: if (!sk_push(ret->data,(char *)pp)) sl@0: { sl@0: #if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporaty fix :-( */ sl@0: fprintf(stderr,"failure in sk_push\n"); sl@0: #endif sl@0: er=2; sl@0: goto err; sl@0: } sl@0: } sl@0: er=0; sl@0: err: sl@0: BUF_MEM_free(buf); sl@0: if (er) sl@0: { sl@0: #if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) sl@0: if (er == 1) fprintf(stderr,"OPENSSL_malloc failure\n"); sl@0: #endif sl@0: if (ret != NULL) sl@0: { sl@0: if (ret->data != NULL) sk_free(ret->data); sl@0: if (ret->index != NULL) OPENSSL_free(ret->index); sl@0: if (ret->qual != NULL) OPENSSL_free(ret->qual); sl@0: if (ret != NULL) OPENSSL_free(ret); sl@0: } sl@0: return(NULL); sl@0: } sl@0: else sl@0: return(ret); sl@0: } sl@0: sl@0: EXPORT_C char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value) sl@0: { sl@0: char **ret; sl@0: LHASH *lh; sl@0: sl@0: if (idx >= db->num_fields) sl@0: { sl@0: db->error=DB_ERROR_INDEX_OUT_OF_RANGE; sl@0: return(NULL); sl@0: } sl@0: lh=db->index[idx]; sl@0: if (lh == NULL) sl@0: { sl@0: db->error=DB_ERROR_NO_INDEX; sl@0: return(NULL); sl@0: } sl@0: ret=(char **)lh_retrieve(lh,value); sl@0: db->error=DB_ERROR_OK; sl@0: return(ret); sl@0: } sl@0: sl@0: EXPORT_C int TXT_DB_create_index(TXT_DB *db, int field, int (*qual)(char **), sl@0: LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp) sl@0: { sl@0: LHASH *idx; sl@0: char **r; sl@0: int i,n; sl@0: sl@0: if (field >= db->num_fields) sl@0: { sl@0: db->error=DB_ERROR_INDEX_OUT_OF_RANGE; sl@0: return(0); sl@0: } sl@0: if ((idx=lh_new(hash,cmp)) == NULL) sl@0: { sl@0: db->error=DB_ERROR_MALLOC; sl@0: return(0); sl@0: } sl@0: n=sk_num(db->data); sl@0: for (i=0; idata,i); sl@0: if ((qual != NULL) && (qual(r) == 0)) continue; sl@0: if ((r=lh_insert(idx,r)) != NULL) sl@0: { sl@0: db->error=DB_ERROR_INDEX_CLASH; sl@0: db->arg1=sk_find(db->data,(char *)r); sl@0: db->arg2=i; sl@0: lh_free(idx); sl@0: return(0); sl@0: } sl@0: } sl@0: if (db->index[field] != NULL) lh_free(db->index[field]); sl@0: db->index[field]=idx; sl@0: db->qual[field]=qual; sl@0: return(1); sl@0: } sl@0: sl@0: EXPORT_C long TXT_DB_write(BIO *out, TXT_DB *db) sl@0: { sl@0: long i,j,n,nn,l,tot=0; sl@0: char *p,**pp,*f; sl@0: BUF_MEM *buf=NULL; sl@0: long ret= -1; sl@0: sl@0: if ((buf=BUF_MEM_new()) == NULL) sl@0: goto err; sl@0: n=sk_num(db->data); sl@0: nn=db->num_fields; sl@0: for (i=0; idata,i); sl@0: sl@0: l=0; sl@0: for (j=0; jdata; sl@0: for (j=0; jdata; sl@0: if (BIO_write(out,buf->data,(int)j) != j) sl@0: goto err; sl@0: tot+=j; sl@0: } sl@0: ret=tot; sl@0: err: sl@0: if (buf != NULL) BUF_MEM_free(buf); sl@0: return(ret); sl@0: } sl@0: sl@0: EXPORT_C int TXT_DB_insert(TXT_DB *db, char **row) sl@0: { sl@0: int i; sl@0: char **r; sl@0: sl@0: for (i=0; inum_fields; i++) sl@0: { sl@0: if (db->index[i] != NULL) sl@0: { sl@0: if ((db->qual[i] != NULL) && sl@0: (db->qual[i](row) == 0)) continue; sl@0: r=(char **)lh_retrieve(db->index[i],row); sl@0: if (r != NULL) sl@0: { sl@0: db->error=DB_ERROR_INDEX_CLASH; sl@0: db->arg1=i; sl@0: db->arg_row=r; sl@0: goto err; sl@0: } sl@0: } sl@0: } sl@0: /* We have passed the index checks, now just append and insert */ sl@0: if (!sk_push(db->data,(char *)row)) sl@0: { sl@0: db->error=DB_ERROR_MALLOC; sl@0: goto err; sl@0: } sl@0: sl@0: for (i=0; inum_fields; i++) sl@0: { sl@0: if (db->index[i] != NULL) sl@0: { sl@0: if ((db->qual[i] != NULL) && sl@0: (db->qual[i](row) == 0)) continue; sl@0: lh_insert(db->index[i],row); sl@0: } sl@0: } sl@0: return(1); sl@0: err: sl@0: return(0); sl@0: } sl@0: sl@0: EXPORT_C void TXT_DB_free(TXT_DB *db) sl@0: { sl@0: int i,n; sl@0: char **p,*max; sl@0: sl@0: if(db == NULL) sl@0: return; sl@0: sl@0: if (db->index != NULL) sl@0: { sl@0: for (i=db->num_fields-1; i>=0; i--) sl@0: if (db->index[i] != NULL) lh_free(db->index[i]); sl@0: OPENSSL_free(db->index); sl@0: } sl@0: if (db->qual != NULL) sl@0: OPENSSL_free(db->qual); sl@0: if (db->data != NULL) sl@0: { sl@0: for (i=sk_num(db->data)-1; i>=0; i--) sl@0: { sl@0: /* check if any 'fields' have been allocated sl@0: * from outside of the initial block */ sl@0: p=(char **)sk_value(db->data,i); sl@0: max=p[db->num_fields]; /* last address */ sl@0: if (max == NULL) /* new row */ sl@0: { sl@0: for (n=0; nnum_fields; n++) sl@0: if (p[n] != NULL) OPENSSL_free(p[n]); sl@0: } sl@0: else sl@0: { sl@0: for (n=0; nnum_fields; n++) sl@0: { sl@0: if (((p[n] < (char *)p) || (p[n] > max)) sl@0: && (p[n] != NULL)) sl@0: OPENSSL_free(p[n]); sl@0: } sl@0: } sl@0: OPENSSL_free(sk_value(db->data,i)); sl@0: } sl@0: sk_free(db->data); sl@0: } sl@0: OPENSSL_free(db); sl@0: }