os/ossrv/ssl/libcrypto/src/crypto/txt_db/txt_db.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* crypto/txt_db/txt_db.c */
     2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
     3  * All rights reserved.
     4  *
     5  * This package is an SSL implementation written
     6  * by Eric Young (eay@cryptsoft.com).
     7  * The implementation was written so as to conform with Netscapes SSL.
     8  * 
     9  * This library is free for commercial and non-commercial use as long as
    10  * the following conditions are aheared to.  The following conditions
    11  * apply to all code found in this distribution, be it the RC4, RSA,
    12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
    13  * included with this distribution is covered by the same copyright terms
    14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
    15  * 
    16  * Copyright remains Eric Young's, and as such any Copyright notices in
    17  * the code are not to be removed.
    18  * If this package is used in a product, Eric Young should be given attribution
    19  * as the author of the parts of the library used.
    20  * This can be in the form of a textual message at program startup or
    21  * in documentation (online or textual) provided with the package.
    22  * 
    23  * Redistribution and use in source and binary forms, with or without
    24  * modification, are permitted provided that the following conditions
    25  * are met:
    26  * 1. Redistributions of source code must retain the copyright
    27  *    notice, this list of conditions and the following disclaimer.
    28  * 2. Redistributions in binary form must reproduce the above copyright
    29  *    notice, this list of conditions and the following disclaimer in the
    30  *    documentation and/or other materials provided with the distribution.
    31  * 3. All advertising materials mentioning features or use of this software
    32  *    must display the following acknowledgement:
    33  *    "This product includes cryptographic software written by
    34  *     Eric Young (eay@cryptsoft.com)"
    35  *    The word 'cryptographic' can be left out if the rouines from the library
    36  *    being used are not cryptographic related :-).
    37  * 4. If you include any Windows specific code (or a derivative thereof) from 
    38  *    the apps directory (application code) you must include an acknowledgement:
    39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
    40  * 
    41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
    42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    51  * SUCH DAMAGE.
    52  * 
    53  * The licence and distribution terms for any publically available version or
    54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
    55  * copied and put under another distribution licence
    56  * [including the GNU Public Licence.]
    57  */
    58 
    59 #include <stdio.h>
    60 #include <stdlib.h>
    61 #include <string.h>
    62 #include "cryptlib.h"
    63 #include <openssl/buffer.h>
    64 #include <openssl/txt_db.h>
    65 
    66 #undef BUFSIZE
    67 #define BUFSIZE	512
    68 
    69 const char TXT_DB_version[]="TXT_DB" OPENSSL_VERSION_PTEXT;
    70 
    71 EXPORT_C TXT_DB *TXT_DB_read(BIO *in, int num)
    72 	{
    73 	TXT_DB *ret=NULL;
    74 	int er=1;
    75 	int esc=0;
    76 	long ln=0;
    77 	int i,add,n;
    78 	int size=BUFSIZE;
    79 	int offset=0;
    80 	char *p,**pp,*f;
    81 	BUF_MEM *buf=NULL;
    82 
    83 	if ((buf=BUF_MEM_new()) == NULL) goto err;
    84 	if (!BUF_MEM_grow(buf,size)) goto err;
    85 
    86 	if ((ret=(TXT_DB *)OPENSSL_malloc(sizeof(TXT_DB))) == NULL)
    87 		goto err;
    88 	ret->num_fields=num;
    89 	ret->index=NULL;
    90 	ret->qual=NULL;
    91 	if ((ret->data=sk_new_null()) == NULL)
    92 		goto err;
    93 	if ((ret->index=(LHASH **)OPENSSL_malloc(sizeof(LHASH *)*num)) == NULL)
    94 		goto err;
    95 	if ((ret->qual=(int (**)(char **))OPENSSL_malloc(sizeof(int (**)(char **))*num)) == NULL)
    96 		goto err;
    97 	for (i=0; i<num; i++)
    98 		{
    99 		ret->index[i]=NULL;
   100 		ret->qual[i]=NULL;
   101 		}
   102 
   103 	add=(num+1)*sizeof(char *);
   104 	buf->data[size-1]='\0';
   105 	offset=0;
   106 	for (;;)
   107 		{
   108 		if (offset != 0)
   109 			{
   110 			size+=BUFSIZE;
   111 			if (!BUF_MEM_grow_clean(buf,size)) goto err;
   112 			}
   113 		buf->data[offset]='\0';
   114 		BIO_gets(in,&(buf->data[offset]),size-offset);
   115 		ln++;
   116 		if (buf->data[offset] == '\0') break;
   117 		if ((offset == 0) && (buf->data[0] == '#')) continue;
   118 		i=strlen(&(buf->data[offset]));
   119 		offset+=i;
   120 		if (buf->data[offset-1] != '\n')
   121 			continue;
   122 		else
   123 			{
   124 			buf->data[offset-1]='\0'; /* blat the '\n' */
   125 			if (!(p=(char *)OPENSSL_malloc(add+offset))) goto err;
   126 			offset=0;
   127 			}
   128 		pp=(char **)p;
   129 		p+=add;
   130 		n=0;
   131 		pp[n++]=p;
   132 		i=0;
   133 		f=buf->data;
   134 
   135 		esc=0;
   136 		for (;;)
   137 			{
   138 			if (*f == '\0') break;
   139 			if (*f == '\t')
   140 				{
   141 				if (esc)
   142 					p--;
   143 				else
   144 					{	
   145 					*(p++)='\0';
   146 					f++;
   147 					if (n >=  num) break;
   148 					pp[n++]=p;
   149 					continue;
   150 					}
   151 				}
   152 			esc=(*f == '\\');
   153 			*(p++)= *(f++);
   154 			}
   155 		*(p++)='\0';
   156 		if ((n != num) || (*f != '\0'))
   157 			{
   158 #if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)	/* temporaty fix :-( */
   159 			fprintf(stderr,"wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n",ln,num,n,f);
   160 #endif
   161 			er=2;
   162 			goto err;
   163 			}
   164 		pp[n]=p;
   165 		if (!sk_push(ret->data,(char *)pp))
   166 			{
   167 #if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)	/* temporaty fix :-( */
   168 			fprintf(stderr,"failure in sk_push\n");
   169 #endif
   170 			er=2;
   171 			goto err;
   172 			}
   173 		}
   174 	er=0;
   175 err:
   176 	BUF_MEM_free(buf);
   177 	if (er)
   178 		{
   179 #if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)
   180 		if (er == 1) fprintf(stderr,"OPENSSL_malloc failure\n");
   181 #endif
   182 		if (ret != NULL)
   183 			{
   184 			if (ret->data != NULL) sk_free(ret->data);
   185 			if (ret->index != NULL) OPENSSL_free(ret->index);
   186 			if (ret->qual != NULL) OPENSSL_free(ret->qual);
   187 			if (ret != NULL) OPENSSL_free(ret);
   188 			}
   189 		return(NULL);
   190 		}
   191 	else
   192 		return(ret);
   193 	}
   194 
   195 EXPORT_C char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value)
   196 	{
   197 	char **ret;
   198 	LHASH *lh;
   199 
   200 	if (idx >= db->num_fields)
   201 		{
   202 		db->error=DB_ERROR_INDEX_OUT_OF_RANGE;
   203 		return(NULL);
   204 		}
   205 	lh=db->index[idx];
   206 	if (lh == NULL)
   207 		{
   208 		db->error=DB_ERROR_NO_INDEX;
   209 		return(NULL);
   210 		}
   211 	ret=(char **)lh_retrieve(lh,value);
   212 	db->error=DB_ERROR_OK;
   213 	return(ret);
   214 	}
   215 
   216 EXPORT_C int TXT_DB_create_index(TXT_DB *db, int field, int (*qual)(char **),
   217 		LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp)
   218 	{
   219 	LHASH *idx;
   220 	char **r;
   221 	int i,n;
   222 
   223 	if (field >= db->num_fields)
   224 		{
   225 		db->error=DB_ERROR_INDEX_OUT_OF_RANGE;
   226 		return(0);
   227 		}
   228 	if ((idx=lh_new(hash,cmp)) == NULL)
   229 		{
   230 		db->error=DB_ERROR_MALLOC;
   231 		return(0);
   232 		}
   233 	n=sk_num(db->data);
   234 	for (i=0; i<n; i++)
   235 		{
   236 		r=(char **)sk_value(db->data,i);
   237 		if ((qual != NULL) && (qual(r) == 0)) continue;
   238 		if ((r=lh_insert(idx,r)) != NULL)
   239 			{
   240 			db->error=DB_ERROR_INDEX_CLASH;
   241 			db->arg1=sk_find(db->data,(char *)r);
   242 			db->arg2=i;
   243 			lh_free(idx);
   244 			return(0);
   245 			}
   246 		}
   247 	if (db->index[field] != NULL) lh_free(db->index[field]);
   248 	db->index[field]=idx;
   249 	db->qual[field]=qual;
   250 	return(1);
   251 	}
   252 
   253 EXPORT_C long TXT_DB_write(BIO *out, TXT_DB *db)
   254 	{
   255 	long i,j,n,nn,l,tot=0;
   256 	char *p,**pp,*f;
   257 	BUF_MEM *buf=NULL;
   258 	long ret= -1;
   259 
   260 	if ((buf=BUF_MEM_new()) == NULL)
   261 		goto err;
   262 	n=sk_num(db->data);
   263 	nn=db->num_fields;
   264 	for (i=0; i<n; i++)
   265 		{
   266 		pp=(char **)sk_value(db->data,i);
   267 
   268 		l=0;
   269 		for (j=0; j<nn; j++)
   270 			{
   271 			if (pp[j] != NULL)
   272 				l+=strlen(pp[j]);
   273 			}
   274 		if (!BUF_MEM_grow_clean(buf,(int)(l*2+nn))) goto err;
   275 
   276 		p=buf->data;
   277 		for (j=0; j<nn; j++)
   278 			{
   279 			f=pp[j];
   280 			if (f != NULL)
   281 				for (;;) 
   282 					{
   283 					if (*f == '\0') break;
   284 					if (*f == '\t') *(p++)='\\';
   285 					*(p++)= *(f++);
   286 					}
   287 			*(p++)='\t';
   288 			}
   289 		p[-1]='\n';
   290 		j=p-buf->data;
   291 		if (BIO_write(out,buf->data,(int)j) != j)
   292 			goto err;
   293 		tot+=j;
   294 		}
   295 	ret=tot;
   296 err:
   297 	if (buf != NULL) BUF_MEM_free(buf);
   298 	return(ret);
   299 	}
   300 
   301 EXPORT_C int TXT_DB_insert(TXT_DB *db, char **row)
   302 	{
   303 	int i;
   304 	char **r;
   305 
   306 	for (i=0; i<db->num_fields; i++)
   307 		{
   308 		if (db->index[i] != NULL)
   309 			{
   310 			if ((db->qual[i] != NULL) &&
   311 				(db->qual[i](row) == 0)) continue;
   312 			r=(char **)lh_retrieve(db->index[i],row);
   313 			if (r != NULL)
   314 				{
   315 				db->error=DB_ERROR_INDEX_CLASH;
   316 				db->arg1=i;
   317 				db->arg_row=r;
   318 				goto err;
   319 				}
   320 			}
   321 		}
   322 	/* We have passed the index checks, now just append and insert */
   323 	if (!sk_push(db->data,(char *)row))
   324 		{
   325 		db->error=DB_ERROR_MALLOC;
   326 		goto err;
   327 		}
   328 
   329 	for (i=0; i<db->num_fields; i++)
   330 		{
   331 		if (db->index[i] != NULL)
   332 			{
   333 			if ((db->qual[i] != NULL) &&
   334 				(db->qual[i](row) == 0)) continue;
   335 			lh_insert(db->index[i],row);
   336 			}
   337 		}
   338 	return(1);
   339 err:
   340 	return(0);
   341 	}
   342 
   343 EXPORT_C void TXT_DB_free(TXT_DB *db)
   344 	{
   345 	int i,n;
   346 	char **p,*max;
   347 
   348 	if(db == NULL)
   349 	    return;
   350 
   351 	if (db->index != NULL)
   352 		{
   353 		for (i=db->num_fields-1; i>=0; i--)
   354 			if (db->index[i] != NULL) lh_free(db->index[i]);
   355 		OPENSSL_free(db->index);
   356 		}
   357 	if (db->qual != NULL)
   358 		OPENSSL_free(db->qual);
   359 	if (db->data != NULL)
   360 		{
   361 		for (i=sk_num(db->data)-1; i>=0; i--)
   362 			{
   363 			/* check if any 'fields' have been allocated
   364 			 * from outside of the initial block */
   365 			p=(char **)sk_value(db->data,i);
   366 			max=p[db->num_fields]; /* last address */
   367 			if (max == NULL) /* new row */
   368 				{
   369 				for (n=0; n<db->num_fields; n++)
   370 					if (p[n] != NULL) OPENSSL_free(p[n]);
   371 				}
   372 			else
   373 				{
   374 				for (n=0; n<db->num_fields; n++)
   375 					{
   376 					if (((p[n] < (char *)p) || (p[n] > max))
   377 						&& (p[n] != NULL))
   378 						OPENSSL_free(p[n]);
   379 					}
   380 				}
   381 			OPENSSL_free(sk_value(db->data,i));
   382 			}
   383 		sk_free(db->data);
   384 		}
   385 	OPENSSL_free(db);
   386 	}