txt_db.c 9.4 KB

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