#ifdef XP_WIN32 #define NSAPI_PUBLIC __declspec(dllexport) #else /* !XP_WIN32 */ #define NSAPI_PUBLIC #endif /* !XP_WIN32 */ #include "nsapi.h" NSAPI_PUBLIC int expire(pblock *pb, Session *sn, Request *rq) { char *max_age = 0; rq->directive_is_cacheable = 1; pblock_nvinsert("Cache-control", "public", rq->srvhdrs); max_age = pblock_findval("max-age", pb); if (max_age) { time_t max_age_t = 0; if (sscanf(max_age, "%ld", &max_age_t) == 1) { char expires_string[128]; time_t cur_time = 0; struct tm expires, *expires_ptr; char *ifmodifiedsince = 0; char *path, modified_time[128]; struct stat *finfo; time_t tp; struct tm res, *resp; if (rq->protv_num > 101) /* Must be HTTP/1.1 or lower */ { log_error(LOG_INFORM, "set_cacheable", sn, rq, "protocol higher as HTTP/1.1: %d", rq->protv_num ); return REQ_NOACTION; } cur_time = time(0); cur_time += max_age_t; expires_ptr = system_gmtime(&cur_time, &expires); util_strftime(expires_string, HTTP_DATE_FMT, &expires); param_free(pblock_remove("expires", rq->srvhdrs)); pblock_nvinsert("expires", expires_string, rq->srvhdrs); /* determine 200 or 304 */ ifmodifiedsince = pblock_findval("if-modified-since", rq->headers); if (ifmodifiedsince == 0) { return REQ_NOACTION; /* 200 response */ } path = pblock_findval("path", rq->vars); if (!(finfo = request_stat_path(path, rq))) { log_error(LOG_INFORM, "set_cacheable", sn, rq, "could not stat path %s", path); return REQ_NOACTION; } tp = finfo->st_mtime; resp = system_gmtime(&tp, &res); if (util_later_than(&res, ifmodifiedsince) == 1) /* if not modified since */ { protocol_status(sn, rq, PROTOCOL_NOT_MODIFIED, NULL); /* We need to get rid of the superfluous HTTP headers. */ param_free(pblock_remove("content-type", rq->srvhdrs)); param_free(pblock_remove("Cache-control", rq->srvhdrs)); /* send response here, do not let the iplanet internal function do this. The internal function strips of the 'Expires' header */ if (protocol_start_response(sn, rq) == REQ_ABORTED) { log_error(LOG_INFORM, "set_cacheable", sn, rq, "Could not send HTTP response"); return REQ_ABORTED; } return REQ_PROCEED; } } } return REQ_NOACTION; }