Annotation of libwww/Library/src/HTAnchor.c, revision 1.27
1.14 frystyk 1: /* HTAnchor.c
2: ** HYPERTEXT "ANCHOR" OBJECT
1.1 timbl 3: **
1.22 frystyk 4: ** (c) COPYRIGHT MIT 1995.
1.14 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
6: **
7: ** An anchor represents a region of a hypertext document which is
8: ** linked to another anchor in the same or a different document.
1.1 timbl 9: **
10: ** History
11: ** Nov 1990 Written in Objective-C for the NeXT browser (TBL)
12: ** 24-Oct-1991 (JFG), written in C, browser-independant
13: ** 21-Nov-1991 (JFG), first complete version
1.17 frystyk 14: ** 3-May-1995 (HF), Added a lot of methods and other stuff
1.1 timbl 15: */
16:
1.16 frystyk 17: /* Library include files */
18: #include "tcp.h"
19: #include "HTUtils.h"
20: #include "HTString.h"
1.7 luotonen 21: #include "HTFormat.h"
1.1 timbl 22: #include "HTParse.h"
1.24 frystyk 23: #include "HTMethod.h"
1.16 frystyk 24: #include "HTFWrite.h" /* for cache stuff */
1.11 frystyk 25: #include "HTAnchor.h" /* Implemented here */
26:
27: #define HASH_SIZE 101 /* Arbitrary prime. Memory/speed tradeoff */
1.1 timbl 28:
29: typedef struct _HyperDoc Hyperdoc;
1.16 frystyk 30: #ifdef VMS
1.1 timbl 31: struct _HyperDoc {
1.16 frystyk 32: int junk; /* VMS cannot handle pointers to undefined structs */
1.1 timbl 33: };
34: #endif
35:
36: PRIVATE HTList **adult_table=0; /* Point to table of lists of all parents */
37:
1.17 frystyk 38: /* ------------------------------------------------------------------------- */
39: /* Creation Methods */
40: /* ------------------------------------------------------------------------- */
41:
42: /*
1.1 timbl 43: ** Do not use "new" by itself outside this module. In order to enforce
44: ** consistency, we insist that you furnish more information about the
45: ** anchor you are creating : use newWithParent or newWithAddress.
46: */
1.16 frystyk 47: PRIVATE HTParentAnchor * HTParentAnchor_new NOARGS
1.1 timbl 48: {
1.16 frystyk 49: HTParentAnchor *newAnchor =
50: (HTParentAnchor *) calloc(1, sizeof (HTParentAnchor));
51: newAnchor->parent = newAnchor;
1.17 frystyk 52: newAnchor->content_type = WWW_UNKNOWN;
1.24 frystyk 53: newAnchor->mainLink.method = METHOD_INVALID;
1.16 frystyk 54: return newAnchor;
1.1 timbl 55: }
56:
1.16 frystyk 57:
58: PRIVATE HTChildAnchor * HTChildAnchor_new NOARGS
1.1 timbl 59: {
1.16 frystyk 60: return (HTChildAnchor *) calloc (1, sizeof (HTChildAnchor));
1.1 timbl 61: }
62:
63:
1.17 frystyk 64: /* Create new or find old child anchor
65: ** -----------------------------------
1.1 timbl 66: **
1.3 timbl 67: ** Me one is for a new anchor being edited into an existing
1.17 frystyk 68: ** document. The parent anchor must already exist. All
69: ** children without tags (no NAME attribut) points to the same NULL
70: ** child.
1.1 timbl 71: */
1.17 frystyk 72: PUBLIC HTChildAnchor * HTAnchor_findChild ARGS2 (HTParentAnchor *, parent,
73: CONST char *,tag)
1.1 timbl 74: {
1.17 frystyk 75: HTChildAnchor *child;
76: HTList *kids;
77:
78: if (!parent) {
79: if (ANCH_TRACE)
80: fprintf(TDEST, "Find Child.. called with NULL parent.\n");
81: return NULL;
82: }
1.1 timbl 83:
1.17 frystyk 84: /* First search list of children to see if tag is already there */
85: if ((kids = parent->children)) {
86: if (tag && *tag) { /* TBL */
87: while ((child = (HTChildAnchor *) HTList_nextObject(kids))) {
1.19 frystyk 88: if (child->tag && !strcasecomp(child->tag, tag)) {
1.17 frystyk 89: if (ANCH_TRACE)
90: fprintf (TDEST,
91: "Find Child.. %p of parent %p with name `%s' already exists.\n",
92: (void *) child, (void *) parent, tag);
93: return child;
94: }
1.1 timbl 95: }
96: }
1.17 frystyk 97: } else /* Create new list of children */
98: parent->children = HTList_new ();
99:
100: /* Did't find it so we need to create a new one */
101: child = HTChildAnchor_new();
102: HTList_addObject(parent->children, child);
103: child->parent = parent;
104: StrAllocCopy(child->tag, tag);
105: if (ANCH_TRACE)
106: fprintf(TDEST,"Find Child.. New Anchor %p named `%s' is child of %p\n",
107: (void *) child, tag ? tag : (CONST char *) "", (void *)parent);
108: return child;
1.1 timbl 109: }
110:
111:
112: /* Create new or find old named anchor
113: ** -----------------------------------
114: **
1.3 timbl 115: ** Me one is for a reference which is found in a document, and might
1.1 timbl 116: ** not be already loaded.
117: ** Note: You are not guaranteed a new anchor -- you might get an old one,
118: ** like with fonts.
119: */
1.16 frystyk 120: PUBLIC HTAnchor * HTAnchor_findAddress ARGS1 (CONST char *, address)
1.1 timbl 121: {
1.16 frystyk 122: char *tag = HTParse (address, "", PARSE_ANCHOR); /* Any tags? */
123: char *newaddr=NULL;
1.1 timbl 124:
1.17 frystyk 125: StrAllocCopy(newaddr, address); /* Get our own copy */
1.16 frystyk 126: if (!HTImProxy)
1.19 frystyk 127: newaddr = HTSimplify(&newaddr); /* Proxy has already simplified */
1.16 frystyk 128:
129: /* If the address represents a sub-anchor, we recursively load its parent,
130: then we create a child anchor within that document. */
131: if (*tag) {
132: char *docAddress = HTParse(newaddr, "", PARSE_ACCESS | PARSE_HOST |
133: PARSE_PATH | PARSE_PUNCTUATION);
134: HTParentAnchor * foundParent =
135: (HTParentAnchor *) HTAnchor_findAddress (docAddress);
136: HTChildAnchor * foundAnchor = HTAnchor_findChild (foundParent, tag);
137: free (docAddress);
138: free (tag);
1.19 frystyk 139: free (newaddr);
1.16 frystyk 140: return (HTAnchor *) foundAnchor;
141: } else { /* Else check whether we have this node */
142: int hash;
143: CONST char *p;
144: HTList * adults;
145: HTList *grownups;
146: HTParentAnchor * foundAnchor;
147: free (tag);
148:
149: /* Select list from hash table */
150: for(p=newaddr, hash=0; *p; p++)
151: hash = (int) ((hash * 3 + (*(unsigned char*)p)) % HASH_SIZE);
152: if (!adult_table)
153: adult_table = (HTList**) calloc(HASH_SIZE, sizeof(HTList*));
154: if (!adult_table[hash]) adult_table[hash] = HTList_new();
155: adults = adult_table[hash];
156:
157: /* Search list for anchor */
158: grownups = adults;
159: while ((foundAnchor = (HTParentAnchor *) HTList_nextObject(grownups))){
1.17 frystyk 160: if (!strcasecomp(foundAnchor->address, newaddr)) {
1.16 frystyk 161: if (ANCH_TRACE)
1.17 frystyk 162: fprintf(TDEST, "Find Parent. %p with address `%s' already exists.\n",
1.16 frystyk 163: (void*) foundAnchor, newaddr);
1.19 frystyk 164: free(newaddr); /* We already have it */
1.16 frystyk 165: return (HTAnchor *) foundAnchor;
166: }
167: }
168:
169: /* Node not found : create new anchor. */
170: foundAnchor = HTParentAnchor_new();
171: foundAnchor->address = newaddr; /* Remember our copy */
172: HTList_addObject (adults, foundAnchor);
1.17 frystyk 173: if (ANCH_TRACE) fprintf(TDEST, "Find Parent. %p with hash %d and address `%s' created\n", (void*)foundAnchor, hash, newaddr);
1.1 timbl 174: return (HTAnchor *) foundAnchor;
175: }
176: }
177:
1.17 frystyk 178: /* ------------------------------------------------------------------------- */
179: /* Link Methods */
180: /* ------------------------------------------------------------------------- */
181:
182: /* Create or find a child anchor with a possible link
183: ** --------------------------------------------------
184: **
185: ** Create new anchor with a given parent and possibly
186: ** a name, and possibly a link to a _relatively_ named anchor.
187: ** (Code originally in ParseHTML.h)
188: */
189: PUBLIC HTChildAnchor * HTAnchor_findChildAndLink
190: ARGS4(
191: HTParentAnchor *,parent, /* May not be 0 */
192: CONST char *,tag, /* May be "" or 0 */
193: CONST char *,href, /* May be "" or 0 */
194: HTLinkType *,ltype /* May be 0 */
195: )
196: {
197: HTChildAnchor * child = HTAnchor_findChild(parent, tag);
198: if (href && *href) {
199: char * relative_to = HTAnchor_address((HTAnchor *) parent);
200: char * parsed_address = HTParse(href, relative_to, PARSE_ALL);
201: HTAnchor * dest = HTAnchor_findAddress(parsed_address);
1.24 frystyk 202: HTAnchor_link((HTAnchor *) child, dest, ltype, METHOD_INVALID);
1.17 frystyk 203: free(parsed_address);
204: free(relative_to);
205: }
206: return child;
207: }
208:
209: /* Link me Anchor to another given one
210: ** -------------------------------------
211: */
1.24 frystyk 212: PUBLIC BOOL HTAnchor_link ARGS4(HTAnchor *, source,
213: HTAnchor *, destination,
214: HTLinkType *, type,
215: HTMethod, method)
1.17 frystyk 216: {
217: if (!(source && destination))
218: return NO; /* Can't link to/from non-existing anchor */
219: if (ANCH_TRACE)
220: fprintf(TDEST, "Link Anchors anchor %p to anchor %p\n",
221: (void *) source, (void *) destination);
222: if (!source->mainLink.dest) {
223: source->mainLink.dest = destination;
224: source->mainLink.type = type;
1.24 frystyk 225: source->mainLink.method = method;
1.17 frystyk 226: } else {
227: HTLink * newLink = (HTLink *) calloc(1, sizeof (HTLink));
228: if (newLink == NULL) outofmem(__FILE__, "HTAnchor_link");
229: newLink->dest = destination;
230: newLink->type = type;
1.24 frystyk 231: newLink->method = method;
232: if (!source->links)
233: source->links = HTList_new();
1.17 frystyk 234: HTList_addObject (source->links, newLink);
235: }
236: if (!destination->parent->sources)
237: destination->parent->sources = HTList_new ();
238: HTList_addObject (destination->parent->sources, source);
239: return YES;
240: }
241:
242:
1.24 frystyk 243: /*
244: ** Returns the main destination of this anchor
245: */
246: PUBLIC HTAnchor * HTAnchor_followMainLink ARGS1(HTAnchor *, me)
247: {
248: return me ? me->mainLink.dest : NULL;
249: }
250:
251:
252: /*
253: ** Returns the methods registered for the main destination of this
254: ** anchor
1.17 frystyk 255: */
1.24 frystyk 256: PUBLIC HTMethod HTAnchor_mainLinkMethod ARGS1(HTAnchor *, me)
257: {
258: return me ? me->mainLink.method : METHOD_INVALID;
259: }
260:
1.17 frystyk 261:
1.24 frystyk 262: /*
263: ** Moves all link information from one anchor to another.
264: ** This is used in redirection etc.
265: ** Returns YES if OK, else NO
266: */
267: PUBLIC BOOL HTAnchor_moveLinks ARGS2(HTAnchor *, src, HTAnchor *, dest)
1.17 frystyk 268: {
1.24 frystyk 269: if (!src || !dest) return NO;
270: if (ANCH_TRACE)
271: fprintf(TDEST, "Move Links.. from anchor %p to anchor %p\n",
272: (void *) src, (void *) dest);
273:
274: /* Move main link information */
275: dest->mainLink.dest = src->mainLink.dest;
276: dest->mainLink.type = src->mainLink.type;
277: dest->mainLink.method = src->mainLink.method;
1.25 frystyk 278: dest->mainLink.result = src->mainLink.result;
1.24 frystyk 279:
280: src->mainLink.dest = NULL;
281: src->mainLink.type = NULL;
1.25 frystyk 282: src->mainLink.method = METHOD_INVALID;
283: src->mainLink.result = HT_OK;
1.24 frystyk 284:
285: /* Move link information for other links */
1.26 frystyk 286: if (dest->links) {
287: HTList *cur = dest->links;
288: HTLink *pres;
289: while ((pres = (HTLink *) HTList_nextObject(cur)))
290: free(pres);
1.24 frystyk 291: HTList_delete(dest->links);
1.26 frystyk 292: }
1.24 frystyk 293: dest->links = src->links;
294: src->links = NULL;
295: return YES;
1.17 frystyk 296: }
297:
1.24 frystyk 298:
299: /*
300: ** Returns a link with a given link type or NULL if nothing found
301: */
302: PUBLIC HTAnchor * HTAnchor_followTypedLink ARGS2(HTAnchor *, me,
303: HTLinkType *,type)
1.17 frystyk 304: {
1.24 frystyk 305: if (me->mainLink.type == type)
306: return me->mainLink.dest;
307: if (me->links) {
308: HTList *links = me->links;
309: HTLink *link;
310: while ((link = (HTLink *) HTList_nextObject (links)))
311: if (link->type == type)
312: return link->dest;
313: }
314: return NULL; /* No link of me type */
1.17 frystyk 315: }
316:
317:
1.24 frystyk 318: /*
319: ** Is this anchor a destination link of the source anchor?
320: ** Return YES if so, else NO
1.17 frystyk 321: */
1.24 frystyk 322: PUBLIC BOOL HTAnchor_isLink ARGS2(HTAnchor *, src, HTAnchor *, dest)
1.17 frystyk 323: {
1.24 frystyk 324: if (src && dest) {
325: if (src->mainLink.dest == dest)
326: return YES;
327: if (src->links) {
328: HTList *cur = src->links;
329: HTLink *pres;
330: while ((pres = (HTLink *) HTList_nextObject(cur)) != NULL) {
331: if (pres->dest == dest)
332: return YES;
333: }
334: }
335: }
336: return NO;
337: }
338:
1.17 frystyk 339:
1.24 frystyk 340: /*
341: ** Upgrade the link to the main destination and and downgrade the
342: ** current main link to the list
343: */
344: PUBLIC BOOL HTAnchor_makeMainLink ARGS2 (HTAnchor *, me, HTLink *, movingLink)
345: {
346: if (! (me && HTList_removeObject (me->links, movingLink)))
347: return NO;
348: else {
349: /* First push current main link onto top of links list */
350: HTLink *newLink = (HTLink*) malloc (sizeof (HTLink));
351: if (newLink == NULL) outofmem(__FILE__, "HTAnchor_makeMainLink");
352: memcpy (newLink, & me->mainLink, sizeof (HTLink));
353: HTList_addObject (me->links, newLink);
354:
355: /* Now make movingLink the new main link, and free it */
356: memcpy (& me->mainLink, movingLink, sizeof (HTLink));
357: free (movingLink);
358: return YES;
359: }
1.17 frystyk 360: }
361:
362: /* Move an anchor to the head of the list of its siblings
363: ** ------------------------------------------------------
364: **
365: ** This is to ensure that an anchor which might have already existed
366: ** is put in the correct order as we load the document.
367: */
368:
369: PUBLIC void HTAnchor_makeLastChild
370: ARGS1(HTChildAnchor *,me)
371: {
372: if (me->parent != (HTParentAnchor *) me) { /* Make sure it's a child */
373: HTList * siblings = me->parent->children;
374: HTList_removeObject (siblings, me);
375: HTList_addObject (siblings, me);
376: }
377: }
378:
379: /* ------------------------------------------------------------------------- */
380: /* Deletion Methods */
381: /* ------------------------------------------------------------------------- */
1.1 timbl 382:
383: /* Delete an anchor and possibly related things (auto garbage collection)
384: ** --------------------------------------------
385: **
386: ** The anchor is only deleted if the corresponding document is not loaded.
1.10 frystyk 387: ** All outgoing links from parent and children are deleted, and this
388: ** anchor is removed from the sources list of all its targets.
1.1 timbl 389: ** We also try to delete the targets whose documents are not loaded.
390: ** If this anchor's source list is empty, we delete it and its children.
391: */
392:
1.19 frystyk 393: /* Deletes all the memory allocated in a parent anchor and returns the
394: ** hyperdoc
395: */
396: PRIVATE HyperDoc * delete_parent ARGS1(HTParentAnchor *, me)
397: {
398: HyperDoc *doc = me->document;
399:
400: /* Remove link and address information */
1.26 frystyk 401: if (me->links) {
402: HTList *cur = me->links;
403: HTLink *pres;
404: while ((pres = (HTLink *) HTList_nextObject(cur)))
405: free(pres);
406: HTList_delete(me->links);
407: }
1.19 frystyk 408: HTList_delete (me->children);
409: HTList_delete (me->sources);
410: FREE(me->physical);
411: FREE(me->address);
412:
413: /* Then remove entity header information (metainformation) */
414: FREE(me->title);
415: FREE(me->derived_from);
416: FREE(me->version);
417: if (me->extra_headers) {
418: HTList *cur = me->extra_headers;
419: char *pres;
420: while ((pres = (char *) HTList_nextObject(cur)))
421: free(pres);
422: HTList_delete(me->extra_headers);
423: }
424: free(me);
425: return doc;
426: }
427:
428:
429: /* Delete a parent anchor and all its children. If a HyperDoc is found
430: ** then it's returned
431: */
432: PRIVATE HyperDoc *delete_family ARGS1(HTAnchor *, me)
433: {
434: HTParentAnchor *parent = me->parent;
435: if (ANCH_TRACE)
436: fprintf(TDEST, "AnchorDelete Remove parent %p and children\n", parent);
437: if (!me) {
438: if (ANCH_TRACE)
439: fprintf(TDEST, "AnchorDelete No anchor found\n");
440: return NULL;
441: }
442:
443: /* Delete children */
444: if (parent->children) {
445: HTChildAnchor *child;
446: while ((child = (HTChildAnchor *)
447: HTList_removeLastObject(parent->children))) {
448: FREE(child->tag);
1.26 frystyk 449: if (child->links) {
450: HTList *cur = child->links;
451: HTLink *pres;
452: while ((pres = (HTLink *) HTList_nextObject(cur)))
453: free(pres);
454: HTList_delete(child->links);
455: }
1.19 frystyk 456: free(child);
457: }
458: }
459: return delete_parent(parent);
460: }
461:
462:
463: /* DELETE ALL ANCHORS
464: ** ------------------
465: ** Deletes all anchors and return a list of all the HyperDocs found.
466: ** It is for the application to delete any HyperDocs.
467: ** Return YES if OK, else NO
468: */
469: PUBLIC BOOL HTAnchor_deleteAll ARGS1(HTList *, documents)
470: {
471: int cnt;
472: HTList *cur;
473: if (!documents)
474: return NO;
475: for (cnt=0; cnt<HASH_SIZE; cnt++) {
476: if ((cur = adult_table[cnt])) {
477: HTParentAnchor *pres;
478: while ((pres = (HTParentAnchor *) HTList_nextObject(cur)) != NULL){
479: HyperDoc *doc = delete_family((HTAnchor *) pres);
480: if (doc) HTList_addObject(documents, (void *) doc);
481: }
482: }
483: HTList_delete(adult_table[cnt]);
484: }
1.21 frystyk 485: FREE(adult_table);
1.19 frystyk 486: return YES;
487: }
488:
489:
1.1 timbl 490: PRIVATE void deleteLinks
1.3 timbl 491: ARGS1 (HTAnchor *,me)
1.1 timbl 492: {
1.3 timbl 493: if (! me)
1.1 timbl 494: return;
495:
496: /* Recursively try to delete target anchors */
1.3 timbl 497: if (me->mainLink.dest) {
498: HTParentAnchor *parent = me->mainLink.dest->parent;
499: HTList_removeObject (parent->sources, me);
1.1 timbl 500: if (! parent->document) /* Test here to avoid calling overhead */
501: HTAnchor_delete (parent);
502: }
1.3 timbl 503: if (me->links) { /* Extra destinations */
1.1 timbl 504: HTLink *target;
1.12 frystyk 505: while ((target = (HTLink *) HTList_removeLastObject (me->links))) {
1.1 timbl 506: HTParentAnchor *parent = target->dest->parent;
1.3 timbl 507: HTList_removeObject (parent->sources, me);
1.1 timbl 508: if (! parent->document) /* Test here to avoid calling overhead */
509: HTAnchor_delete (parent);
510: }
511: }
512: }
513:
514: PUBLIC BOOL HTAnchor_delete
1.3 timbl 515: ARGS1 (HTParentAnchor *,me)
1.1 timbl 516: {
517: HTChildAnchor *child;
518:
519: /* Don't delete if document is loaded */
1.3 timbl 520: if (me->document)
1.1 timbl 521: return NO;
522:
523: /* Recursively try to delete target anchors */
1.3 timbl 524: deleteLinks ((HTAnchor *) me);
1.1 timbl 525:
1.3 timbl 526: if (! HTList_isEmpty (me->sources)) { /* There are still incoming links */
1.1 timbl 527: /* Delete all outgoing links from children, if any */
1.3 timbl 528: HTList *kids = me->children;
1.12 frystyk 529: while ((child = (HTChildAnchor *) HTList_nextObject (kids)))
1.1 timbl 530: deleteLinks ((HTAnchor *) child);
531: return NO; /* Parent not deleted */
532: }
533:
534: /* No more incoming links : kill everything */
535: /* First, recursively delete children */
1.12 frystyk 536: while ((child = (HTChildAnchor *) HTList_removeLastObject (me->children))) {
1.1 timbl 537: deleteLinks ((HTAnchor *) child);
538: free (child->tag);
539: free (child);
540: }
541:
542: /* Now kill myself */
1.19 frystyk 543: delete_parent(me);
1.1 timbl 544: return YES; /* Parent deleted */
545: }
546:
1.17 frystyk 547: /* ------------------------------------------------------------------------- */
548: /* Data Access Methods */
549: /* ------------------------------------------------------------------------- */
1.1 timbl 550:
1.17 frystyk 551: PUBLIC HTParentAnchor * HTAnchor_parent ARGS1 (HTAnchor *,me)
1.1 timbl 552: {
1.17 frystyk 553: return me ? me->parent : NULL;
1.1 timbl 554: }
555:
1.17 frystyk 556: PUBLIC void HTAnchor_setDocument ARGS2 (HTParentAnchor *, me, HyperDoc *,doc)
1.1 timbl 557: {
1.17 frystyk 558: if (me)
559: me->document = doc;
1.1 timbl 560: }
561:
1.17 frystyk 562: PUBLIC HyperDoc * HTAnchor_document ARGS1 (HTParentAnchor *,me)
1.1 timbl 563: {
1.17 frystyk 564: return me ? me->document : NULL;
1.1 timbl 565: }
566:
567:
1.10 frystyk 568: #if 0
1.17 frystyk 569: /* We might want to use this when we have a link editing application */
1.10 frystyk 570: PUBLIC void HTAnchor_setAddress
1.3 timbl 571: ARGS2 (HTAnchor *,me, char *,addr)
1.1 timbl 572: {
1.3 timbl 573: if (me)
574: StrAllocCopy (me->parent->address, addr);
1.1 timbl 575: }
1.10 frystyk 576: #endif
577:
1.17 frystyk 578: PUBLIC char * HTAnchor_address ARGS1 (HTAnchor *, me)
1.1 timbl 579: {
1.17 frystyk 580: char *addr = NULL;
581: if (me) {
582: if (((HTParentAnchor *) me == me->parent) ||
583: !((HTChildAnchor *) me)->tag) { /* it's an adult or no tag */
584: StrAllocCopy (addr, me->parent->address);
585: }
586: else { /* it's a named child */
587: addr = (char *) malloc (2 + strlen (me->parent->address)
588: + strlen (((HTChildAnchor *) me)->tag));
589: if (addr == NULL) outofmem(__FILE__, "HTAnchor_address");
590: sprintf (addr, "%s#%s", me->parent->address,
591: ((HTChildAnchor *) me)->tag);
592: }
1.1 timbl 593: }
1.17 frystyk 594: return addr;
1.1 timbl 595: }
596:
1.17 frystyk 597: PUBLIC BOOL HTAnchor_hasChildren ARGS1 (HTParentAnchor *,me)
598: {
599: return me ? ! HTList_isEmpty(me->children) : NO;
600: }
1.1 timbl 601:
1.17 frystyk 602: PUBLIC void HTAnchor_clearIndex ARGS1 (HTParentAnchor *,me)
603: {
604: if (me)
605: me->isIndex = NO;
606: }
1.1 timbl 607:
1.17 frystyk 608: PUBLIC void HTAnchor_setIndex ARGS1 (HTParentAnchor *,me)
1.1 timbl 609: {
1.3 timbl 610: if (me)
1.17 frystyk 611: me->isIndex = YES;
612: }
613:
614: PUBLIC BOOL HTAnchor_isIndex ARGS1 (HTParentAnchor *,me)
615: {
616: return me ? me->isIndex : NO;
1.1 timbl 617: }
618:
1.17 frystyk 619: /* Protocol
620: ** --------
621: */
622:
623: PUBLIC void * HTAnchor_protocol ARGS1(HTParentAnchor *, me)
1.1 timbl 624: {
1.17 frystyk 625: return me->protocol;
1.1 timbl 626: }
627:
1.17 frystyk 628: PUBLIC void HTAnchor_setProtocol ARGS2(HTParentAnchor *, me,
629: void*, protocol)
1.9 frystyk 630: {
1.17 frystyk 631: me->protocol = protocol;
1.9 frystyk 632: }
1.1 timbl 633:
1.17 frystyk 634: /* Physical Address
635: ** ----------------
636: */
637:
638: PUBLIC char * HTAnchor_physical ARGS1(HTParentAnchor *, me)
1.1 timbl 639: {
1.17 frystyk 640: return me->physical;
1.1 timbl 641: }
642:
1.17 frystyk 643: PUBLIC void HTAnchor_setPhysical ARGS2(HTParentAnchor *, me,
644: char *, physical)
1.1 timbl 645: {
1.17 frystyk 646: if (!me || !physical) {
647: if (ANCH_TRACE)
648: fprintf(TDEST, "HTAnchor.... setPhysical, called with null argument\n");
649: return;
650: }
651: StrAllocCopy(me->physical, physical);
1.27 ! frystyk 652: }
! 653:
! 654: /* Cache Information
! 655: ** -----------------
! 656: */
! 657: PUBLIC BOOL HTAnchor_cacheHit ARGS1(HTParentAnchor *, me)
! 658: {
! 659: return me->cacheHit;
! 660: }
! 661:
! 662: PUBLIC void HTAnchor_setCacheHit ARGS2(HTParentAnchor *, me, BOOL, cacheHit)
! 663: {
! 664: me->cacheHit = cacheHit;
1.1 timbl 665: }
666:
1.17 frystyk 667: /* ------------------------------------------------------------------------- */
668: /* Entity Header Information */
669: /* ------------------------------------------------------------------------- */
670:
671: /*
672: ** Media Types (Content-Type)
673: */
674: PUBLIC HTFormat HTAnchor_format ARGS1(HTParentAnchor *,me)
675: {
676: return me ? me->content_type : NULL;
677: }
1.1 timbl 678:
1.17 frystyk 679: PUBLIC void HTAnchor_setFormat ARGS2(HTParentAnchor *,me, HTFormat, form)
1.1 timbl 680: {
1.17 frystyk 681: if (me) me->content_type = form;
1.1 timbl 682: }
683:
1.17 frystyk 684: /*
685: ** Charset parameter to Content-Type
1.1 timbl 686: */
1.17 frystyk 687: PUBLIC HTCharset HTAnchor_charset ARGS1(HTParentAnchor *, me)
1.1 timbl 688: {
1.17 frystyk 689: return me ? me->charset : NULL;
1.1 timbl 690: }
691:
1.17 frystyk 692: PUBLIC void HTAnchor_setCharset ARGS2(HTParentAnchor *,me, HTCharset, charset)
1.1 timbl 693: {
1.17 frystyk 694: if (me) me->charset = charset;
1.1 timbl 695: }
696:
1.17 frystyk 697: /*
1.20 frystyk 698: ** Level parameter to Content-Type
699: */
700: PUBLIC HTLevel HTAnchor_level ARGS1(HTParentAnchor *, me)
701: {
702: return me ? me->level : NULL;
703: }
704:
705: PUBLIC void HTAnchor_setLevel ARGS2(HTParentAnchor *,me, HTLevel, level)
706: {
707: if (me) me->level = level;
708: }
709:
710: /*
1.17 frystyk 711: ** Content Encoding
712: */
713: PUBLIC HTEncoding HTAnchor_encoding ARGS1(HTParentAnchor *,me)
1.1 timbl 714: {
1.17 frystyk 715: return me ? me->content_encoding : NULL;
1.1 timbl 716: }
717:
1.17 frystyk 718: PUBLIC void HTAnchor_setEncoding ARGS2(HTParentAnchor *,me,
719: HTEncoding, encoding)
720: {
721: if (me) me->content_encoding = encoding;
722: }
723:
724: /*
1.21 frystyk 725: ** Content Language
726: ** @@@ SHOULD BE A LIST @@@
727: */
728: PUBLIC HTLanguage HTAnchor_language ARGS1(HTParentAnchor *,me)
729: {
730: return me ? me->content_language : NULL;
731: }
732:
733: PUBLIC void HTAnchor_setLanguage ARGS2(HTParentAnchor *,me,
734: HTLanguage, language)
735: {
736: if (me) me->content_language = language;
737: }
738:
739: /*
1.17 frystyk 740: ** Content Transfer Encoding
1.1 timbl 741: */
1.17 frystyk 742: PUBLIC HTCte HTAnchor_cte ARGS1(HTParentAnchor *,me)
743: {
744: return me ? me->cte : NULL;
745: }
1.1 timbl 746:
1.17 frystyk 747: PUBLIC void HTAnchor_setCte ARGS2(HTParentAnchor *,me, HTCte, cte)
748: {
749: if (me) me->cte = cte;
750: }
751:
752: /*
753: ** Content Length
754: */
755: PUBLIC long int HTAnchor_length ARGS1(HTParentAnchor *,me)
1.1 timbl 756: {
1.17 frystyk 757: return me ? me->content_length : -1;
1.1 timbl 758: }
759:
1.17 frystyk 760: PUBLIC void HTAnchor_setLength ARGS2(HTParentAnchor *,me, long int, length)
761: {
762: if (me) me->content_length = length;
763: }
1.1 timbl 764:
1.17 frystyk 765: /*
766: ** Allowed methods (Allow)
1.1 timbl 767: */
1.17 frystyk 768: PUBLIC int HTAnchor_methods ARGS1(HTParentAnchor *, me)
769: {
770: return me ? me->methods : 0;
771: }
1.1 timbl 772:
1.17 frystyk 773: PUBLIC void HTAnchor_setMethods ARGS2(HTParentAnchor *,me, int, methodset)
1.1 timbl 774: {
1.17 frystyk 775: if (me) me->methods = methodset;
1.1 timbl 776: }
777:
1.17 frystyk 778: PUBLIC void HTAnchor_appendMethods ARGS2(HTParentAnchor *,me, int, methodset)
1.1 timbl 779: {
1.17 frystyk 780: if (me) me->methods += methodset;
1.1 timbl 781: }
782:
1.17 frystyk 783: /*
784: ** Title
1.2 timbl 785: */
1.17 frystyk 786: PUBLIC CONST char * HTAnchor_title ARGS1 (HTParentAnchor *,me)
1.1 timbl 787: {
1.17 frystyk 788: return me ? me->title : NULL;
789: }
1.1 timbl 790:
1.17 frystyk 791: PUBLIC void HTAnchor_setTitle ARGS2(HTParentAnchor *,me, CONST char *, title)
792: {
793: if (me && title) StrAllocCopy(me->title, title);
1.2 timbl 794: }
795:
1.17 frystyk 796: PUBLIC void HTAnchor_appendTitle ARGS2(HTParentAnchor *,me, CONST char *,title)
797: {
798: if (me && title) StrAllocCat(me->title, title);
799: }
1.2 timbl 800:
1.17 frystyk 801: /*
802: ** Version
1.2 timbl 803: */
1.17 frystyk 804: PUBLIC CONST char * HTAnchor_version ARGS1 (HTParentAnchor *,me)
805: {
806: return me ? me->version : NULL;
807: }
1.2 timbl 808:
1.17 frystyk 809: PUBLIC void HTAnchor_setVersion ARGS2(HTParentAnchor *, me,
810: CONST char *, version)
1.2 timbl 811: {
1.17 frystyk 812: if (me && version) StrAllocCopy(me->version, version);
1.2 timbl 813: }
814:
1.17 frystyk 815: /*
816: ** Derived from
1.2 timbl 817: */
1.17 frystyk 818: PUBLIC CONST char * HTAnchor_derived ARGS1 (HTParentAnchor *,me)
819: {
820: return me ? me->derived_from : NULL;
821: }
822:
823: PUBLIC void HTAnchor_setDerived ARGS2(HTParentAnchor *, me,
824: CONST char *, derived_from)
825: {
826: if (me && derived_from) StrAllocCopy(me->derived_from, derived_from);
827: }
1.2 timbl 828:
1.17 frystyk 829: /*
830: ** Extra Header List of unknown headers
831: */
832: PUBLIC HTList * HTAnchor_Extra ARGS1 (HTParentAnchor *, me)
1.2 timbl 833: {
1.17 frystyk 834: return me ? me->extra_headers : NULL;
1.2 timbl 835: }
836:
1.17 frystyk 837: PUBLIC void HTAnchor_addExtra ARGS2(HTParentAnchor *, me,
838: CONST char * , header)
1.2 timbl 839: {
1.17 frystyk 840: if (me) {
1.18 frystyk 841: char *newhead = NULL;
842: StrAllocCopy(newhead, header);
1.17 frystyk 843: if (!me->extra_headers)
844: me->extra_headers = HTList_new();
1.18 frystyk 845: HTList_addObject(me->extra_headers, (void *) newhead);
1.17 frystyk 846: }
1.2 timbl 847: }
848:
1.23 frystyk 849: /*
850: ** Has header been parsed?
1.2 timbl 851: */
1.17 frystyk 852: PUBLIC BOOL HTAnchor_headerParsed ARGS1(HTParentAnchor *, me)
1.2 timbl 853: {
1.17 frystyk 854: return (me ? me->header_parsed : NO);
1.23 frystyk 855: }
856:
857: PUBLIC void HTAnchor_setHeaderParsed ARGS1(HTParentAnchor *, me)
858: {
859: if (me) me->header_parsed = YES;
1.2 timbl 860: }
861:
1.17 frystyk 862: /* Clear Header Information
863: ** ------------------------
864: */
865: PUBLIC void HTAnchor_clearHeader ARGS1(HTParentAnchor *, me)
1.2 timbl 866: {
1.17 frystyk 867: me->methods = METHOD_INVALID;
868: me->content_encoding = NULL;
1.21 frystyk 869: #ifdef NEW_CODE
870: /* WAIT UNTIL WE HANDLE LANGUAGE AS A LIST */
1.17 frystyk 871: if (me->content_language) {
872: HTList_delete(me->content_language);
873: me->content_language = HTList_new();
1.9 frystyk 874: }
1.21 frystyk 875: #else
876: me->content_language = NULL;
877: #endif
1.17 frystyk 878: me->content_length = -1; /* Invalid */
879: me->cte = NULL;
880: me->content_type = WWW_UNKNOWN;
881: me->charset = NULL;
1.20 frystyk 882: me->level = NULL;
1.17 frystyk 883:
884: me->date = (time_t) 0;
885: me->expires = (time_t) 0;
886: me->last_modified = (time_t) 0;
887:
1.18 frystyk 888: FREE(me->derived_from);
889: FREE(me->version);
890:
891: if (me->extra_headers) {
892: HTList *cur = me->extra_headers;
893: char *pres;
894: while ((pres = (char *) HTList_nextObject(cur)))
895: free(pres);
896: HTList_delete(me->extra_headers);
897: me->extra_headers = NULL;
898: }
1.17 frystyk 899: me->header_parsed = NO; /* All cleared */
1.1 timbl 900: }
Webmaster