Fix version stuff:
[openssl.git] / crypto / txt_db / txt_db.c
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 "buffer.h"
64 #include "txt_db.h"
65
66 #undef BUFSIZE
67 #define BUFSIZE 512
68
69 char *TXT_DB_version="TXT_DB part of OpenSSL 0.9.2 31-Dec-1998";
70
71 TXT_DB *TXT_DB_read(in,num)
72 BIO *in;
73 int num;
74         {
75         TXT_DB *ret=NULL;
76         int er=1;
77         int esc=0;
78         long ln=0;
79         int i,add,n;
80         int size=BUFSIZE;
81         int offset=0;
82         char *p,**pp,*f;
83         BUF_MEM *buf=NULL;
84
85         if ((buf=BUF_MEM_new()) == NULL) goto err;
86         if (!BUF_MEM_grow(buf,size)) goto err;
87
88         if ((ret=(TXT_DB *)Malloc(sizeof(TXT_DB))) == NULL)
89                 goto err;
90         ret->num_fields=num;
91         ret->index=NULL;
92         ret->qual=NULL;
93         if ((ret->data=sk_new_null()) == NULL)
94                 goto err;
95         if ((ret->index=(LHASH **)Malloc(sizeof(LHASH *)*num)) == NULL)
96                 goto err;
97         if ((ret->qual=(int (**)())Malloc(sizeof(int (**)())*num)) == NULL)
98                 goto err;
99         for (i=0; i<num; i++)
100                 {
101                 ret->index[i]=NULL;
102                 ret->qual[i]=NULL;
103                 }
104
105         add=(num+1)*sizeof(char *);
106         buf->data[size-1]='\0';
107         offset=0;
108         for (;;)
109                 {
110                 if (offset != 0)
111                         {
112                         size+=BUFSIZE;
113                         if (!BUF_MEM_grow(buf,size)) goto err;
114                         }
115                 buf->data[offset]='\0';
116                 BIO_gets(in,&(buf->data[offset]),size-offset);
117                 ln++;
118                 if (buf->data[offset] == '\0') break;
119                 if ((offset == 0) && (buf->data[0] == '#')) continue;
120                 i=strlen(&(buf->data[offset]));
121                 offset+=i;
122                 if (buf->data[offset-1] != '\n')
123                         continue;
124                 else
125                         {
126                         buf->data[offset-1]='\0'; /* blat the '\n' */
127                         p=(char *)Malloc(add+offset);
128                         offset=0;
129                         }
130                 pp=(char **)p;
131                 p+=add;
132                 n=0;
133                 pp[n++]=p;
134                 i=0;
135                 f=buf->data;
136
137                 esc=0;
138                 for (;;)
139                         {
140                         if (*f == '\0') break;
141                         if (*f == '\t')
142                                 {
143                                 if (esc)
144                                         p--;
145                                 else
146                                         {       
147                                         *(p++)='\0';
148                                         f++;
149                                         if (n >=  num) break;
150                                         pp[n++]=p;
151                                         continue;
152                                         }
153                                 }
154                         esc=(*f == '\\');
155                         *(p++)= *(f++);
156                         }
157                 *(p++)='\0';
158                 if ((n != num) || (*f != '\0'))
159                         {
160 #if !defined(NO_STDIO) && !defined(WIN16)       /* temporaty fix :-( */
161                         fprintf(stderr,"wrong number of fields on line %ld\n",ln);
162 #endif
163                         er=2;
164                         goto err;
165                         }
166                 pp[n]=p;
167                 if (!sk_push(ret->data,(char *)pp))
168                         {
169 #if !defined(NO_STDIO) && !defined(WIN16)       /* temporaty fix :-( */
170                         fprintf(stderr,"failure in sk_push\n");
171 #endif
172                         er=2;
173                         goto err;
174                         }
175                 }
176         er=0;
177 err:
178         BUF_MEM_free(buf);
179         if (er)
180                 {
181 #if !defined(NO_STDIO) && !defined(WIN16)
182                 if (er == 1) fprintf(stderr,"Malloc failure\n");
183 #endif
184                 if (ret->data != NULL) sk_free(ret->data);
185                 if (ret->index != NULL) Free(ret->index);
186                 if (ret->qual != NULL) Free((char *)ret->qual);
187                 if (ret != NULL) Free(ret);
188                 return(NULL);
189                 }
190         else
191                 return(ret);
192         }
193
194 char **TXT_DB_get_by_index(db,idx,value)
195 TXT_DB *db;
196 int idx;
197 char **value;
198         {
199         char **ret;
200         LHASH *lh;
201
202         if (idx >= db->num_fields)
203                 {
204                 db->error=DB_ERROR_INDEX_OUT_OF_RANGE;
205                 return(NULL);
206                 }
207         lh=db->index[idx];
208         if (lh == NULL)
209                 {
210                 db->error=DB_ERROR_NO_INDEX;
211                 return(NULL);
212                 }
213         ret=(char **)lh_retrieve(lh,(char *)value);
214         db->error=DB_ERROR_OK;
215         return(ret);
216         }
217
218 int TXT_DB_create_index(db,field,qual,hash,cmp)
219 TXT_DB *db;
220 int field;
221 int (*qual)();
222 unsigned long (*hash)();
223 int (*cmp)();
224         {
225         LHASH *idx;
226         char *r;
227         int i,n;
228
229         if (field >= db->num_fields)
230                 {
231                 db->error=DB_ERROR_INDEX_OUT_OF_RANGE;
232                 return(0);
233                 }
234         if ((idx=lh_new(hash,cmp)) == NULL)
235                 {
236                 db->error=DB_ERROR_MALLOC;
237                 return(0);
238                 }
239         n=sk_num(db->data);
240         for (i=0; i<n; i++)
241                 {
242                 r=(char *)sk_value(db->data,i);
243                 if ((qual != NULL) && (qual(r) == 0)) continue;
244                 if ((r=lh_insert(idx,r)) != NULL)
245                         {
246                         db->error=DB_ERROR_INDEX_CLASH;
247                         db->arg1=sk_find(db->data,r);
248                         db->arg2=i;
249                         lh_free(idx);
250                         return(0);
251                         }
252                 }
253         if (db->index[field] != NULL) lh_free(db->index[field]);
254         db->index[field]=idx;
255         db->qual[field]=qual;
256         return(1);
257         }
258
259 long TXT_DB_write(out,db)
260 BIO *out;
261 TXT_DB *db;
262         {
263         long i,j,n,nn,l,tot=0;
264         char *p,**pp,*f;
265         BUF_MEM *buf=NULL;
266         long ret= -1;
267
268         if ((buf=BUF_MEM_new()) == NULL)
269                 goto err;
270         n=sk_num(db->data);
271         nn=db->num_fields;
272         for (i=0; i<n; i++)
273                 {
274                 pp=(char **)sk_value(db->data,i);
275
276                 l=0;
277                 for (j=0; j<nn; j++)
278                         {
279                         if (pp[j] != NULL)
280                                 l+=strlen(pp[j]);
281                         }
282                 if (!BUF_MEM_grow(buf,(int)(l*2+nn))) goto err;
283
284                 p=buf->data;
285                 for (j=0; j<nn; j++)
286                         {
287                         f=pp[j];
288                         if (f != NULL)
289                                 for (;;) 
290                                         {
291                                         if (*f == '\0') break;
292                                         if (*f == '\t') *(p++)='\\';
293                                         *(p++)= *(f++);
294                                         }
295                         *(p++)='\t';
296                         }
297                 p[-1]='\n';
298                 j=p-buf->data;
299                 if (BIO_write(out,buf->data,(int)j) != j)
300                         goto err;
301                 tot+=j;
302                 }
303         ret=tot;
304 err:
305         if (buf != NULL) BUF_MEM_free(buf);
306         return(ret);
307         }
308
309 int TXT_DB_insert(db,row)
310 TXT_DB *db;
311 char **row;
312         {
313         int i;
314         char **r;
315
316         for (i=0; i<db->num_fields; i++)
317                 {
318                 if (db->index[i] != NULL)
319                         {
320                         if ((db->qual[i] != NULL) &&
321                                 (db->qual[i](row) == 0)) continue;
322                         r=(char **)lh_retrieve(db->index[i],(char *)row);
323                         if (r != NULL)
324                                 {
325                                 db->error=DB_ERROR_INDEX_CLASH;
326                                 db->arg1=i;
327                                 db->arg_row=r;
328                                 goto err;
329                                 }
330                         }
331                 }
332         /* We have passed the index checks, now just append and insert */
333         if (!sk_push(db->data,(char *)row))
334                 {
335                 db->error=DB_ERROR_MALLOC;
336                 goto err;
337                 }
338
339         for (i=0; i<db->num_fields; i++)
340                 {
341                 if (db->index[i] != NULL)
342                         {
343                         if ((db->qual[i] != NULL) &&
344                                 (db->qual[i](row) == 0)) continue;
345                         lh_insert(db->index[i],(char *)row);
346                         }
347                 }
348         return(1);
349 err:
350         return(0);
351         }
352
353 void TXT_DB_free(db)
354 TXT_DB *db;
355         {
356         int i,n;
357         char **p,*max;
358
359         if (db->index != NULL)
360                 {
361                 for (i=db->num_fields-1; i>=0; i--)
362                         if (db->index[i] != NULL) lh_free(db->index[i]);
363                 Free(db->index);
364                 }
365         if (db->qual != NULL)
366                 Free(db->qual);
367         if (db->data != NULL)
368                 {
369                 for (i=sk_num(db->data)-1; i>=0; i--)
370                         {
371                         /* check if any 'fields' have been allocated
372                          * from outside of the initial block */
373                         p=(char **)sk_value(db->data,i);
374                         max=p[db->num_fields]; /* last address */
375                         if (max == NULL) /* new row */
376                                 {
377                                 for (n=0; n<db->num_fields; n++)
378                                         if (p[n] != NULL) Free(p[n]);
379                                 }
380                         else
381                                 {
382                                 for (n=0; n<db->num_fields; n++)
383                                         {
384                                         if (((p[n] < (char *)p) || (p[n] > max))
385                                                 && (p[n] != NULL))
386                                                 Free(p[n]);
387                                         }
388                                 }
389                         Free(sk_value(db->data,i));
390                         }
391                 sk_free(db->data);
392                 }
393         Free(db);
394         }