99 |
|
|
100 |
/* Check the If-Match, If-Modified etc stuff. |
/* Check the If-Match, If-Modified etc stuff. |
101 |
*/ |
*/ |
102 |
if (req->if_type) |
if (req->if_types) |
103 |
if (check_if_stuff(req) == 0) { |
if (check_if_stuff(req) == 0) { |
104 |
close(data_fd); |
close(data_fd); |
105 |
return 0; |
return 0; |
237 |
*/ |
*/ |
238 |
#define MAX_COMMA_SEP_ELEMENTS 6 |
#define MAX_COMMA_SEP_ELEMENTS 6 |
239 |
inline |
inline |
240 |
static void break_comma_list( char* etag, char* broken_etag[MAX_COMMA_SEP_ELEMENTS], int* elements) |
static void break_comma_list(char *etag, |
241 |
|
char *broken_etag[MAX_COMMA_SEP_ELEMENTS], |
242 |
|
int *elements) |
243 |
{ |
{ |
244 |
*elements = 0; |
*elements = 0; |
245 |
char *p = etag; |
char *p = etag; |
246 |
|
|
247 |
do { |
do { |
248 |
broken_etag[*elements] = p; |
broken_etag[*elements] = p; |
249 |
|
|
250 |
(*elements)++; |
(*elements)++; |
251 |
|
|
252 |
p = strchr( p, ','); |
p = strchr(p, ','); |
253 |
if (p) { |
if (p) { |
254 |
*p = 0; |
*p = 0; |
255 |
p++; /* move to next entry and skip white |
p++; /* move to next entry and skip white |
256 |
* space. |
* space. |
257 |
*/ |
*/ |
258 |
while (*p == ' ') p++; |
while (*p == ' ') |
259 |
} |
p++; |
260 |
} while( p != NULL && *elements < MAX_COMMA_SEP_ELEMENTS); |
} |
261 |
|
} while (p != NULL && *elements < MAX_COMMA_SEP_ELEMENTS); |
262 |
} |
} |
263 |
|
|
264 |
/* |
/* |
267 |
* |
* |
268 |
* req->last_modified, and req->filesize MUST have been set |
* req->last_modified, and req->filesize MUST have been set |
269 |
* before calling this function. This function should be called |
* before calling this function. This function should be called |
270 |
* if req->if_type != 0. |
* if req->if_types != 0. |
271 |
* |
* |
272 |
* Return values: |
* Return values: |
273 |
* 1: Successful, continue sending the file |
* 1: Successful, continue sending the file |
277 |
static int check_if_stuff(request * req) |
static int check_if_stuff(request * req) |
278 |
{ |
{ |
279 |
int comp = 0; |
int comp = 0; |
280 |
|
char *broken_etag[MAX_COMMA_SEP_ELEMENTS]; |
281 |
|
int broken_etag_size, i; |
282 |
|
char new_etag[MAX_ETAG_LENGTH]; |
283 |
|
|
284 |
/* Although we allow multiple If-* directives to be used, we |
/* Although we allow multiple If-* directives to be used, we |
285 |
* actually use only one. The priority used is shown below. |
* actually use only one. The priority used is shown below. |
286 |
*/ |
*/ |
287 |
|
|
288 |
/* First try IF_MODIFIED_SINCE |
/* First try IF_MODIFIED_SINCE |
289 |
*/ |
*/ |
290 |
if (req->if_type & IF_MODIFIED_SINCE) { |
if (req->if_types & IF_MODIFIED_SINCE) { |
291 |
if (!modified_since(req->last_modified, req->if_modified_since)) { |
if (!modified_since(req->last_modified, req->if_modified_since)) { |
292 |
send_r_not_modified(req); |
send_r_not_modified(req); |
293 |
return 0; |
return 0; |
295 |
return 1; |
return 1; |
296 |
} |
} |
297 |
|
|
298 |
/* After that we need the etag |
|
299 |
|
/* Then try IF_MATCH |
300 |
*/ |
*/ |
301 |
if (req->etag == NULL) |
if (req->if_types & IF_MATCH) { |
|
return 1; |
|
302 |
|
|
|
if (req->etag[0] == '"') { /* ETag may contain a date, if If-Range |
|
|
* was used. |
|
|
*/ |
|
|
char * broken_etag[MAX_COMMA_SEP_ELEMENTS]; |
|
|
int broken_etag_size, i; |
|
|
|
|
303 |
/* Check for the "*" |
/* Check for the "*" |
304 |
*/ |
*/ |
305 |
if (strncmp(req->etag, "\"*\"", 3) == 0) { |
if (strncmp(req->if_match_etag, "\"*\"", 3) == 0) { |
306 |
comp = 0; /* comparison is always ok */ |
comp = 0; /* comparison is always ok */ |
307 |
} else { |
} else { |
|
char new_etag[MAX_ETAG_LENGTH]; |
|
308 |
|
|
309 |
/* Create the current ETag |
/* Create the current ETag of the file. |
310 |
*/ |
*/ |
311 |
create_etag(req->filesize, req->last_modified, new_etag); |
create_etag(req->filesize, req->last_modified, new_etag); |
312 |
|
|
313 |
/* Check if one of the ETags sent, match ours |
/* Check if one of the ETags sent, match ours |
314 |
*/ |
*/ |
315 |
|
break_comma_list(req->if_match_etag, broken_etag, |
316 |
|
&broken_etag_size); |
317 |
|
|
318 |
break_comma_list( req->etag, broken_etag, &broken_etag_size); |
comp = 1; |
319 |
|
for (i = 0; i < broken_etag_size; i++) { |
320 |
comp = 1; |
comp = strcmp(broken_etag[i], new_etag); |
321 |
for (i=0;i<broken_etag_size;i++) { |
if (comp == 0) /* matches! */ |
322 |
comp = strcmp(broken_etag[i], new_etag); |
break; |
323 |
if (comp==0) /* matches! */ |
} |
|
break; |
|
|
} |
|
324 |
|
|
325 |
|
|
326 |
} |
} |
|
} |
|
327 |
|
|
|
/* Then try IF_MATCH |
|
|
*/ |
|
|
if (req->if_type & IF_MATCH) { |
|
328 |
if (comp == 0) |
if (comp == 0) |
329 |
return 1; |
return 1; |
330 |
send_r_precondition_failed(req); |
send_r_precondition_failed(req); |
333 |
|
|
334 |
/* Then try IF_RANGE |
/* Then try IF_RANGE |
335 |
*/ |
*/ |
336 |
if (req->if_type & IF_RANGE) { |
if (req->if_types & IF_RANGE) { |
337 |
if (req->etag[0] != '"') { /* Not '"' there, so he has a |
if (req->if_range_etag[0] == '"') { /* ETag may contain a date, if If-Range |
338 |
* date in the etag */ |
* was used. |
339 |
if (!modified_since(req->last_modified, req->etag)) { |
*/ |
340 |
return 1; |
/* Check for the "*" |
341 |
|
*/ |
342 |
|
if (strncmp(req->if_range_etag, "\"*\"", 3) == 0) { |
343 |
|
comp = 0; /* comparison is always ok */ |
344 |
|
} else { |
345 |
|
|
346 |
|
/* Create the current ETag |
347 |
|
*/ |
348 |
|
create_etag(req->filesize, req->last_modified, new_etag); |
349 |
|
|
350 |
|
/* Check if one of the ETags sent, match ours |
351 |
|
*/ |
352 |
|
|
353 |
|
break_comma_list(req->if_range_etag, broken_etag, |
354 |
|
&broken_etag_size); |
355 |
|
|
356 |
|
comp = 1; |
357 |
|
for (i = 0; i < broken_etag_size; i++) { |
358 |
|
comp = strcmp(broken_etag[i], new_etag); |
359 |
|
if (comp == 0) /* matches! */ |
360 |
|
break; |
361 |
|
} |
362 |
|
|
363 |
|
|
364 |
} |
} |
365 |
/* it was modified */ |
} else { |
366 |
req->range_start = req->range_stop = 0; |
comp = modified_since(req->last_modified, req->if_range_etag); |
|
return 1; |
|
367 |
} |
} |
368 |
|
|
369 |
|
|
370 |
|
/* File didn't change */ |
371 |
if (comp == 0) |
if (comp == 0) |
372 |
return 1; |
return 1; |
373 |
|
|
374 |
/* Ok, but send the whole file, because |
/* File has been changed, but it is Ok, so send the whole |
375 |
* it has been changed. |
* file. |
376 |
*/ |
*/ |
377 |
req->range_start = req->range_stop = 0; |
req->range_start = req->range_stop = 0; |
378 |
return 1; |
return 1; |
380 |
|
|
381 |
/* Then try IF_NONE_MATCH |
/* Then try IF_NONE_MATCH |
382 |
*/ |
*/ |
383 |
if (req->if_type & IF_NONE_MATCH) { |
if (req->if_types & IF_NONE_MATCH) { |
384 |
|
/* Check for the "*" |
385 |
|
*/ |
386 |
|
if (strncmp(req->if_none_match_etag, "\"*\"", 3) == 0) { |
387 |
|
comp = 0; /* comparison is always ok */ |
388 |
|
} else { |
389 |
|
|
390 |
|
/* Create the current ETag |
391 |
|
*/ |
392 |
|
create_etag(req->filesize, req->last_modified, new_etag); |
393 |
|
|
394 |
|
/* Check if one of the ETags sent, match ours |
395 |
|
*/ |
396 |
|
|
397 |
|
break_comma_list(req->if_none_match_etag, broken_etag, |
398 |
|
&broken_etag_size); |
399 |
|
|
400 |
|
comp = 1; |
401 |
|
for (i = 0; i < broken_etag_size; i++) { |
402 |
|
comp = strcmp(broken_etag[i], new_etag); |
403 |
|
if (comp == 0) /* matches! */ |
404 |
|
break; |
405 |
|
} |
406 |
|
|
407 |
|
|
408 |
|
} |
409 |
|
|
410 |
if (comp == 0) { |
if (comp == 0) { |
411 |
send_r_not_modified(req); |
send_r_not_modified(req); |
412 |
return 0; |
return 0; |