res_ari_model.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013, Digium, Inc.
  5. *
  6. * David M. Lee, II <dlee@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Implementation Swagger validators.
  21. *
  22. * \author David M. Lee, II <dlee@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <support_level>core</support_level>
  26. ***/
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "ari/ari_model_validators.h"
  30. #include "asterisk/logger.h"
  31. #include "asterisk/module.h"
  32. #include "asterisk/utils.h"
  33. #include <regex.h>
  34. /* Regex to match date strings */
  35. static regex_t date_regex;
  36. /* Regex for YYYY-MM-DD */
  37. #define REGEX_YMD "[0-9]{4}-[01][0-9]-[0-3][0-9]"
  38. /* Regex for hh:mm(:ss(.s)); seconds and subseconds optional
  39. * Handles the probably impossible case of a leap second, too */
  40. #define REGEX_HMS "[0-2][0-9]:[0-5][0-9](:[0-6][0-9](.[0-9]+)?)?"
  41. /* Regex for timezone: (+|-)hh(:mm), with optional colon. */
  42. #define REGEX_TZ "(Z|[-+][0-2][0-9](:?[0-5][0-9])?)"
  43. /* REGEX for ISO 8601, the time specifier optional */
  44. #define ISO8601_PATTERN "^" REGEX_YMD "(T" REGEX_HMS REGEX_TZ ")?$"
  45. static int check_type(struct ast_json *json, enum ast_json_type expected)
  46. {
  47. enum ast_json_type actual;
  48. if (!json) {
  49. ast_log(LOG_ERROR, "Expected type %s, was NULL\n",
  50. ast_json_typename(expected));
  51. return 0;
  52. }
  53. actual = ast_json_typeof(json);
  54. if (expected != actual) {
  55. ast_log(LOG_ERROR, "Expected type %s, was %s\n",
  56. ast_json_typename(expected), ast_json_typename(actual));
  57. return 0;
  58. }
  59. return 1;
  60. }
  61. static int check_range(intmax_t minval, intmax_t maxval, struct ast_json *json)
  62. {
  63. intmax_t v;
  64. if (!check_type(json, AST_JSON_INTEGER)) {
  65. return 0;
  66. }
  67. v = ast_json_integer_get(json);
  68. if (v < minval || maxval < v) {
  69. ast_log(LOG_ERROR, "Value out of range. Expected %jd <= %jd <= %jd\n", minval, v, maxval);
  70. return 0;
  71. }
  72. return 1;
  73. }
  74. int ast_ari_validate_void(struct ast_json *json)
  75. {
  76. return check_type(json, AST_JSON_NULL);
  77. }
  78. int ast_ari_validate_object(struct ast_json *json)
  79. {
  80. return check_type(json, AST_JSON_OBJECT);
  81. }
  82. int ast_ari_validate_byte(struct ast_json *json)
  83. {
  84. /* Java bytes are signed, which accounts for great fun for all */
  85. return check_range(-128, 255, json);
  86. }
  87. int ast_ari_validate_boolean(struct ast_json *json)
  88. {
  89. enum ast_json_type actual = ast_json_typeof(json);
  90. switch (actual) {
  91. case AST_JSON_TRUE:
  92. case AST_JSON_FALSE:
  93. return 1;
  94. default:
  95. ast_log(LOG_ERROR, "Expected type boolean, was %s\n",
  96. ast_json_typename(actual));
  97. return 0;
  98. }
  99. }
  100. int ast_ari_validate_int(struct ast_json *json)
  101. {
  102. /* Swagger int's are 32-bit */
  103. return check_range(-2147483648LL, 2147483647LL, json);
  104. }
  105. int ast_ari_validate_long(struct ast_json *json)
  106. {
  107. /* All integral values are valid longs. No need for range check. */
  108. return check_type(json, AST_JSON_INTEGER);
  109. }
  110. int ast_ari_validate_float(struct ast_json *json)
  111. {
  112. return check_type(json, AST_JSON_REAL);
  113. }
  114. int ast_ari_validate_double(struct ast_json *json)
  115. {
  116. return check_type(json, AST_JSON_REAL);
  117. }
  118. int ast_ari_validate_string(struct ast_json *json)
  119. {
  120. return check_type(json, AST_JSON_STRING);
  121. }
  122. int ast_ari_validate_date(struct ast_json *json)
  123. {
  124. /* Dates are ISO-8601 strings */
  125. const char *str;
  126. if (!check_type(json, AST_JSON_STRING)) {
  127. return 0;
  128. }
  129. str = ast_json_string_get(json);
  130. ast_assert(str != NULL);
  131. if (regexec(&date_regex, str, 0, NULL, 0) != 0) {
  132. ast_log(LOG_ERROR, "Date field is malformed: '%s'\n", str);
  133. return 0;
  134. }
  135. return 1;
  136. }
  137. int ast_ari_validate_list(struct ast_json *json, int (*fn)(struct ast_json *))
  138. {
  139. int res = 1;
  140. size_t i;
  141. if (!check_type(json, AST_JSON_ARRAY)) {
  142. return 0;
  143. }
  144. for (i = 0; i < ast_json_array_size(json); ++i) {
  145. int member_res;
  146. member_res = fn(ast_json_array_get(json, i));
  147. if (!member_res) {
  148. ast_log(LOG_ERROR,
  149. "Array member %zu failed validation\n", i);
  150. res = 0;
  151. }
  152. }
  153. return res;
  154. }
  155. static int load_module(void)
  156. {
  157. int res;
  158. res = regcomp(&date_regex, ISO8601_PATTERN,
  159. REG_EXTENDED | REG_ICASE | REG_NOSUB);
  160. if (res != 0) {
  161. return AST_MODULE_LOAD_FAILURE;
  162. }
  163. return AST_MODULE_LOAD_SUCCESS;
  164. }
  165. static int unload_module(void)
  166. {
  167. regfree(&date_regex);
  168. return 0;
  169. }
  170. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER | AST_MODFLAG_GLOBAL_SYMBOLS, "ARI Model validators",
  171. .support_level = AST_MODULE_SUPPORT_CORE,
  172. .load = load_module,
  173. .unload = unload_module,
  174. .load_pri = AST_MODPRI_APP_DEPEND,
  175. );