/xmlfy-1.5.5/xmlfy/validate_args/process_arg_expel.c

# · C · 478 lines · 380 code · 38 blank · 60 comment · 130 complexity · cbdfbef0b45823abdc938f365fdae4f6 MD5 · raw file

  1. /*
  2. * BSD License for xmlfy
  3. * Copyright (c) 2008-2011, Arthur Gouros
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * - Redistributions of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. * - Neither the name of Arthur Gouros nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  22. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  23. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  24. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  25. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  26. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /**************************************************************************
  31. * xmlfy - Convert to XML on the fly. *
  32. * Original Author: Arthur Gouros. *
  33. * *
  34. * Please consult the documentation for further information. *
  35. **************************************************************************
  36. */
  37. #include "validate_args.h"
  38. /* function templates */
  39. int process_arg_expel(unsigned char *s);
  40. int set_flag_string(int status, int pos, unsigned char *s, int s_length);
  41. int process_arg_expel(s)
  42. unsigned char *s;
  43. {
  44. /* translate expel arg to expel structure */
  45. unsigned char *records, *fields, string_delimiter;
  46. int s_length, r_length, f_length;
  47. int i, j, ret;
  48. char value[10];
  49. int i_value;
  50. int flag_string;
  51. /* initialise */
  52. ret = TRUE;
  53. s_length = xstrlen(s);
  54. flag_string = FALSE;
  55. string_delimiter = '/';
  56. if (s_length == 0)
  57. ret = FALSE;
  58. /* ensure legal characters */
  59. j = 0;
  60. for (i = 0 ; i < s_length ; i++)
  61. {
  62. switch (s[i])
  63. {
  64. case '0' :
  65. case '1' :
  66. case '2' :
  67. case '3' :
  68. case '4' :
  69. case '5' :
  70. case '6' :
  71. case '7' :
  72. case '8' :
  73. case '9' :
  74. case '$' :
  75. case '-' :
  76. case ',' :
  77. case 'n' :
  78. case 'f' :
  79. case 'c' :
  80. case '\'' :
  81. case '\"' :
  82. break;
  83. case '/' :
  84. case '%' : if (!flag_string)
  85. string_delimiter = s[i];
  86. if (string_delimiter == s[i])
  87. flag_string = set_flag_string(flag_string, i, s, s_length);
  88. break;
  89. case ':' : if (!flag_string)
  90. j++;
  91. break;
  92. default : if (!flag_string)
  93. ret = FALSE;
  94. }
  95. }
  96. if (j > 1)
  97. ret = FALSE;
  98. if (ret)
  99. {
  100. /* split arg into records/fields components */
  101. i = 0;
  102. flag_string = FALSE;
  103. while (i < s_length && (flag_string || s[i] != ':'))
  104. {
  105. if (!flag_string && (s[i] == '/' || s[i] == '%'))
  106. string_delimiter = s[i];
  107. if (s[i] == string_delimiter)
  108. flag_string = set_flag_string(flag_string, i, s, s_length);
  109. i++;
  110. }
  111. if (i == s_length)
  112. {
  113. records = s;
  114. r_length = s_length;
  115. fields = NULL;
  116. f_length = 0;
  117. }
  118. else
  119. {
  120. records = s;
  121. r_length = i;
  122. fields = &s[i + 1];
  123. f_length = s_length - i - 1;
  124. /* ensure legal field chars */
  125. for (i = 0 ; i < f_length ; i++)
  126. {
  127. switch (fields[i])
  128. {
  129. case '0' :
  130. case '1' :
  131. case '2' :
  132. case '3' :
  133. case '4' :
  134. case '5' :
  135. case '6' :
  136. case '7' :
  137. case '8' :
  138. case '9' :
  139. case '$' :
  140. case '-' :
  141. case ',' :
  142. case '\'' :
  143. case '\"' :
  144. break;
  145. default :
  146. ret = FALSE;
  147. }
  148. }
  149. }
  150. }
  151. if (ret)
  152. {
  153. /* allocate memory for expel structure */
  154. if (nexpel)
  155. expel = (struct_expel *) realloc(expel, ((nexpel + 1) * sizeof(struct_expel)));
  156. else
  157. expel = (struct_expel *) malloc(sizeof(struct_expel));
  158. if (expel == NULL) out_of_mem();
  159. /* calc number of records/fields */
  160. expel[nexpel].n_erecords = 1;
  161. flag_string = FALSE;
  162. for (i = 0 ; i < r_length ; i++)
  163. {
  164. if (!flag_string && (records[i] == '/' || records[i] == '%'))
  165. string_delimiter = records[i];
  166. if (records[i] == string_delimiter)
  167. flag_string = set_flag_string(flag_string, i, records, r_length);
  168. if (!flag_string && records[i] == ',')
  169. expel[nexpel].n_erecords++;
  170. }
  171. if (f_length > 0)
  172. {
  173. expel[nexpel].n_efields = 1;
  174. for (i = 0 ; i < f_length ; i++)
  175. if (fields[i] == ',')
  176. expel[nexpel].n_efields++;
  177. }
  178. else
  179. expel[nexpel].n_efields = 0;
  180. /* allocate ranges */
  181. expel[nexpel].erecords = (struct_erecords *) malloc(expel[nexpel].n_erecords * sizeof(struct_erecords));
  182. if (expel[nexpel].erecords == NULL) out_of_mem();
  183. if (expel[nexpel].n_efields)
  184. {
  185. expel[nexpel].efields = (struct_efields *) malloc(expel[nexpel].n_efields * sizeof(struct_efields));
  186. if (expel[nexpel].efields == NULL) out_of_mem();
  187. }
  188. for (i = 0 ; i < expel[nexpel].n_erecords ; i++)
  189. {
  190. expel[nexpel].erecords[i].type = RANGE_UNSET;
  191. expel[nexpel].erecords[i].min = RANGE_UNSET;
  192. expel[nexpel].erecords[i].max = RANGE_UNSET;
  193. expel[nexpel].erecords[i].s = NULL;
  194. expel[nexpel].erecords[i].s_length = 0;
  195. }
  196. for (i = 0 ; i < expel[nexpel].n_efields ; i++)
  197. {
  198. expel[nexpel].efields[i].min = RANGE_UNSET;
  199. expel[nexpel].efields[i].max = RANGE_UNSET;
  200. }
  201. /* populate expel structure */
  202. j = 0;
  203. i_value = 0;
  204. value[0] = '\0';
  205. flag_string = FALSE;
  206. for (i = 0 ; i < r_length ; i++)
  207. {
  208. if (!flag_string && (records[i] == '/' || records[i] == '%'))
  209. string_delimiter = records[i];
  210. switch (records[i])
  211. {
  212. case '/' :
  213. case '%' : if (!flag_string)
  214. {
  215. if (i + 1 < r_length)
  216. {
  217. flag_string = TRUE;
  218. expel[nexpel].erecords[j].s = &records[i + 1];
  219. /* read up to next matching forward slash */
  220. while (i + expel[nexpel].erecords[j].s_length + 1 < r_length && flag_string)
  221. {
  222. if (records[i + expel[nexpel].erecords[j].s_length + 1] == string_delimiter)
  223. flag_string = set_flag_string(flag_string, i + expel[nexpel].erecords[j].s_length + 1, records, r_length);
  224. if (flag_string)
  225. expel[nexpel].erecords[j].s_length++;
  226. }
  227. if (flag_string)
  228. ret = FALSE;
  229. i += expel[nexpel].erecords[j].s_length + 1;
  230. }
  231. }
  232. else
  233. ret = FALSE;
  234. break;
  235. case '\'' :
  236. case '\"' : i_value = 0;
  237. break;
  238. case 'n' : if (expel[nexpel].erecords[j].type == RANGE_UNSET)
  239. expel[nexpel].erecords[j].type = EXPEL_TYPE_N;
  240. else
  241. ret = FALSE;
  242. i_value = 0;
  243. break;
  244. case 'f' : if (expel[nexpel].erecords[j].type == RANGE_UNSET)
  245. expel[nexpel].erecords[j].type = EXPEL_TYPE_F;
  246. else
  247. ret = FALSE;
  248. i_value = 0;
  249. break;
  250. case 'c' : if (expel[nexpel].erecords[j].type == RANGE_UNSET)
  251. expel[nexpel].erecords[j].type = EXPEL_TYPE_C;
  252. else
  253. ret = FALSE;
  254. i_value = 0;
  255. break;
  256. case '$' : if (expel[nexpel].erecords[j].min == RANGE_UNSET)
  257. ret = FALSE; /* in this release the last record must be in a range */
  258. else
  259. expel[nexpel].erecords[j].max = -1;
  260. i_value = 0;
  261. break;
  262. case '-' : if (i_value)
  263. {
  264. if (expel[nexpel].erecords[j].min == RANGE_UNSET)
  265. {
  266. expel[nexpel].erecords[j].min = atol(value) - 1;
  267. if (expel[nexpel].erecords[j].min < 0)
  268. ret = FALSE;
  269. }
  270. }
  271. else
  272. expel[nexpel].erecords[j].min = 0;
  273. i_value = 0;
  274. /* pre-populate max field in case not supplied */
  275. expel[nexpel].erecords[j].max = -1;
  276. break;
  277. case ',' : if (i_value)
  278. {
  279. if (expel[nexpel].erecords[j].min == RANGE_UNSET)
  280. {
  281. expel[nexpel].erecords[j].min = atol(value) - 1;
  282. if (expel[nexpel].erecords[j].min < 0)
  283. ret = FALSE;
  284. /* pre-populate max field in case not supplied */
  285. expel[nexpel].erecords[j].max = expel[nexpel].erecords[j].min;
  286. }
  287. else
  288. {
  289. expel[nexpel].erecords[j].max = atol(value) - 1;
  290. if (expel[nexpel].erecords[j].max < 0)
  291. ret = FALSE;
  292. }
  293. }
  294. i_value = 0;
  295. /* quick sanity check */
  296. if (expel[nexpel].erecords[j].type == RANGE_UNSET || (expel[nexpel].erecords[j].max > 0 && expel[nexpel].erecords[j].min > expel[nexpel].erecords[j].max))
  297. ret = FALSE;
  298. j++;
  299. break;
  300. default : value[i_value++] = records[i];
  301. value[i_value] = '\0';
  302. }
  303. }
  304. if (i_value)
  305. {
  306. if (expel[nexpel].erecords[j].min == RANGE_UNSET)
  307. {
  308. expel[nexpel].erecords[j].min = atol(value) - 1;
  309. if (expel[nexpel].erecords[j].min < 0)
  310. ret = FALSE;
  311. /* pre-populate max field in case not supplied */
  312. expel[nexpel].erecords[j].max = expel[nexpel].erecords[j].min;
  313. }
  314. else
  315. {
  316. expel[nexpel].erecords[j].max = atol(value) - 1;
  317. if (expel[nexpel].erecords[j].max < 0)
  318. ret = FALSE;
  319. }
  320. }
  321. /* quick sanity check */
  322. if (j < expel[nexpel].n_erecords && (expel[nexpel].erecords[j].type == RANGE_UNSET || (expel[nexpel].erecords[j].max > 0 && expel[nexpel].erecords[j].min > expel[nexpel].erecords[j].max)))
  323. ret = FALSE;
  324. if (expel[nexpel].n_efields)
  325. {
  326. j = 0;
  327. i_value = 0;
  328. value[0] = '\0';
  329. for (i = 0 ; i < f_length ; i++)
  330. {
  331. switch (fields[i])
  332. {
  333. case '\'' :
  334. case '\"' : i_value = 0;
  335. break;
  336. case '$' : if (expel[nexpel].efields[j].min == RANGE_UNSET)
  337. {
  338. expel[nexpel].efields[j].min = -1;
  339. /* pre-populate max field in case not supplied */
  340. expel[nexpel].efields[j].max = -1;
  341. }
  342. else
  343. expel[nexpel].efields[j].max = -1;
  344. i_value = 0;
  345. break;
  346. case '-' : if (i_value)
  347. {
  348. if (expel[nexpel].efields[j].min == RANGE_UNSET)
  349. {
  350. expel[nexpel].efields[j].min = atol(value) - 1;
  351. if (expel[nexpel].efields[j].min < 0)
  352. ret = FALSE;
  353. }
  354. }
  355. else
  356. expel[nexpel].efields[j].min = 0;
  357. i_value = 0;
  358. /* pre-populate max field in case not supplied */
  359. expel[nexpel].efields[j].max = -1;
  360. break;
  361. case ',' : if (i_value)
  362. {
  363. if (expel[nexpel].efields[j].min == RANGE_UNSET)
  364. {
  365. expel[nexpel].efields[j].min = atol(value) - 1;
  366. if (expel[nexpel].efields[j].min < 0)
  367. ret = FALSE;
  368. /* pre-populate max field in case not supplied */
  369. expel[nexpel].efields[j].max = expel[nexpel].efields[j].min;
  370. }
  371. else
  372. {
  373. expel[nexpel].efields[j].max = atol(value) - 1;
  374. if (expel[nexpel].efields[j].max < 0)
  375. ret = FALSE;
  376. }
  377. }
  378. i_value = 0;
  379. /* quick sanity check */
  380. if (expel[nexpel].efields[j].max > 0 && expel[nexpel].efields[j].min > expel[nexpel].efields[j].max)
  381. ret = FALSE;
  382. j++;
  383. break;
  384. default : value[i_value++] = fields[i];
  385. value[i_value] = '\0';
  386. }
  387. }
  388. if (i_value)
  389. {
  390. if (expel[nexpel].efields[j].min == RANGE_UNSET)
  391. {
  392. expel[nexpel].efields[j].min = atol(value) - 1;
  393. if (expel[nexpel].efields[j].min < 0)
  394. ret = FALSE;
  395. /* pre-populate max field in case not supplied */
  396. expel[nexpel].efields[j].max = expel[nexpel].efields[j].min;
  397. }
  398. else
  399. {
  400. expel[nexpel].efields[j].max = atol(value) - 1;
  401. if (expel[nexpel].efields[j].max < 0)
  402. ret = FALSE;
  403. }
  404. /* quick sanity check */
  405. if (expel[nexpel].efields[j].max > 0 && expel[nexpel].efields[j].min > expel[nexpel].efields[j].max)
  406. ret = FALSE;
  407. }
  408. /* quick sanity check */
  409. for (i = 0 ; i < expel[nexpel].n_efields ; i++)
  410. if (expel[nexpel].efields[i].min == RANGE_UNSET && expel[nexpel].efields[i].max == RANGE_UNSET)
  411. ret = FALSE;
  412. }
  413. nexpel++;
  414. }
  415. return(ret);
  416. }
  417. int set_flag_string(status, pos, s, s_length)
  418. int status;
  419. int pos;
  420. unsigned char *s;
  421. int s_length;
  422. {
  423. /* Toggle the flag_status and ensure the terminating string delimiter is correctly identified */
  424. if (!status)
  425. status = TRUE;
  426. else if (pos + 1 >= s_length)
  427. status = FALSE;
  428. else
  429. {
  430. switch (s[pos + 1])
  431. {
  432. case '\'' :
  433. case '\"' :
  434. case ',' :
  435. case ':' :
  436. status = FALSE;
  437. }
  438. }
  439. return(status);
  440. }