📄 htanchor.c
字号:
if (me->children) { int cnt = 0; for (; cnt<CHILD_HASH_SIZE; cnt++) { HTList * kids = me->children[cnt]; if (kids) { HTChildAnchor * child; while ((child = (HTChildAnchor *) HTList_nextObject(kids))) delete_links((HTAnchor *) child); return NO; /* Parent not deleted */ } } } /* ** No more incoming links : kill everything ** First, recursively delete children */ if (me->children) { int cnt = 0; for (; cnt<CHILD_HASH_SIZE; cnt++) { HTList * kids = me->children[cnt]; if (kids) { HTChildAnchor * child; while ((child=(HTChildAnchor *) HTList_removeLastObject(kids))) delete_links((HTAnchor *) child); HT_FREE(child->tag); HT_FREE(child); } } } } /* 2001/03/06: Bug fix by Serge Adda <sAdda@infovista.com> HTAnchor_delete wasn't removing the reference to the deleted anchor. This caused a bug whenever requesting another anchor for the same URL. */ if (adult_table) { int hash; const char *p; HTList * adults; HTList * grownups; HTList * last; HTParentAnchor * foundAnchor; /* Select list from hash table */ for(p=me->address, hash=0; *p; p++) hash = (int) ((hash * 3 + (*(unsigned char*)p)) % PARENT_HASH_SIZE); adults = adult_table[hash]; /* Search list for anchor */ grownups = adults; last = grownups; while ((foundAnchor = (HTParentAnchor *) HTList_nextObject(grownups))){ if (!strcmp(foundAnchor->address, me->address)) { HTList_quickRemoveElement (grownups, last); break; } last = grownups; } } /* Now kill myself */ delete_parent(me); return YES; /* Parent deleted */#if 0 if (! HTList_isEmpty (me->sources)) { /* There are still incoming links */ /* Delete all outgoing links from children, if any */ HTList *kids = me->children; while ((child = (HTChildAnchor *) HTList_nextObject (kids))) delete_links ((HTAnchor *) child); return NO; /* Parent not deleted */ } /* No more incoming links : kill everything */ /* First, recursively delete children */ while ((child = (HTChildAnchor *) HTList_removeLastObject (me->children))) { delete_links ((HTAnchor *) child); HT_FREE(child->tag); HT_FREE(child); }#endif}/* FLATTEN ALL ANCHORS** -------------------** Flattens the anchor web structure into an array.** This is useful for calculating statistics, sorting** the parent anchors etc.**** The caller can indicate the size of the array (total** number of anchors if known - otherwise 0).**** Return an array that must be freed by the caller or** NULL if no anchors.*/PUBLIC HTArray * HTAnchor_getArray (int growby){ int cnt; HTArray * array = NULL; HTList * cur = NULL; if (!adult_table) return NULL; /* Allocate an array for the anchors */ if (growby <= 0) growby = PARENT_HASH_SIZE; array = HTArray_new(growby); /* Traverse anchor structure */ for (cnt=0; cnt<PARENT_HASH_SIZE; cnt++) { if ((cur = adult_table[cnt])) { HTParentAnchor * pres = NULL; while ((pres = (HTParentAnchor *) HTList_nextObject(cur)) != NULL) { if (HTArray_addObject(array, pres) == NO) { HTTRACE(ANCH_TRACE, "Anchor...... Can't add object %p to array %p\n" _ pres _ array); break; } } } } return array;}/* ------------------------------------------------------------------------- *//* Data Access Methods *//* ------------------------------------------------------------------------- */PUBLIC HTParentAnchor * HTAnchor_parent (HTAnchor * me){ return me ? me->parent : NULL;}PUBLIC void HTAnchor_setDocument (HTParentAnchor * me, void * doc){ if (me) me->document = doc;}PUBLIC void * HTAnchor_document (HTParentAnchor * me){ return me ? me->document : NULL;}PUBLIC char * HTAnchor_address (HTAnchor * me) { char *addr = NULL; if (me) { if (((HTParentAnchor *) me == me->parent) || !((HTChildAnchor *) me)->tag) { /* it's an adult or no tag */ StrAllocCopy (addr, me->parent->address); } else { /* it's a named child */ if ((addr = (char *) HT_MALLOC(2 + strlen (me->parent->address) + \strlen (((HTChildAnchor *) me)->tag))) == NULL) HT_OUTOFMEM("HTAnchor_address"); sprintf (addr, "%s#%s", me->parent->address, ((HTChildAnchor *) me)->tag); } } return addr;}/*** We resolve the child address with respect to either a base URL,** a content-location, or to the request-URI*/PUBLIC char * HTAnchor_expandedAddress (HTAnchor * me){ char *addr = NULL; if (me) { HTParentAnchor * parent = me->parent; char * base = HTAnchor_base(parent); if (((HTParentAnchor *) me == me->parent) || !((HTChildAnchor *) me)->tag) { /* it's an adult or no tag */ StrAllocCopy(addr, base); } else { /* it's a named child */ if ((addr = (char *) HT_MALLOC(2 + strlen(base) + strlen(((HTChildAnchor *) me)->tag))) == NULL) HT_OUTOFMEM("HTAnchor_address"); sprintf (addr, "%s#%s", base, ((HTChildAnchor *) me)->tag); } } return addr;}/* Physical Address** ----------------*/PUBLIC char * HTAnchor_physical (HTParentAnchor * me){ return me ? me->physical ? me->physical : me->address : NULL;}PUBLIC void HTAnchor_setPhysical (HTParentAnchor * me, char * physical){ if (!me || !physical) { HTTRACE(ANCH_TRACE, "HTAnchor.... setPhysical, called with null argument\n"); return; } StrAllocCopy(me->physical, physical);}PUBLIC void HTAnchor_clearPhysical(HTParentAnchor * me){ if (me) HT_FREE(me->physical);}/*** Children information*/PUBLIC BOOL HTAnchor_hasChildren (HTParentAnchor * me){ return (me && me->children);}/*** Fix up a simple routine to see if this anchor is a (ChildAnchor *)** Seem to be doing it all over the place, so simplify!*/PUBLIC BOOL HTAnchor_isChild (HTAnchor * me){ return (me && (HTParentAnchor *) me != me->parent);}PUBLIC char * HTAnchor_view (HTAnchor * me){ char * view = NULL; if (me && (HTParentAnchor *) me != me->parent && ((HTChildAnchor *) me)->tag) StrAllocCopy(view, ((HTChildAnchor *) me)->tag); return view;}/* ------------------------------------------------------------------------- *//* Entity Header Information *//* ------------------------------------------------------------------------- *//*** 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;}/*** Variants. If this anchor has any variants then keep them in a list** so that we can find them later. The list is simply a list of ** parent anchors.*/PUBLIC HTList * HTAnchor_variants (HTParentAnchor * me){ return me ? me->variants : NULL;}PUBLIC BOOL HTAnchor_addVariant (HTParentAnchor * me, HTParentAnchor * variant){ if (me && variant) { if (!me->variants) me->variants = HTList_new(); return HTList_addObject(me->variants, variant); } return NO;}PUBLIC BOOL HTAnchor_deleteVariant (HTParentAnchor * me, HTParentAnchor * variant){ return (me && variant) ? HTList_removeObject(me->variants, variant) : NO;}/*** Is this resource an index?*/PUBLIC void HTAnchor_clearIndex (HTParentAnchor * me){ if (me) me->isIndex = NO;}PUBLIC void HTAnchor_setIndex (HTParentAnchor * me){ if (me) me->isIndex = YES;}PUBLIC BOOL HTAnchor_isIndex (HTParentAnchor * me){ return me ? me->isIndex : NO;}/* 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;}PUBLIC BOOL HTAnchor_setBase (HTParentAnchor * me, char * base){ if (me && base) { StrAllocCopy(me->content_base, base); return YES; } return NO;}/* 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;}/*** Expand the location relative to the base URL if any, otherwise the ** anchor address it self*/PUBLIC BOOL HTAnchor_setLocation (HTParentAnchor * me, char * location){ if (me && location) { char * base = HTAnchor_base(me); if (!base) base = me->address; me->content_location = HTParse(location, base, PARSE_ALL); return YES; } return NO;}/* Meta tags** ---------*/PUBLIC HTAssocList * HTAnchor_meta (HTParentAnchor * me){ return me ? me->meta_tags : NULL;}PUBLIC BOOL HTAnchor_addMeta (HTParentAnchor * me, const char * name, const char * value){ if (me) { if (!me->meta_tags) me->meta_tags = HTAssocList_new(); return HTAssocList_replaceObject(me->meta_tags, name, value); } return NO;}/*** 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;}/* Content-Type** ------------*/PUBLIC HTFormat HTAnchor_format (HTParentAnchor * me){ return me ? me->content_type : NULL;}PUBLIC void HTAnchor_setFormat (HTParentAnchor * me, HTFormat form){ if (me) me->content_type = form;}PUBLIC HTAssocList * HTAnchor_formatParam (HTParentAnchor * me){ return me ? me->type_parameters : NULL;}PUBLIC BOOL HTAnchor_addFormatParam (HTParentAnchor * me, const char * name, const char * value){ if (me) { if (!me->type_parameters) me->type_parameters = HTAssocList_new(); return HTAssocList_replaceObject(me->type_parameters, name, value); } return NO;}/*** Charset parameter to Content-Type*/PUBLIC HTCharset HTAnchor_charset (HTParentAnchor * me){ if (me && me->type_parameters) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -