tnet_dns_regexp.rl 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (C) 2010-2015 Mamadou DIOP.
  3. *
  4. * This file is part of Open Source Doubango Framework.
  5. *
  6. * DOUBANGO is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * DOUBANGO is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with DOUBANGO.
  18. *
  19. */
  20. /**@file tnet_dns_regexp.c
  21. * @brief DNS Regex parser for NAPTR RR.
  22. */
  23. #include "tnet_dns_regexp.h"
  24. #include "tsk_string.h"
  25. #include "tsk_memory.h"
  26. #include "tsk_ragel_state.h"
  27. #include "tsk_debug.h"
  28. #include <string.h>
  29. /* === Ragel state machine === */
  30. %%{
  31. machine tdns_machine_regexp;
  32. action tag {
  33. tag_start = p;
  34. }
  35. action parse_prefix {
  36. TSK_PARSER_SET_STRING(prefix);
  37. }
  38. action cat_any{
  39. int len = (int)(p - tag_start);
  40. if (len) {
  41. tsk_strncat(&ret, tag_start, len);
  42. }
  43. }
  44. action cat_group {
  45. if (prefix) {
  46. int prefixlen = (tsk_size_t)tsk_strlen(prefix);
  47. tsk_strncat(&ret, e164num + prefixlen, (e164len - prefixlen));
  48. }
  49. }
  50. # http://www.itu.int/itudoc/itu-t/workshop/enum/012_pp7.ppt
  51. # The format is like this: !<regexp>!<string>!
  52. # * 1. Match <regexp> on the original E.164 number
  53. # * 2. Apply rewrite rule <string>
  54. # * \n in <string> is replaced with group number 'n' in <regexp>
  55. #
  56. regexp = (".*") | ("\\"? <:any*>tag %parse_prefix :>"(.*)");
  57. group = "\\" digit;
  58. string = (any -- "\\")*>tag %cat_any (group >tag %cat_group)? (any -- "\\")*>tag %cat_any;
  59. # Supported regexp --> !^.*$! or !^+1800(.*)! where "1800" is called the prefix
  60. main := "!^"<: regexp :> "$!" <: string :>"!" "i"?;
  61. }%%
  62. /**
  63. * Apply @a regexp to @a e164num.
  64. * @param e164num Original E.164 number supplied by the user (only digits or '+' are accepted).
  65. * @param regexp A <character-string> containing a substitution expression that is
  66. * applied to the original string held by the client in order to
  67. * construct the next domain name to lookup. Example: "!^.*$!sip:bob@doubango.org!i".
  68. * @retval The final Internet address. It's up to the caller to free the string.
  69. */
  70. char* tnet_dns_regex_parse(const char* e164num, const char* regexp)
  71. {
  72. char* ret = tsk_null;
  73. char* prefix = tsk_null;
  74. const char* tag_start;
  75. tsk_size_t e164len;
  76. // Ragel
  77. int cs = 0;
  78. const char *p = tag_start = regexp;
  79. const char *pe;
  80. const char *eof;
  81. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  82. %%write data;
  83. TSK_RAGEL_DISABLE_WARNINGS_END()
  84. (void)(eof);
  85. (void)(tdns_machine_regexp_first_final);
  86. (void)(tdns_machine_regexp_error);
  87. (void)(tdns_machine_regexp_en_main);
  88. if (!e164num) {
  89. goto bail;
  90. }
  91. if (!regexp) {
  92. ret = tsk_strdup(e164num);
  93. goto bail;
  94. }
  95. e164len = (tsk_size_t)tsk_strlen(e164num);
  96. pe = p + tsk_strlen(regexp);
  97. eof = pe;
  98. TSK_RAGEL_DISABLE_WARNINGS_BEGIN()
  99. %%write init;
  100. %%write exec;
  101. TSK_RAGEL_DISABLE_WARNINGS_END()
  102. if (cs < %%{ write first_final; }%% ){
  103. TSK_DEBUG_ERROR("regexp substitition failed.");
  104. TSK_FREE(ret);
  105. }
  106. bail:
  107. TSK_FREE(prefix);
  108. return ret;
  109. }