Annotation of embedaddon/lighttpd/src/etag.c, revision 1.1.1.2
1.1.1.2 ! misho 1: #include "first.h"
! 2:
1.1 misho 3: #include "buffer.h"
4: #include "etag.h"
5:
6: #if defined HAVE_STDINT_H
7: # include <stdint.h>
8: #elif defined HAVE_INTTYPES_H
9: # include <inttypes.h>
10: #endif
11:
12: #include <string.h>
13:
1.1.1.2 ! misho 14: int etag_is_equal(buffer *etag, const char *line, int weak_ok) {
! 15: enum {
! 16: START = 0,
! 17: CHECK,
! 18: CHECK_QUOTED,
! 19: SKIP,
! 20: SKIP_QUOTED,
! 21: TAIL
! 22: } state = START;
! 23:
! 24: const char *current;
! 25: const char *tok_start;
! 26: const char *tok = NULL;
! 27: int matched;
! 28:
! 29: if ('*' == line[0] && '\0' == line[1]) {
! 30: return 1;
! 31: }
! 32:
! 33: if (!etag || buffer_string_is_empty(etag)) return 0;
! 34: tok_start = etag->ptr;
! 35:
! 36: if ('W' == tok_start[0]) {
! 37: if (!weak_ok || '/' != tok_start[1]) return 0; /* bad etag */
! 38: tok_start = tok_start + 2;
! 39: }
! 40:
! 41: if ('"' != tok_start[0]) return 0; /* bad etag */
! 42: /* we start comparing after the first '"' */
! 43: ++tok_start;
! 44:
! 45: for (current = line; *current; ++current) {
! 46: switch (state) {
! 47: case START:
! 48: /* wait for etag to start; ignore whitespace and ',' */
! 49: switch (*current) {
! 50: case 'W':
! 51: /* weak etag always starts with 'W/"' */
! 52: if ('/' != *++current) return 0; /* bad etag list */
! 53: if ('"' != *++current) return 0; /* bad etag list */
! 54: if (!weak_ok) {
! 55: state = SKIP;
! 56: } else {
! 57: state = CHECK;
! 58: tok = tok_start;
! 59: }
! 60: break;
! 61: case '"':
! 62: /* strong etag starts with '"' */
! 63: state = CHECK;
! 64: tok = tok_start;
! 65: break;
! 66: case ' ':
! 67: case ',':
! 68: case '\t':
! 69: case '\r':
! 70: case '\n':
! 71: break;
! 72: default:
! 73: return 0; /* bad etag list */
! 74: }
! 75: break;
! 76: case CHECK:
! 77: /* compare etags (after the beginning '"')
! 78: * quoted-pairs must match too (i.e. quoted in both strings):
! 79: * > (RFC 2616:) both validators MUST be identical in every way
! 80: */
! 81: matched = *tok && *tok == *current;
! 82: ++tok;
! 83: switch (*current) {
! 84: case '\\':
! 85: state = matched ? CHECK_QUOTED : SKIP_QUOTED;
! 86: break;
! 87: case '"':
! 88: if (*tok) {
! 89: /* bad etag - string should end after '"' */
! 90: return 0;
! 91: }
! 92: if (matched) {
! 93: /* matching etag: strings were equal */
! 94: return 1;
! 95: }
! 96:
! 97: state = TAIL;
! 98: break;
! 99: default:
! 100: if (!matched) {
! 101: /* strings not matching, skip remainder of etag */
! 102: state = SKIP;
! 103: }
! 104: break;
! 105: }
! 106: break;
! 107: case CHECK_QUOTED:
! 108: if (!*tok || *tok != *current) {
! 109: /* strings not matching, skip remainder of etag */
! 110: state = SKIP;
! 111: break;
! 112: }
! 113: ++tok;
! 114: state = CHECK;
! 115: break;
! 116: case SKIP:
! 117: /* wait for final (not quoted) '"' */
! 118: switch (*current) {
! 119: case '\\':
! 120: state = SKIP_QUOTED;
! 121: break;
! 122: case '"':
! 123: state = TAIL;
! 124: break;
! 125: }
! 126: break;
! 127: case SKIP_QUOTED:
! 128: state = SKIP;
! 129: break;
! 130: case TAIL:
! 131: /* search for ',', ignore white space */
! 132: switch (*current) {
! 133: case ',':
! 134: state = START;
! 135: break;
! 136: case ' ':
! 137: case '\t':
! 138: case '\r':
! 139: case '\n':
! 140: break;
! 141: default:
! 142: return 0; /* bad etag list */
! 143: }
! 144: break;
! 145: }
! 146: }
! 147: /* no matching etag found */
1.1 misho 148: return 0;
149: }
150:
151: int etag_create(buffer *etag, struct stat *st,etag_flags_t flags) {
152: if (0 == flags) return 0;
153:
154: buffer_reset(etag);
155:
156: if (flags & ETAG_USE_INODE) {
1.1.1.2 ! misho 157: buffer_append_int(etag, st->st_ino);
1.1 misho 158: buffer_append_string_len(etag, CONST_STR_LEN("-"));
159: }
160:
161: if (flags & ETAG_USE_SIZE) {
1.1.1.2 ! misho 162: buffer_append_int(etag, st->st_size);
1.1 misho 163: buffer_append_string_len(etag, CONST_STR_LEN("-"));
164: }
165:
166: if (flags & ETAG_USE_MTIME) {
1.1.1.2 ! misho 167: buffer_append_int(etag, st->st_mtime);
1.1 misho 168: }
169:
170: return 0;
171: }
172:
173: int etag_mutate(buffer *mut, buffer *etag) {
1.1.1.2 ! misho 174: size_t i, len;
1.1 misho 175: uint32_t h;
176:
1.1.1.2 ! misho 177: len = buffer_string_length(etag);
! 178: for (h=0, i=0; i < len; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
1.1 misho 179:
180: buffer_reset(mut);
181: buffer_copy_string_len(mut, CONST_STR_LEN("\""));
1.1.1.2 ! misho 182: buffer_append_int(mut, h);
1.1 misho 183: buffer_append_string_len(mut, CONST_STR_LEN("\""));
184:
185: return 0;
186: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>