Annotation of libwww/Library/src/HTAnchor.c, revision 1.18
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;
52: newAnchor->level = HTML_INVALID;
1.16 frystyk 53: return newAnchor;
1.1 timbl 54: }
55:
1.16 frystyk 56:
57: PRIVATE HTChildAnchor * HTChildAnchor_new NOARGS
1.1 timbl 58: {
1.16 frystyk 59: return (HTChildAnchor *) calloc (1, sizeof (HTChildAnchor));
1.1 timbl 60: }
61:
62:
1.17 frystyk 63: /* Create new or find old child anchor
64: ** -----------------------------------
1.1 timbl 65: **
1.3 timbl 66: ** Me one is for a new anchor being edited into an existing
1.17 frystyk 67: ** document. The parent anchor must already exist. All
68: ** children without tags (no NAME attribut) points to the same NULL
69: ** child.
1.1 timbl 70: */
1.17 frystyk 71: PUBLIC HTChildAnchor * HTAnchor_findChild ARGS2 (HTParentAnchor *, parent,
72: CONST char *,tag)
1.1 timbl 73: {
1.17 frystyk 74: HTChildAnchor *child;
75: HTList *kids;
76:
77: if (!parent) {
78: if (ANCH_TRACE)
79: fprintf(TDEST, "Find Child.. called with NULL parent.\n");
80: return NULL;
81: }
1.1 timbl 82:
1.17 frystyk 83: /* First search list of children to see if tag is already there */
84: if ((kids = parent->children)) {
85: if (tag && *tag) { /* TBL */
86: while ((child = (HTChildAnchor *) HTList_nextObject(kids))) {
87: if (!(child->tag && strcasecomp(child->tag, tag))) {
88: if (ANCH_TRACE)
89: fprintf (TDEST,
90: "Find Child.. %p of parent %p with name `%s' already exists.\n",
91: (void *) child, (void *) parent, tag);
92: return child;
93: }
1.1 timbl 94: }
95: }
1.17 frystyk 96: } else /* Create new list of children */
97: parent->children = HTList_new ();
98:
99: /* Did't find it so we need to create a new one */
100: child = HTChildAnchor_new();
101: HTList_addObject(parent->children, child);
102: child->parent = parent;
103: StrAllocCopy(child->tag, tag);
104: if (ANCH_TRACE)
105: fprintf(TDEST,"Find Child.. New Anchor %p named `%s' is child of %p\n",
106: (void *) child, tag ? tag : (CONST char *) "", (void *)parent);
107: return child;
1.1 timbl 108: }
109:
110:
111: /* Create new or find old named anchor
112: ** -----------------------------------
113: **
1.3 timbl 114: ** Me one is for a reference which is found in a document, and might
1.1 timbl 115: ** not be already loaded.
116: ** Note: You are not guaranteed a new anchor -- you might get an old one,
117: ** like with fonts.
118: */
1.16 frystyk 119: PUBLIC HTAnchor * HTAnchor_findAddress ARGS1 (CONST char *, address)
1.1 timbl 120: {
1.16 frystyk 121: char *tag = HTParse (address, "", PARSE_ANCHOR); /* Any tags? */
122: char *newaddr=NULL;
1.1 timbl 123:
1.17 frystyk 124: StrAllocCopy(newaddr, address); /* Get our own copy */
1.16 frystyk 125: if (!HTImProxy)
126: newaddr = HTSimplify(newaddr); /* Proxy has already simplified */
127:
128: /* If the address represents a sub-anchor, we recursively load its parent,
129: then we create a child anchor within that document. */
130: if (*tag) {
131: char *docAddress = HTParse(newaddr, "", PARSE_ACCESS | PARSE_HOST |
132: PARSE_PATH | PARSE_PUNCTUATION);
133: HTParentAnchor * foundParent =
134: (HTParentAnchor *) HTAnchor_findAddress (docAddress);
135: HTChildAnchor * foundAnchor = HTAnchor_findChild (foundParent, tag);
136: free (docAddress);
137: free (tag);
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);
162: return (HTAnchor *) foundAnchor;
163: }
164: }
165:
166: /* Node not found : create new anchor. */
167: foundAnchor = HTParentAnchor_new();
168: foundAnchor->address = newaddr; /* Remember our copy */
169: HTList_addObject (adults, foundAnchor);
1.17 frystyk 170: if (ANCH_TRACE) fprintf(TDEST, "Find Parent. %p with hash %d and address `%s' created\n", (void*)foundAnchor, hash, newaddr);
1.1 timbl 171: return (HTAnchor *) foundAnchor;
172: }
173: }
174:
1.17 frystyk 175: /* ------------------------------------------------------------------------- */
176: /* Link Methods */
177: /* ------------------------------------------------------------------------- */
178:
179: /* Create or find a child anchor with a possible link
180: ** --------------------------------------------------
181: **
182: ** Create new anchor with a given parent and possibly
183: ** a name, and possibly a link to a _relatively_ named anchor.
184: ** (Code originally in ParseHTML.h)
185: */
186: PUBLIC HTChildAnchor * HTAnchor_findChildAndLink
187: ARGS4(
188: HTParentAnchor *,parent, /* May not be 0 */
189: CONST char *,tag, /* May be "" or 0 */
190: CONST char *,href, /* May be "" or 0 */
191: HTLinkType *,ltype /* May be 0 */
192: )
193: {
194: HTChildAnchor * child = HTAnchor_findChild(parent, tag);
195: if (href && *href) {
196: char * relative_to = HTAnchor_address((HTAnchor *) parent);
197: char * parsed_address = HTParse(href, relative_to, PARSE_ALL);
198: HTAnchor * dest = HTAnchor_findAddress(parsed_address);
199: HTAnchor_link((HTAnchor *) child, dest, ltype);
200: free(parsed_address);
201: free(relative_to);
202: }
203: return child;
204: }
205:
206: /* Link me Anchor to another given one
207: ** -------------------------------------
208: */
209: PUBLIC BOOL HTAnchor_link ARGS3(HTAnchor *, source,
210: HTAnchor *, destination,
211: HTLinkType *, type)
212: {
213: if (!(source && destination))
214: return NO; /* Can't link to/from non-existing anchor */
215: if (ANCH_TRACE)
216: fprintf(TDEST, "Link Anchors anchor %p to anchor %p\n",
217: (void *) source, (void *) destination);
218: if (!source->mainLink.dest) {
219: source->mainLink.dest = destination;
220: source->mainLink.type = type;
221: } else {
222: HTLink * newLink = (HTLink *) calloc(1, sizeof (HTLink));
223: if (newLink == NULL) outofmem(__FILE__, "HTAnchor_link");
224: newLink->dest = destination;
225: newLink->type = type;
226: if (! source->links)
227: source->links = HTList_new ();
228: HTList_addObject (source->links, newLink);
229: }
230: if (!destination->parent->sources)
231: destination->parent->sources = HTList_new ();
232: HTList_addObject (destination->parent->sources, source);
233: return YES;
234: }
235:
236:
237: /* Manipulation of links
238: ** ---------------------
239: */
240:
241: PUBLIC HTAnchor * HTAnchor_followMainLink
242: ARGS1 (HTAnchor *,me)
243: {
244: return me->mainLink.dest;
245: }
246:
247: PUBLIC HTAnchor * HTAnchor_followTypedLink
248: ARGS2 (HTAnchor *,me, HTLinkType *,type)
249: {
250: if (me->mainLink.type == type)
251: return me->mainLink.dest;
252: if (me->links) {
253: HTList *links = me->links;
254: HTLink *link;
255: while ((link = (HTLink *) HTList_nextObject (links)))
256: if (link->type == type)
257: return link->dest;
258: }
259: return NULL; /* No link of me type */
260: }
261:
262:
263: /* Make main link
264: */
265: PUBLIC BOOL HTAnchor_makeMainLink
266: ARGS2 (HTAnchor *,me, HTLink *,movingLink)
267: {
268: /* Check that everything's OK */
269: if (! (me && HTList_removeObject (me->links, movingLink)))
270: return NO; /* link not found or NULL anchor */
271: else {
272: /* First push current main link onto top of links list */
273: HTLink *newLink = (HTLink*) malloc (sizeof (HTLink));
274: if (newLink == NULL) outofmem(__FILE__, "HTAnchor_makeMainLink");
275: memcpy (newLink, & me->mainLink, sizeof (HTLink));
276: HTList_addObject (me->links, newLink);
277:
278: /* Now make movingLink the new main link, and free it */
279: memcpy (& me->mainLink, movingLink, sizeof (HTLink));
280: free (movingLink);
281: return YES;
282: }
283: }
284:
285: /* Move an anchor to the head of the list of its siblings
286: ** ------------------------------------------------------
287: **
288: ** This is to ensure that an anchor which might have already existed
289: ** is put in the correct order as we load the document.
290: */
291:
292: PUBLIC void HTAnchor_makeLastChild
293: ARGS1(HTChildAnchor *,me)
294: {
295: if (me->parent != (HTParentAnchor *) me) { /* Make sure it's a child */
296: HTList * siblings = me->parent->children;
297: HTList_removeObject (siblings, me);
298: HTList_addObject (siblings, me);
299: }
300: }
301:
302: /* ------------------------------------------------------------------------- */
303: /* Deletion Methods */
304: /* ------------------------------------------------------------------------- */
1.1 timbl 305:
306: /* Delete an anchor and possibly related things (auto garbage collection)
307: ** --------------------------------------------
308: **
309: ** The anchor is only deleted if the corresponding document is not loaded.
1.10 frystyk 310: ** All outgoing links from parent and children are deleted, and this
311: ** anchor is removed from the sources list of all its targets.
1.1 timbl 312: ** We also try to delete the targets whose documents are not loaded.
313: ** If this anchor's source list is empty, we delete it and its children.
314: */
315:
316: PRIVATE void deleteLinks
1.3 timbl 317: ARGS1 (HTAnchor *,me)
1.1 timbl 318: {
1.3 timbl 319: if (! me)
1.1 timbl 320: return;
321:
322: /* Recursively try to delete target anchors */
1.3 timbl 323: if (me->mainLink.dest) {
324: HTParentAnchor *parent = me->mainLink.dest->parent;
325: HTList_removeObject (parent->sources, me);
1.1 timbl 326: if (! parent->document) /* Test here to avoid calling overhead */
327: HTAnchor_delete (parent);
328: }
1.3 timbl 329: if (me->links) { /* Extra destinations */
1.1 timbl 330: HTLink *target;
1.12 frystyk 331: while ((target = (HTLink *) HTList_removeLastObject (me->links))) {
1.1 timbl 332: HTParentAnchor *parent = target->dest->parent;
1.3 timbl 333: HTList_removeObject (parent->sources, me);
1.1 timbl 334: if (! parent->document) /* Test here to avoid calling overhead */
335: HTAnchor_delete (parent);
336: }
337: }
338: }
339:
340: PUBLIC BOOL HTAnchor_delete
1.3 timbl 341: ARGS1 (HTParentAnchor *,me)
1.1 timbl 342: {
343: HTChildAnchor *child;
344:
345: /* Don't delete if document is loaded */
1.3 timbl 346: if (me->document)
1.1 timbl 347: return NO;
348:
349: /* Recursively try to delete target anchors */
1.3 timbl 350: deleteLinks ((HTAnchor *) me);
1.1 timbl 351:
1.3 timbl 352: if (! HTList_isEmpty (me->sources)) { /* There are still incoming links */
1.1 timbl 353: /* Delete all outgoing links from children, if any */
1.3 timbl 354: HTList *kids = me->children;
1.12 frystyk 355: while ((child = (HTChildAnchor *) HTList_nextObject (kids)))
1.1 timbl 356: deleteLinks ((HTAnchor *) child);
357: return NO; /* Parent not deleted */
358: }
359:
360: /* No more incoming links : kill everything */
361: /* First, recursively delete children */
1.12 frystyk 362: while ((child = (HTChildAnchor *) HTList_removeLastObject (me->children))) {
1.1 timbl 363: deleteLinks ((HTAnchor *) child);
364: free (child->tag);
365: free (child);
366: }
367:
368: /* Now kill myself */
1.3 timbl 369: HTList_delete (me->children);
370: HTList_delete (me->sources);
371: free (me->address);
1.1 timbl 372: /* Devise a way to clean out the HTFormat if no longer needed (ref count?) */
1.3 timbl 373: free (me);
1.6 timbl 374: if (me->cacheItems) {
375: HTCacheClear(me->cacheItems);
376: }
1.1 timbl 377: return YES; /* Parent deleted */
378: }
379:
1.17 frystyk 380: /* ------------------------------------------------------------------------- */
381: /* Data Access Methods */
382: /* ------------------------------------------------------------------------- */
1.1 timbl 383:
1.17 frystyk 384: PUBLIC HTParentAnchor * HTAnchor_parent ARGS1 (HTAnchor *,me)
1.1 timbl 385: {
1.17 frystyk 386: return me ? me->parent : NULL;
1.1 timbl 387: }
388:
1.17 frystyk 389: PUBLIC void HTAnchor_setDocument ARGS2 (HTParentAnchor *, me, HyperDoc *,doc)
1.1 timbl 390: {
1.17 frystyk 391: if (me)
392: me->document = doc;
1.1 timbl 393: }
394:
1.17 frystyk 395: PUBLIC HyperDoc * HTAnchor_document ARGS1 (HTParentAnchor *,me)
1.1 timbl 396: {
1.17 frystyk 397: return me ? me->document : NULL;
1.1 timbl 398: }
399:
400:
1.10 frystyk 401: #if 0
1.17 frystyk 402: /* We might want to use this when we have a link editing application */
1.10 frystyk 403: PUBLIC void HTAnchor_setAddress
1.3 timbl 404: ARGS2 (HTAnchor *,me, char *,addr)
1.1 timbl 405: {
1.3 timbl 406: if (me)
407: StrAllocCopy (me->parent->address, addr);
1.1 timbl 408: }
1.10 frystyk 409: #endif
410:
1.17 frystyk 411: PUBLIC char * HTAnchor_address ARGS1 (HTAnchor *, me)
1.1 timbl 412: {
1.17 frystyk 413: char *addr = NULL;
414: if (me) {
415: if (((HTParentAnchor *) me == me->parent) ||
416: !((HTChildAnchor *) me)->tag) { /* it's an adult or no tag */
417: StrAllocCopy (addr, me->parent->address);
418: }
419: else { /* it's a named child */
420: addr = (char *) malloc (2 + strlen (me->parent->address)
421: + strlen (((HTChildAnchor *) me)->tag));
422: if (addr == NULL) outofmem(__FILE__, "HTAnchor_address");
423: sprintf (addr, "%s#%s", me->parent->address,
424: ((HTChildAnchor *) me)->tag);
425: }
1.1 timbl 426: }
1.17 frystyk 427: return addr;
1.1 timbl 428: }
429:
1.17 frystyk 430: PUBLIC BOOL HTAnchor_hasChildren ARGS1 (HTParentAnchor *,me)
431: {
432: return me ? ! HTList_isEmpty(me->children) : NO;
433: }
1.1 timbl 434:
1.17 frystyk 435: PUBLIC void HTAnchor_clearIndex ARGS1 (HTParentAnchor *,me)
436: {
437: if (me)
438: me->isIndex = NO;
439: }
1.1 timbl 440:
1.17 frystyk 441: PUBLIC void HTAnchor_setIndex ARGS1 (HTParentAnchor *,me)
1.1 timbl 442: {
1.3 timbl 443: if (me)
1.17 frystyk 444: me->isIndex = YES;
445: }
446:
447: PUBLIC BOOL HTAnchor_isIndex ARGS1 (HTParentAnchor *,me)
448: {
449: return me ? me->isIndex : NO;
1.1 timbl 450: }
451:
1.17 frystyk 452: /* Protocol
453: ** --------
454: */
455:
456: PUBLIC void * HTAnchor_protocol ARGS1(HTParentAnchor *, me)
1.1 timbl 457: {
1.17 frystyk 458: return me->protocol;
1.1 timbl 459: }
460:
1.17 frystyk 461: PUBLIC void HTAnchor_setProtocol ARGS2(HTParentAnchor *, me,
462: void*, protocol)
1.9 frystyk 463: {
1.17 frystyk 464: me->protocol = protocol;
1.9 frystyk 465: }
1.1 timbl 466:
1.17 frystyk 467: /* Physical Address
468: ** ----------------
469: */
470:
471: PUBLIC char * HTAnchor_physical ARGS1(HTParentAnchor *, me)
1.1 timbl 472: {
1.17 frystyk 473: return me->physical;
1.1 timbl 474: }
475:
1.17 frystyk 476: PUBLIC void HTAnchor_setPhysical ARGS2(HTParentAnchor *, me,
477: char *, physical)
1.1 timbl 478: {
1.17 frystyk 479: if (!me || !physical) {
480: if (ANCH_TRACE)
481: fprintf(TDEST, "HTAnchor.... setPhysical, called with null argument\n");
482: return;
483: }
484: StrAllocCopy(me->physical, physical);
1.1 timbl 485: }
486:
1.17 frystyk 487: /* ------------------------------------------------------------------------- */
488: /* Entity Header Information */
489: /* ------------------------------------------------------------------------- */
490:
491: /*
492: ** Media Types (Content-Type)
493: */
494: PUBLIC HTFormat HTAnchor_format ARGS1(HTParentAnchor *,me)
495: {
496: return me ? me->content_type : NULL;
497: }
1.1 timbl 498:
1.17 frystyk 499: PUBLIC void HTAnchor_setFormat ARGS2(HTParentAnchor *,me, HTFormat, form)
1.1 timbl 500: {
1.17 frystyk 501: if (me) me->content_type = form;
1.1 timbl 502: }
503:
1.17 frystyk 504: /*
505: ** Charset parameter to Content-Type
1.1 timbl 506: */
1.17 frystyk 507: PUBLIC HTCharset HTAnchor_charset ARGS1(HTParentAnchor *, me)
1.1 timbl 508: {
1.17 frystyk 509: return me ? me->charset : NULL;
1.1 timbl 510: }
511:
1.17 frystyk 512: PUBLIC void HTAnchor_setCharset ARGS2(HTParentAnchor *,me, HTCharset, charset)
1.1 timbl 513: {
1.17 frystyk 514: if (me) me->charset = charset;
1.1 timbl 515: }
516:
1.17 frystyk 517: /*
518: ** Content Encoding
519: */
520: PUBLIC HTEncoding HTAnchor_encoding ARGS1(HTParentAnchor *,me)
1.1 timbl 521: {
1.17 frystyk 522: return me ? me->content_encoding : NULL;
1.1 timbl 523: }
524:
1.17 frystyk 525: PUBLIC void HTAnchor_setEncoding ARGS2(HTParentAnchor *,me,
526: HTEncoding, encoding)
527: {
528: if (me) me->content_encoding = encoding;
529: }
530:
531: /*
532: ** Content Transfer Encoding
1.1 timbl 533: */
1.17 frystyk 534: PUBLIC HTCte HTAnchor_cte ARGS1(HTParentAnchor *,me)
535: {
536: return me ? me->cte : NULL;
537: }
1.1 timbl 538:
1.17 frystyk 539: PUBLIC void HTAnchor_setCte ARGS2(HTParentAnchor *,me, HTCte, cte)
540: {
541: if (me) me->cte = cte;
542: }
543:
544: /*
545: ** Content Length
546: */
547: PUBLIC long int HTAnchor_length ARGS1(HTParentAnchor *,me)
1.1 timbl 548: {
1.17 frystyk 549: return me ? me->content_length : -1;
1.1 timbl 550: }
551:
1.17 frystyk 552: PUBLIC void HTAnchor_setLength ARGS2(HTParentAnchor *,me, long int, length)
553: {
554: if (me) me->content_length = length;
555: }
1.1 timbl 556:
1.17 frystyk 557: /*
558: ** Allowed methods (Allow)
1.1 timbl 559: */
1.17 frystyk 560: PUBLIC int HTAnchor_methods ARGS1(HTParentAnchor *, me)
561: {
562: return me ? me->methods : 0;
563: }
1.1 timbl 564:
1.17 frystyk 565: PUBLIC void HTAnchor_setMethods ARGS2(HTParentAnchor *,me, int, methodset)
1.1 timbl 566: {
1.17 frystyk 567: if (me) me->methods = methodset;
1.1 timbl 568: }
569:
1.17 frystyk 570: PUBLIC void HTAnchor_appendMethods ARGS2(HTParentAnchor *,me, int, methodset)
1.1 timbl 571: {
1.17 frystyk 572: if (me) me->methods += methodset;
1.1 timbl 573: }
574:
1.17 frystyk 575: /*
576: ** Title
1.2 timbl 577: */
1.17 frystyk 578: PUBLIC CONST char * HTAnchor_title ARGS1 (HTParentAnchor *,me)
1.1 timbl 579: {
1.17 frystyk 580: return me ? me->title : NULL;
581: }
1.1 timbl 582:
1.17 frystyk 583: PUBLIC void HTAnchor_setTitle ARGS2(HTParentAnchor *,me, CONST char *, title)
584: {
585: if (me && title) StrAllocCopy(me->title, title);
1.2 timbl 586: }
587:
1.17 frystyk 588: PUBLIC void HTAnchor_appendTitle ARGS2(HTParentAnchor *,me, CONST char *,title)
589: {
590: if (me && title) StrAllocCat(me->title, title);
591: }
1.2 timbl 592:
1.17 frystyk 593: /*
594: ** Version
1.2 timbl 595: */
1.17 frystyk 596: PUBLIC CONST char * HTAnchor_version ARGS1 (HTParentAnchor *,me)
597: {
598: return me ? me->version : NULL;
599: }
1.2 timbl 600:
1.17 frystyk 601: PUBLIC void HTAnchor_setVersion ARGS2(HTParentAnchor *, me,
602: CONST char *, version)
1.2 timbl 603: {
1.17 frystyk 604: if (me && version) StrAllocCopy(me->version, version);
1.2 timbl 605: }
606:
1.17 frystyk 607: /*
608: ** Derived from
1.2 timbl 609: */
1.17 frystyk 610: PUBLIC CONST char * HTAnchor_derived ARGS1 (HTParentAnchor *,me)
611: {
612: return me ? me->derived_from : NULL;
613: }
614:
615: PUBLIC void HTAnchor_setDerived ARGS2(HTParentAnchor *, me,
616: CONST char *, derived_from)
617: {
618: if (me && derived_from) StrAllocCopy(me->derived_from, derived_from);
619: }
1.2 timbl 620:
1.17 frystyk 621: /*
622: ** Extra Header List of unknown headers
623: */
624: PUBLIC HTList * HTAnchor_Extra ARGS1 (HTParentAnchor *, me)
1.2 timbl 625: {
1.17 frystyk 626: return me ? me->extra_headers : NULL;
1.2 timbl 627: }
628:
1.17 frystyk 629: PUBLIC void HTAnchor_addExtra ARGS2(HTParentAnchor *, me,
630: CONST char * , header)
1.2 timbl 631: {
1.17 frystyk 632: if (me) {
1.18 ! frystyk 633: char *newhead = NULL;
! 634: StrAllocCopy(newhead, header);
1.17 frystyk 635: if (!me->extra_headers)
636: me->extra_headers = HTList_new();
1.18 ! frystyk 637: HTList_addObject(me->extra_headers, (void *) newhead);
1.17 frystyk 638: }
1.2 timbl 639: }
640:
1.17 frystyk 641: /* Has header been parsed?
642: ** -----------------------
1.2 timbl 643: */
1.17 frystyk 644: PUBLIC BOOL HTAnchor_headerParsed ARGS1(HTParentAnchor *, me)
1.2 timbl 645: {
1.17 frystyk 646: return (me ? me->header_parsed : NO);
1.2 timbl 647: }
648:
1.17 frystyk 649: /* Clear Header Information
650: ** ------------------------
651: */
652: PUBLIC void HTAnchor_clearHeader ARGS1(HTParentAnchor *, me)
1.2 timbl 653: {
1.17 frystyk 654: me->methods = METHOD_INVALID;
655: me->content_encoding = NULL;
656: if (me->content_language) {
657: HTList_delete(me->content_language);
658: me->content_language = HTList_new();
1.9 frystyk 659: }
1.17 frystyk 660: me->content_length = -1; /* Invalid */
661: me->cte = NULL;
662: me->content_type = WWW_UNKNOWN;
663: me->charset = NULL;
664: me->level = HTML_INVALID;
665:
666: me->date = (time_t) 0;
667: me->expires = (time_t) 0;
668: me->last_modified = (time_t) 0;
669:
1.18 ! frystyk 670: FREE(me->derived_from);
! 671: FREE(me->version);
! 672:
! 673: if (me->extra_headers) {
! 674: HTList *cur = me->extra_headers;
! 675: char *pres;
! 676: while ((pres = (char *) HTList_nextObject(cur)))
! 677: free(pres);
! 678: HTList_delete(me->extra_headers);
! 679: me->extra_headers = NULL;
! 680: }
1.17 frystyk 681: me->header_parsed = NO; /* All cleared */
1.1 timbl 682: }
Webmaster