aboutsummaryrefslogtreecommitdiff
path: root/src/houdini_html_e.c
blob: 4e523f538ca0a8e585358d1edf389b0e689bfdc4 (plain)
  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "houdini.h"
  5. /**
  6. * According to the OWASP rules:
  7. *
  8. * & --> &amp;
  9. * < --> &lt;
  10. * > --> &gt;
  11. * " --> &quot;
  12. * ' --> &#x27; &apos; is not recommended
  13. * / --> &#x2F; forward slash is included as it helps end an HTML entity
  14. *
  15. */
  16. static const char HTML_ESCAPE_TABLE[] = {
  17. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  18. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  19. 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
  20. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0,
  21. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  22. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  23. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  24. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  25. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  26. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  27. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  28. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  29. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  30. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  31. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  32. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  33. };
  34. static const char *HTML_ESCAPES[] = {
  35. "",
  36. "&quot;",
  37. "&amp;",
  38. "&#39;",
  39. "&#47;",
  40. "&lt;",
  41. "&gt;"
  42. };
  43. int
  44. houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, size_t size, int secure)
  45. {
  46. size_t i = 0, org, esc = 0;
  47. while (i < size) {
  48. org = i;
  49. while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
  50. i++;
  51. if (i > org)
  52. cmark_strbuf_put(ob, src + org, i - org);
  53. /* escaping */
  54. if (unlikely(i >= size))
  55. break;
  56. /* The forward slash is only escaped in secure mode */
  57. if ((src[i] == '/' || src[i] == '\'') && !secure) {
  58. cmark_strbuf_putc(ob, src[i]);
  59. } else {
  60. cmark_strbuf_puts(ob, HTML_ESCAPES[esc]);
  61. }
  62. i++;
  63. }
  64. return 1;
  65. }
  66. int
  67. houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, size_t size)
  68. {
  69. return houdini_escape_html0(ob, src, size, 1);
  70. }