]>
Commit | Line | Data |
---|---|---|
774c051c | 1 | #include "squid.h" |
2 | #include "HttpReply.h" | |
3 | #include "ICAPOptions.h" | |
4 | #include "TextException.h" | |
78e8cfc4 | 5 | #include "ICAPConfig.h" |
6 | ||
7 | extern ICAPConfig TheICAPConfig; | |
774c051c | 8 | |
9 | ICAPOptions::ICAPOptions(): error("unconfigured"), method(ICAP::methodNone), | |
10 | max_connections(-1), allow204(false), | |
8eeb99bf | 11 | preview(-1), theTTL(-1), transfer_ext(NULL) |
774c051c | 12 | { |
13 | transfers.preview = transfers.ignore = transfers.complete = NULL; | |
14 | transfers.other = TRANSFER_NONE; | |
15 | }; | |
16 | ||
17 | ICAPOptions::~ICAPOptions() | |
18 | { | |
19 | delete transfers.preview; | |
20 | delete transfers.ignore; | |
21 | delete transfers.complete; | |
22 | delete transfer_ext; | |
23 | }; | |
24 | ||
25 | ICAPOptions::transfer_type ICAPOptions::getTransferExt(const char *s) | |
26 | { | |
27 | ||
28 | if (transfer_ext) { | |
29 | List<TransferPair> *data = transfer_ext; | |
30 | ||
31 | while (data) { | |
32 | if (*(data->element.ext) == *s) { | |
33 | return data->element.type; | |
34 | } | |
35 | ||
36 | data = data->next; | |
37 | } | |
38 | } | |
39 | ||
40 | return TRANSFER_NONE; | |
41 | } | |
42 | ||
774c051c | 43 | void ICAPOptions::insertTransferExt(const char *t, transfer_type t_type) |
44 | { | |
45 | List<TransferPair> **Tail; | |
46 | TransferPair t_ext; | |
47 | ||
48 | if (t == "*") { | |
49 | transfers.other = t_type; | |
50 | return; | |
51 | } | |
52 | ||
53 | for (Tail = &transfer_ext; *Tail; Tail = &((*Tail)->next)) { | |
54 | if (*(*Tail)->element.ext == *t) { | |
55 | (*Tail)->element.type = t_type; | |
56 | return; | |
57 | } | |
58 | } | |
59 | ||
60 | t_ext.ext = xstrdup(t); | |
61 | t_ext.type = t_type; | |
62 | List<TransferPair> *q = new List<TransferPair>(t_ext); | |
63 | *(Tail) = q; | |
64 | ||
65 | }; | |
66 | ||
9d0cdbb9 | 67 | void ICAPOptions::cfgTransferListHeader(const HttpHeader *h, const char *fname, transfer_type t_type) |
68 | { | |
69 | const String s = httpHeaderGetByName(h, fname); | |
70 | ||
71 | if (!s.size()) | |
72 | return; | |
73 | ||
74 | if (t_type == TRANSFER_PREVIEW) | |
75 | transfers.preview = parseExtFileList(s.buf(), s.buf() + s.size(), t_type); | |
76 | else if (t_type == TRANSFER_IGNORE) | |
77 | transfers.ignore = parseExtFileList(s.buf(), s.buf() + s.size(), t_type); | |
78 | else if (t_type == TRANSFER_COMPLETE) | |
79 | transfers.complete = parseExtFileList(s.buf(), s.buf() + s.size(), t_type); | |
80 | else | |
81 | fatalf("Unexpected transfer_type at %s:%d", __FILE__,__LINE__); | |
82 | } | |
83 | ||
774c051c | 84 | List<String> *ICAPOptions::parseExtFileList(const char *start, const char *end, transfer_type t_type) |
85 | { | |
9d0cdbb9 | 86 | const String s = xstrndup(start, end - start + 1); |
774c051c | 87 | const char *item; |
88 | const char *pos = NULL; | |
89 | char *fext = NULL; | |
90 | int ilen; | |
91 | String t = NULL; | |
92 | ||
93 | List<String> **Tail; | |
94 | List<String> *H; | |
95 | ||
96 | for (Tail = &H; *Tail; Tail = &((*Tail)->next)) | |
97 | ||
98 | ; | |
99 | while (strListGetItem(&s, ',', &item, &ilen, &pos)) { | |
100 | fext = xstrndup(item, ilen + 1); | |
101 | t = fext; | |
102 | List<String> *q = new List<String> (t); | |
103 | *(Tail) = q; | |
104 | Tail = &q->next; | |
105 | insertTransferExt(fext, t_type); | |
106 | } | |
107 | ||
108 | return H; | |
109 | } | |
110 | ||
774c051c | 111 | bool ICAPOptions::valid() const |
112 | { | |
113 | return !error; | |
114 | } | |
115 | ||
116 | bool ICAPOptions::fresh() const | |
117 | { | |
118 | return squid_curtime <= expire(); | |
119 | } | |
120 | ||
121 | time_t ICAPOptions::expire() const | |
122 | { | |
123 | Must(valid()); | |
8eeb99bf | 124 | return theTTL >= 0 ? theTimestamp + theTTL : -1; |
774c051c | 125 | } |
126 | ||
127 | void ICAPOptions::configure(const HttpReply *reply) | |
128 | { | |
129 | error = NULL; // reset initial "unconfigured" value (or an old error?) | |
130 | ||
131 | const HttpHeader *h = &reply->header; | |
132 | ||
133 | if (reply->sline.status != 200) | |
134 | error = "unsupported status code of OPTIONS response"; | |
135 | ||
136 | // Methods | |
9d0cdbb9 | 137 | if (httpHeaderHasByNameListMember(h, "Methods", "REQMOD", ',')) |
774c051c | 138 | cfgMethod(ICAP::methodReqmod); |
139 | ||
9d0cdbb9 | 140 | if (httpHeaderHasByNameListMember(h, "Methods", "RESPMOD", ',')) |
774c051c | 141 | cfgMethod(ICAP::methodRespmod); |
142 | ||
143 | service = httpHeaderGetByName(h, "Service"); | |
144 | ||
145 | serviceId = httpHeaderGetByName(h, "ServiceId"); | |
146 | ||
147 | istag = httpHeaderGetByName(h, "ISTag"); | |
148 | ||
149 | if (httpHeaderGetByName(h, "Opt-body-type").size()) | |
150 | error = "ICAP service returns unsupported OPTIONS body"; | |
151 | ||
152 | cfgIntHeader(h, "Max-Connections", max_connections); | |
153 | ||
8eeb99bf | 154 | cfgIntHeader(h, "Options-TTL", theTTL); |
774c051c | 155 | |
78e8cfc4 | 156 | if (theTTL < 0) |
157 | theTTL = TheICAPConfig.default_options_ttl; | |
158 | ||
8eeb99bf | 159 | theTimestamp = httpHeaderGetTime(h, HDR_DATE); |
774c051c | 160 | |
8eeb99bf | 161 | if (theTimestamp < 0) |
162 | theTimestamp = squid_curtime; | |
774c051c | 163 | |
9d0cdbb9 | 164 | if (httpHeaderHasListMember(h, HDR_ALLOW, "204", ',')) |
774c051c | 165 | allow204 = true; |
166 | ||
167 | cfgIntHeader(h, "Preview", preview); | |
168 | ||
9d0cdbb9 | 169 | cfgTransferListHeader(h, "Transfer-Preview", TRANSFER_PREVIEW); |
774c051c | 170 | |
9d0cdbb9 | 171 | cfgTransferListHeader(h, "Transfer-Ignore", TRANSFER_IGNORE); |
774c051c | 172 | |
9d0cdbb9 | 173 | cfgTransferListHeader(h, "Transfer-Complete", TRANSFER_COMPLETE); |
774c051c | 174 | } |
175 | ||
176 | void ICAPOptions::cfgMethod(ICAP::Method m) | |
177 | { | |
178 | Must(m != ICAP::methodNone); | |
179 | ||
180 | if (method == ICAP::methodNone) | |
181 | method = m; | |
182 | else | |
183 | error = "the service claims to support several request methods"; | |
184 | } | |
185 | ||
186 | // TODO: HttpHeader should provide a general method for this type of conversion | |
187 | void ICAPOptions::cfgIntHeader(const HttpHeader *h, const char *fname, int &value) | |
188 | { | |
189 | const String s = httpHeaderGetByName(h, fname); | |
190 | ||
191 | if (s.size() && xisdigit(*s.buf())) | |
192 | value = atoi(s.buf()); | |
193 | else | |
194 | value = -1; | |
195 | } |