txt_db.c 9.3 KB

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