/* ** Check whether we can cache this object or not. */ PUBLIC HTCachable HTResponse_isCachable (HTResponse * me) { if (me) { /* We may already have decided that this object is not cachable */ if (me->cachable == HT_NO_CACHE) return HT_NO_CACHE; #if 0 /* We don't cache negotiated resources for the moment */ if (me->variants) return HT_NO_CACHE; #endif /* ** Check if we should cache this object or not. We are very liberale ** in that we cache everything except if we explicit are told not to ** cache (no-store, no-cache). In all other cases we can get around ** it by forcing revalidation */ if (me->cache_control) { char * token; if ((token=HTAssocList_findObject(me->cache_control, "no-store"))) return HT_NO_CACHE; if ((token=HTAssocList_findObject(me->cache_control, "no-cache"))) if (!*token) return HT_NO_CACHE; } /* Cache everything else */ return me->cachable; } return HT_NO_CACHE; }
PUBLIC HTStream * HTBoundary (HTRequest * request, void * param, HTFormat input_format, HTFormat output_format, HTStream * output_stream) { HTResponse * response = HTRequest_response(request); HTParentAnchor * anchor = HTRequest_anchor(request); HTAssocList * type_param = response ? HTResponse_formatParam(response) : HTAnchor_formatParam(anchor); char * boundary = HTAssocList_findObject(type_param, "boundary"); if (boundary) { HTStream * me; if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL) HT_OUTOFMEM("HTBoundary"); me->isa = &HTBoundaryClass; me->request = request; me->format = output_format; me->orig_target = output_stream; me->debug = HTRequest_debugStream(request); me->state = EOL_FLF; StrAllocCopy(me->boundary, boundary); /* Local copy */ me->bpos = me->boundary; HTTRACE(STREAM_TRACE, "Boundary.... Stream created with boundary '%s\'\n" _ me->boundary); return me; } else { HTTRACE(STREAM_TRACE, "Boundary.... UNKNOWN boundary!\n"); return HTErrorStream(); } }
/* Content Base ** ------------ */ PUBLIC char * HTAnchor_base (HTParentAnchor * me) { if (me) { if (me->content_base) return me->content_base; if (me->headers) { char * base = HTAssocList_findObject(me->headers, "content-base"); /* ** If no base is found then take the content-location if this ** is present and is absolute, else use the Request-URI. */ if (base) StrAllocCopy(me->content_base, HTStrip(base)); } /* ** Try the content location if any */ { char * location = HTAnchor_location(me); StrAllocCopy(me->content_base, (location && HTURL_isAbsolute(location)) ? location : me->address); } return me->content_base; } return NULL; }
/* ** robots meta tag */ PUBLIC char * HTAnchor_robots (HTParentAnchor * me) { if (me && me->meta_tags) { char * robots = HTAssocList_findObject(me->meta_tags, "robots"); return robots; } return NULL; }
/* ** Level parameter to Content-Type */ PUBLIC HTLevel HTAnchor_level (HTParentAnchor * me) { if (me && me->type_parameters) { char * level = HTAssocList_findObject(me->type_parameters, "level"); return HTAtom_for(level); } return NULL; }
PUBLIC time_t HTResponse_maxAge (HTResponse * me) { if (me && me->cache_control) { char * token = HTAssocList_findObject(me->cache_control, "max-age"); if (token) return atol(token); } return (time_t) -1; }
/* ** Charset parameter to Content-Type */ PUBLIC HTCharset HTResponse_charset (HTResponse * me) { if (me && me->type_parameters) { char * charset = HTAssocList_findObject(me->type_parameters,"charset"); return HTAtom_for(charset); } return NULL; }
/* ** Take the relevant infomration from the response object and cache it ** in the anchor object. We inherit the information that is already ** parsed in the response along with the unparsed headers. */ PUBLIC BOOL HTAnchor_update (HTParentAnchor * me, HTResponse * response) { if (me && response) { HTCachable cachable = HTResponse_isCachable(response); if (cachable == HT_CACHE_ETAG) { char * etag = HTResponse_etag(response); HTTRACE(ANCH_TRACE, "HTAnchor.... Updating etag for %p\n" _ me); if (etag) { HTAnchor_setEtag(me, etag); return YES; } } else if (cachable == HT_CACHE_NOT_MODIFIED) { HTTRACE(ANCH_TRACE, "HTAnchor.... Information is up to date for %p\n" _ me); return YES; } else if (cachable == HT_CACHE_ALL) { char * etag = HTResponse_etag(response); HTTRACE(ANCH_TRACE, "HTAnchor.... Updating metainformation for %p\n" _ me); /* ** The content length and type is already parsed at this point ** in time. We also check for format parameters like charset etc. ** and copy the contents in the anchor object */ me->content_length = HTResponse_length(response); me->content_type = HTResponse_format(response); me->type_parameters = HTResponse_formatParam(response); me->content_encoding = HTResponse_encoding(response); /* Don't forget the etag as well */ if (etag) HTAnchor_setEtag(me, etag); /* ** Inherit all the unparsed headers - we may need them later! */ if (me->headers) HTAssocList_delete(me->headers); me->headers = HTResponse_handOverHeader(response); /* ** Notifify the response object not to delete the lists that we ** have inherited in the anchor object */ HTResponse_isCached(response, YES); /* ** Set the datestamp of when the anchor was updated if we didn't ** get any in the response */ if (!HTAssocList_findObject(me->headers, "date")) HTAnchor_setDate(me, time(NULL)); return YES; } } return NO; }
PUBLIC char * HTResponse_etag (HTResponse * me) { if (me && me->headers) { char * value = HTAssocList_findObject(me->headers, "etag"); char * etag = HTNextField(&value); return etag; } return NULL; }
/* ** Expires */ PUBLIC time_t HTAnchor_expires (HTParentAnchor * me) { if (me) { if (me->expires == (time_t) -1 && me->headers) { char * value = HTAssocList_findObject(me->headers, "expires"); if (value) me->expires = HTParseTime(value, NULL, YES); } return me->expires; } return (time_t) -1; }
/* ** Date */ PUBLIC time_t HTAnchor_date (HTParentAnchor * me) { if (me) { if (me->date == (time_t) -1 && me->headers) { char * value = HTAssocList_findObject(me->headers, "date"); if (value) me->date = HTParseTime(value, NULL, YES); } return me->date; } return (time_t) -1; }
/* ** Age */ PUBLIC time_t HTAnchor_age (HTParentAnchor * me) { if (me) { if (me->age == (time_t) -1 && me->headers) { char * value = HTAssocList_findObject(me->headers, "age"); if (value) me->age = atol(value); } return me->age; } return (time_t) -1; }
/* ** Last Modified */ PUBLIC time_t HTAnchor_lastModified (HTParentAnchor * me) { if (me) { if (me->last_modified == (time_t) -1 && me->headers) { char * value = HTAssocList_findObject(me->headers,"last-modified"); if (value) me->last_modified = HTParseTime(value, NULL, YES); } return me->last_modified; } return (time_t) -1; }
/* Content Location ** ---------------- */ PUBLIC char * HTAnchor_location (HTParentAnchor * me) { if (me) { if (me->content_location) return *me->content_location ? me->content_location : NULL; if (me->headers) { char * location = HTAssocList_findObject(me->headers, "content-location"); StrAllocCopy(me->content_location, location ? HTStrip(location) : ""); return me->content_location; } } return NULL; }
/* ** Title */ PUBLIC const char * HTAnchor_title (HTParentAnchor * me) { if (me) { if (me->title) return *me->title ? me->title : NULL; if (me->headers) { char * value = HTAssocList_findObject(me->headers, "title"); char * title; if ((title = HTNextField(&value))) StrAllocCopy(me->title, title); return me->title; } } return NULL; }
/* ** Content MD5 */ PUBLIC char * HTAnchor_md5 (HTParentAnchor * me) { if (me) { if (me->content_md5) return *me->content_md5 ? me->content_md5 : NULL; if (me->headers) { char * value = HTAssocList_findObject(me->headers, "content-md5"); char * md5; if ((md5 = HTNextField(&value))) StrAllocCopy(me->content_md5,md5); return me->content_md5; } } return NULL; }
/* ** Version */ PUBLIC char * HTAnchor_version (HTParentAnchor * me) { if (me) { if (me->version) return *me->version ? me->version : NULL; if (me->headers) { char * value = HTAssocList_findObject(me->headers, "version"); char * version; if ((version = HTNextField(&value))) StrAllocCopy(me->version, version); return me->version; } } return NULL; }
/* ** Derived from */ PUBLIC char * HTAnchor_derived (HTParentAnchor * me) { if (me) { if (me->derived_from) return *me->derived_from ? me->derived_from : NULL; if (me->headers) { char * value = HTAssocList_findObject(me->headers, "derived-from"); char * derived_from; if ((derived_from = HTNextField(&value))) StrAllocCopy(me->derived_from, derived_from); return me->derived_from; } } return NULL; }
/* ** Entity Tag */ PUBLIC char * HTAnchor_etag (HTParentAnchor * me) { if (me) { if (me->etag) return *me->etag ? me->etag : NULL; if (me->headers) { char * value = HTAssocList_findObject(me->headers, "etag"); char * etag; if ((etag = HTNextField(&value))) StrAllocCopy(me->etag, etag); return me->etag; } } return me ? me->etag : NULL; }
/* ** Content Language */ PUBLIC HTList * HTAnchor_language (HTParentAnchor * me) { if (me) { if (me->content_language == NULL && me->headers) { char * value = HTAssocList_findObject(me->headers, "content-language"); char * field; if (!me->content_language) me->content_language = HTList_new(); while ((field = HTNextField(&value)) != NULL) { char * lc = field; while ((*lc = TOLOWER(*lc))) lc++; HTList_addObject(me->content_language, HTAtom_for(field)); } } return me->content_language; } return NULL; }
/* ** Allowed methods (Allow) */ PUBLIC HTMethod HTAnchor_allow (HTParentAnchor * me) { if (me) { if (me->allow == 0 && me->headers) { char * value = HTAssocList_findObject(me->headers, "allow"); char * field; /* ** We treat methods allowed on this object as case insensitive ** in case we receive the information over the net - that is - ** in the Allow header. */ while ((field = HTNextField(&value)) != NULL) { HTMethod new_method; if ((new_method = HTMethod_enum(field)) != METHOD_INVALID) me->allow |= new_method; } } return me->allow; } return METHOD_INVALID; }
PUBLIC char * HTResponse_noCache (HTResponse * me) { return (me && me->cache_control) ? HTAssocList_findObject(me->cache_control, "no-cache") : NULL; }
PUBLIC BOOL HTResponse_mustRevalidate (HTResponse * me) { return me && me->cache_control && (HTAssocList_findObject(me->cache_control, "must-revalidate") != NULL); }