txt_db.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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 (**)(char **))OPENSSL_malloc(sizeof(int (**)(char **))*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_clean(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. if (!(p=(char *)OPENSSL_malloc(add+offset))) goto err;
  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 != NULL)
  175. {
  176. if (ret->data != NULL) sk_free(ret->data);
  177. if (ret->index != NULL) OPENSSL_free(ret->index);
  178. if (ret->qual != NULL) OPENSSL_free(ret->qual);
  179. if (ret != NULL) OPENSSL_free(ret);
  180. }
  181. return(NULL);
  182. }
  183. else
  184. return(ret);
  185. }
  186. char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value)
  187. {
  188. char **ret;
  189. LHASH *lh;
  190. if (idx >= db->num_fields)
  191. {
  192. db->error=DB_ERROR_INDEX_OUT_OF_RANGE;
  193. return(NULL);
  194. }
  195. lh=db->index[idx];
  196. if (lh == NULL)
  197. {
  198. db->error=DB_ERROR_NO_INDEX;
  199. return(NULL);
  200. }
  201. ret=(char **)lh_retrieve(lh,value);
  202. db->error=DB_ERROR_OK;
  203. return(ret);
  204. }
  205. int TXT_DB_create_index(TXT_DB *db, int field, int (*qual)(char **),
  206. LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp)
  207. {
  208. LHASH *idx;
  209. char **r;
  210. int i,n;
  211. if (field >= db->num_fields)
  212. {
  213. db->error=DB_ERROR_INDEX_OUT_OF_RANGE;
  214. return(0);
  215. }
  216. if ((idx=lh_new(hash,cmp)) == NULL)
  217. {
  218. db->error=DB_ERROR_MALLOC;
  219. return(0);
  220. }
  221. n=sk_num(db->data);
  222. for (i=0; i<n; i++)
  223. {
  224. r=(char **)sk_value(db->data,i);
  225. if ((qual != NULL) && (qual(r) == 0)) continue;
  226. if ((r=lh_insert(idx,r)) != NULL)
  227. {
  228. db->error=DB_ERROR_INDEX_CLASH;
  229. db->arg1=sk_find(db->data,(char *)r);
  230. db->arg2=i;
  231. lh_free(idx);
  232. return(0);
  233. }
  234. }
  235. if (db->index[field] != NULL) lh_free(db->index[field]);
  236. db->index[field]=idx;
  237. db->qual[field]=qual;
  238. return(1);
  239. }
  240. long TXT_DB_write(BIO *out, TXT_DB *db)
  241. {
  242. long i,j,n,nn,l,tot=0;
  243. char *p,**pp,*f;
  244. BUF_MEM *buf=NULL;
  245. long ret= -1;
  246. if ((buf=BUF_MEM_new()) == NULL)
  247. goto err;
  248. n=sk_num(db->data);
  249. nn=db->num_fields;
  250. for (i=0; i<n; i++)
  251. {
  252. pp=(char **)sk_value(db->data,i);
  253. l=0;
  254. for (j=0; j<nn; j++)
  255. {
  256. if (pp[j] != NULL)
  257. l+=strlen(pp[j]);
  258. }
  259. if (!BUF_MEM_grow_clean(buf,(int)(l*2+nn))) goto err;
  260. p=buf->data;
  261. for (j=0; j<nn; j++)
  262. {
  263. f=pp[j];
  264. if (f != NULL)
  265. for (;;)
  266. {
  267. if (*f == '\0') break;
  268. if (*f == '\t') *(p++)='\\';
  269. *(p++)= *(f++);
  270. }
  271. *(p++)='\t';
  272. }
  273. p[-1]='\n';
  274. j=p-buf->data;
  275. if (BIO_write(out,buf->data,(int)j) != j)
  276. goto err;
  277. tot+=j;
  278. }
  279. ret=tot;
  280. err:
  281. if (buf != NULL) BUF_MEM_free(buf);
  282. return(ret);
  283. }
  284. int TXT_DB_insert(TXT_DB *db, char **row)
  285. {
  286. int i;
  287. char **r;
  288. for (i=0; i<db->num_fields; i++)
  289. {
  290. if (db->index[i] != NULL)
  291. {
  292. if ((db->qual[i] != NULL) &&
  293. (db->qual[i](row) == 0)) continue;
  294. r=(char **)lh_retrieve(db->index[i],row);
  295. if (r != NULL)
  296. {
  297. db->error=DB_ERROR_INDEX_CLASH;
  298. db->arg1=i;
  299. db->arg_row=r;
  300. goto err;
  301. }
  302. }
  303. }
  304. /* We have passed the index checks, now just append and insert */
  305. if (!sk_push(db->data,(char *)row))
  306. {
  307. db->error=DB_ERROR_MALLOC;
  308. goto err;
  309. }
  310. for (i=0; i<db->num_fields; i++)
  311. {
  312. if (db->index[i] != NULL)
  313. {
  314. if ((db->qual[i] != NULL) &&
  315. (db->qual[i](row) == 0)) continue;
  316. lh_insert(db->index[i],row);
  317. }
  318. }
  319. return(1);
  320. err:
  321. return(0);
  322. }
  323. void TXT_DB_free(TXT_DB *db)
  324. {
  325. int i,n;
  326. char **p,*max;
  327. if(db == NULL)
  328. return;
  329. if (db->index != NULL)
  330. {
  331. for (i=db->num_fields-1; i>=0; i--)
  332. if (db->index[i] != NULL) lh_free(db->index[i]);
  333. OPENSSL_free(db->index);
  334. }
  335. if (db->qual != NULL)
  336. OPENSSL_free(db->qual);
  337. if (db->data != NULL)
  338. {
  339. for (i=sk_num(db->data)-1; i>=0; i--)
  340. {
  341. /* check if any 'fields' have been allocated
  342. * from outside of the initial block */
  343. p=(char **)sk_value(db->data,i);
  344. max=p[db->num_fields]; /* last address */
  345. if (max == NULL) /* new row */
  346. {
  347. for (n=0; n<db->num_fields; n++)
  348. if (p[n] != NULL) OPENSSL_free(p[n]);
  349. }
  350. else
  351. {
  352. for (n=0; n<db->num_fields; n++)
  353. {
  354. if (((p[n] < (char *)p) || (p[n] > max))
  355. && (p[n] != NULL))
  356. OPENSSL_free(p[n]);
  357. }
  358. }
  359. OPENSSL_free(sk_value(db->data,i));
  360. }
  361. sk_free(db->data);
  362. }
  363. OPENSSL_free(db);
  364. }