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