lighttpd 1.4.x https://www.lighttpd.net/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.3 KiB

  1. /*
  2. * http_etag - HTTP ETag manipulation
  3. *
  4. * Copyright(c) 2015,2020 Glenn Strauss gstrauss()gluelogic.com All rights reserved
  5. * License: BSD 3-clause (same as lighttpd)
  6. */
  7. #include "first.h"
  8. #include "http_etag.h"
  9. #include <sys/stat.h>
  10. #include <string.h>
  11. #include "algo_md.h"
  12. #include "buffer.h"
  13. int
  14. http_etag_matches (const buffer * const etag, const char *s, const int weak_ok)
  15. {
  16. if ('*' == s[0] && '\0' == s[1]) return 1;
  17. if (buffer_string_is_empty(etag)) return 0;
  18. uint32_t etag_sz = buffer_string_length(etag);
  19. const char *etag_ptr = etag->ptr;
  20. if (etag_ptr[0] == 'W' && etag_ptr[1] == '/') {
  21. if (!weak_ok) return 0;
  22. etag_ptr += 2;
  23. etag_sz -= 2;
  24. }
  25. while (*s) {
  26. while (*s == ' ' || *s == '\t' || *s == ',') ++s;
  27. if (s[0] == 'W' && s[1] == '/' ? (s+=2, weak_ok) : 1) {
  28. if (0 == strncmp(s, etag_ptr, etag_sz) || *s == '*') {
  29. s += (*s != '*' ? etag_sz : 1);
  30. if (*s == '\0' || *s == ' ' || *s == '\t' || *s == ',')
  31. return 1;
  32. }
  33. }
  34. while (*s != '\0' && *s != ',') ++s;
  35. }
  36. return 0;
  37. }
  38. static void
  39. http_etag_remix (buffer * const etag, const char * const str, const uint32_t len)
  40. {
  41. uint32_t h = dekhash(str, len, len); /*(pass len as initial hash value)*/
  42. uint32_t elen = buffer_string_length(etag);
  43. if (elen > 2) /*(expect "..." if set)*/
  44. h = dekhash(etag->ptr+1, elen-2, h);
  45. buffer_string_set_length(etag, 1);
  46. etag->ptr[0] = '\"';
  47. buffer_append_int(etag, h);
  48. buffer_append_string_len(etag, CONST_STR_LEN("\""));
  49. }
  50. void
  51. http_etag_create (buffer * const etag, const struct stat * const st, const int flags)
  52. {
  53. if (0 == flags) return;
  54. uint64_t x[4];
  55. uint32_t len = 0;
  56. if (flags & ETAG_USE_INODE)
  57. x[len++] = (uint64_t)st->st_ino;
  58. if (flags & ETAG_USE_SIZE)
  59. x[len++] = (uint64_t)st->st_size;
  60. if (flags & ETAG_USE_MTIME) {
  61. x[len++] = (uint64_t)st->st_mtime;
  62. #ifdef st_mtime /* use high-precision timestamp if available */
  63. #if defined(__APPLE__) && defined(__MACH__)
  64. x[len++] = (uint64_t)st->st_mtimespec.tv_nsec;
  65. #else
  66. x[len++] = (uint64_t)st->st_mtim.tv_nsec;
  67. #endif
  68. #endif
  69. }
  70. buffer_clear(etag);
  71. http_etag_remix(etag, (char *)x, len << 3);
  72. }