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