Annotation of libwww/Library/src/HTAccess.html, revision 2.31
2.9 timbl 1: <HTML>
2: <HEAD>
2.6 timbl 3: <TITLE>HTAccess: Access manager for libwww</TITLE>
2.19 timbl 4: <NEXTID N="z11">
2.9 timbl 5: </HEAD>
2.5 timbl 6: <BODY>
7: <H1>Access Manager</H1>This module keeps a list of valid
8: protocol (naming scheme) specifiers
9: with associated access code. It
10: allows documents to be loaded given
11: various combinations of parameters.
12: New access protocols may be registered
13: at any time.<P>
2.9 timbl 14: Note: HTRequest defined and request
15: parametsr added to almost all calls
16: 18 Nov 1993.<P>
2.5 timbl 17: Part of the <A
2.19 timbl 18: NAME="z0" HREF="Overview.html">libwww library</A> . Implemented
19: by <A
20: NAME="z8" HREF="HTAccess.c">HTAcces.c</A>
2.5 timbl 21: <PRE>#ifndef HTACCESS_H
1.1 timbl 22: #define HTACCESS_H
23:
24: /* Definition uses:
25: */
26: #include "HTUtils.h"
2.16 luotonen 27: #include "HTList.h"
1.1 timbl 28: #include "tcp.h"
2.14 luotonen 29:
1.1 timbl 30:
31: #ifdef SHORT_NAMES
2.8 timbl 32: #define HTClientHost HTClHost
33: #define HTSearchAbsolute HTSeAbso
34: #define HTOutputStream HTOuStre
35: #define HTOutputFormat HTOuForm
1.1 timbl 36: #endif
37:
2.16 luotonen 38: typedef enum {
39: METHOD_INVALID = 0,
40: METHOD_GET = 1,
41: METHOD_HEAD,
42: METHOD_POST,
43: METHOD_PUT,
44: METHOD_DELETE,
45: METHOD_CHECKOUT,
46: METHOD_CHECKIN,
47: METHOD_SHOWMETHOD,
48: METHOD_LINK,
49: METHOD_UNLINK,
50: MAX_METHODS
51: } HTMethod;
52:
53:
54: </PRE>
55: <H2>Methods</H2>
56: <PRE>
57:
58: /* Get method enum value
59: ** ---------------------
60: */
61: PUBLIC HTMethod HTMethod_enum PARAMS((char * name));
62:
63:
64: /* Get method name
65: ** ---------------
66: */
67: PUBLIC char * HTMethod_name PARAMS((HTMethod method));
68:
69:
70: /* PUBLIC HTMethod_inList()
71: ** IS A METHOD IN A LIST OF METHOD NAMES
72: ** ON ENTRY:
73: ** method is the method to look for.
74: ** list is a list of method names.
75: **
76: ** ON EXIT:
77: ** returns YES, if method was found.
78: ** NO, if not found.
79: */
80: PUBLIC BOOL HTMethod_inList PARAMS((HTMethod method,
81: HTList * list));
82: </PRE>
83: <H2>Match Template Against Filename</H2>
84: <PRE>
85: /* PUBLIC HTAA_templateMatch()
86: ** STRING COMPARISON FUNCTION FOR FILE NAMES
87: ** WITH ONE WILDCARD * IN THE TEMPLATE
88: ** NOTE:
89: ** This is essentially the same code as in HTRules.c, but it
90: ** cannot be used because it is embedded in between other code.
91: ** (In fact, HTRules.c should use this routine, but then this
92: ** routine would have to be more sophisticated... why is life
93: ** sometimes so hard...)
94: **
95: ** ON ENTRY:
96: ** template is a template string to match the file name
97: ** agaist, may contain a single wildcard
98: ** character * which matches zero or more
99: ** arbitrary characters.
100: ** filename is the filename (or pathname) to be matched
101: ** agaist the template.
102: **
103: ** ON EXIT:
104: ** returns YES, if filename matches the template.
105: ** NO, otherwise.
106: */
107: PUBLIC BOOL HTAA_templateMatch PARAMS((CONST char * template,
108: CONST char * filename));
109:
110:
2.19 timbl 111: </PRE>The following have to be defined
2.10 timbl 112: in advance of the other include files
113: because of circular references.
114: <PRE>typedef struct _HTRequest HTRequest;
115:
2.14 luotonen 116: /*
117: ** Callback to call when username and password
118: ** have been prompted.
119: */
120: typedef int (*HTRetryCallbackType) PARAMS((HTRequest * req));
121:
122:
2.10 timbl 123: #include "HTAnchor.h"
124: #include <A
125: NAME="z3" HREF="HTFormat.html">"HTFormat.h"</A>
2.15 luotonen 126: #include "HTAAUtil.h" /* HTAAScheme, HTAAFailReason */
2.14 luotonen 127: #include "HTAABrow.h" /* HTAASetup */
2.10 timbl 128:
129:
1.1 timbl 130: /* Return codes from load routines:
131: **
132: ** These codes may be returned by the protocol modules,
133: ** and by the HTLoad routines.
134: ** In general, positive codes are OK and negative ones are bad.
135: */
136:
137: #define HT_NO_DATA -9999 /* return code: OK but no data was loaded */
138: /* Typically, other app started or forked */
139:
2.5 timbl 140: </PRE>
2.6 timbl 141: <H2>Default Addresses</H2>These control the home page selection.
2.8 timbl 142: To mess with these for normal browses
2.6 timbl 143: is asking for user confusion.
144: <PRE>#define LOGICAL_DEFAULT "WWW_HOME" /* Defined to be the home page */
1.1 timbl 145:
2.6 timbl 146: #ifndef PERSONAL_DEFAULT
147: #define PERSONAL_DEFAULT "WWW/default.html" /* in home directory */
148: #endif
149: #ifndef LOCAL_DEFAULT_FILE
1.1 timbl 150: #define LOCAL_DEFAULT_FILE "/usr/local/lib/WWW/default.html"
2.6 timbl 151: #endif
2.7 timbl 152: /* If one telnets to a www access point,
153: it will look in this file for home page */
154: #ifndef REMOTE_POINTER
155: #define REMOTE_POINTER "/etc/www-remote.url" /* can't be file */
156: #endif
157: /* and if that fails it will use this. */
2.6 timbl 158: #ifndef REMOTE_ADDRESS
1.1 timbl 159: #define REMOTE_ADDRESS "http://info.cern.ch/remote.html" /* can't be file */
160: #endif
161:
162: /* If run from telnet daemon and no -l specified, use this file:
163: */
164: #ifndef DEFAULT_LOGFILE
165: #define DEFAULT_LOGFILE "/usr/adm/www-log/www-log"
166: #endif
167:
168: /* If the home page isn't found, use this file:
169: */
170: #ifndef LAST_RESORT
2.6 timbl 171: #define LAST_RESORT "http://info.cern.ch/default.html"
1.1 timbl 172: #endif
173:
2.23 frystyk 174: /* This is the default cache directory:
175: */
176: #ifndef CACHE_HOME_DIR
177: #define CACHE_HOME_DIR "/tmp/"
178: #endif
179:
180: /* The default directory for "save locally" and "save and execute" files:
181: */
182: #ifndef SAVE_LOCALLY_HOME_DIR
183: #define SAVE_LOCALLY_HOME_DIR "/tmp/"
184: #endif
2.10 timbl 185:
2.9 timbl 186: </PRE>
187: <H2><A
188: NAME="z1">The Request structure</A></H2>When a request is handled, all kinds
189: of things about it need to be passed
190: along. These are all put into a
2.31 ! frystyk 191: HTRequest structure. <P>
! 192:
! 193: <NOTE>Note 1:</NOTE> There is also a <A NAME="z4" HREF="HTFormat.html#z17">global list of converters</A> <P>
! 194: <NOTE>Note 2:</NOTE> It is <B>NOT</B> safe to reuse a request structure for more than one request. It should be freed and reallocated or cleared, see <A HREF="#z100">functions to manipulate HTRequest Structure</A>
! 195:
2.10 timbl 196: <PRE>struct _HTRequest {
2.19 timbl 197:
198: </PRE>The elements of the request structure
199: are as follows.
200: <H3>Set by the caller of HTaccess:</H3>
201: <H4>Conditions of the request itself:</H4>
202: <PRE> HTMethod method;
203:
204: </PRE>An atom for the name of the operation
205: using HTTP <A
206: NAME="z7" HREF="../../Protocols/HTTP/Methods.html">method names</A> .
207: <PRE> HTList * conversions ;
2.20 frystyk 208: </PRE>NULL, or a list of conversions which
2.19 timbl 209: the format manager can do in order
210: to fulfill the request. This is
211: set by the caller of HTAccess. Typically
212: points to a list set up an initialisation
213: time for example by HTInit.
214: <PRE> HTList * encodings; /* allowed content-encodings */
215:
216: </PRE>The list of encodings acceptablein
217: the output stream.
218: <PRE> HTList * languages; /* accepted content-languages */
219:
220: </PRE>The list of (human) language values
221: acceptable in the response
222: <PRE> BOOL (*<A
2.20 frystyk 223: NAME="z9"> callback</A> ) PARAMS((
2.9 timbl 224: struct _HTRequest* request,
225: void *param));
2.19 timbl 226:
227: </PRE>A function to be called back in the
228: event that a file has been saved
229: to disk by HTSaveAndCallBack for
230: example.
231: <PRE> void * context; /* caller data -- HTAccess unaware */
232:
233: </PRE>An arbitrary pointer passed to HTAccess
234: and passed back as a parameter to
235: the <A
2.20 frystyk 236: NAME="z10" HREF="#z9">callback</A> .
2.19 timbl 237: <PRE> HTStream* output_stream;
238:
239: </PRE>NULL in the case of display to the
240: user, or if a specific output stream
241: is required, the stream.
242: <PRE> HTAtom * output_format;
243:
244: </PRE>The output format required, or a
245: generic format such as www/present
246: (present to user).
247: <H4>Information about the requester</H4>
248: <PRE> char * from;
249:
250: </PRE>Email format address of person responible
251: for request
252: <H3>Set by HTAccess</H3>None of the bits below may be looked
253: at by a client application except
254: in the callback routine, when the
255: anchor may be picked out.
256: <PRE> HTParentAnchor* anchor;
257:
258: </PRE>The anchor for the object in question.
2.20 frystyk 259: Set immediately by HTAcesss. Used
2.19 timbl 260: by the protocol and parsing modules.
261: Valid thoughout the access.
262: <PRE> HTChildAnchor * childAnchor; /* For element within the object */
263:
2.31 ! frystyk 264: </PRE>The anchor for the sub object if
2.19 timbl 265: any. The object builder should ensure
266: that htis is selected, highlighted,
267: etc when the object is loaded. NOTE:
268: Set by HTAccess.
269: <PRE> void * using_cache;
270:
271: </PRE>pointer to cache element if cache
272: hit
2.25 luotonen 273: <H3>Error Diagnostics</H3>
274: <PRE>
2.30 frystyk 275: BOOL error_block; /* YES if stream has been used */
2.29 luotonen 276: HTList * error_stack; /* List of errors */
277: HTList * old_error_stack;/* Old list of error messages */
2.25 luotonen 278:
279: </PRE>
2.21 luotonen 280: <H3>Server Side</H3>
281: <PRE>
282: HTAtom * content_type; /* Content-Type: */
2.18 luotonen 283: HTAtom * content_language;/* Language */
284: HTAtom * content_encoding;/* Encoding */
2.16 luotonen 285: int content_length; /* Content-Length: */
2.21 luotonen 286: HTInputSocket * isoc; /* InputSocket object for reading */
2.14 luotonen 287: char * authorization; /* Authorization: field */
288: HTAAScheme scheme; /* Authentication scheme used */
2.19 timbl 289: </PRE>
2.21 luotonen 290: <H3>Client Side</H3>
2.19 timbl 291: <PRE>
2.14 luotonen 292: HTList * valid_schemes; /* Valid auth.schemes */
293: HTAssocList ** scheme_specifics;/* Scheme-specific parameters */
294: char * prot_template; /* WWW-Protection-Template: field */
295: HTAASetup * setup; /* Doc protection info */
296: HTAARealm * realm; /* Password realm */
297: char * dialog_msg; /* Authentication prompt (client) */
298: HTRetryCallbackType
299: retry_callback; /* Called when password entered */
2.10 timbl 300: };
2.9 timbl 301:
2.31 ! frystyk 302: </PRE>
! 303:
! 304: <H2><A NAME="z100">Functions to Manipulate a HTRequest Structure</A></H2>
! 305:
! 306: Just to make things easier especially for clients, here are some functions to
! 307: manipulate the request structure:
! 308:
! 309: <H3>Create blank request</H3>This request has defaults in -- in
2.9 timbl 310: most cases it will need some information
311: added before being passed to HTAccess,
312: but it will work as is for a simple
313: request.
2.14 luotonen 314: <PRE>
315: PUBLIC HTRequest * HTRequest_new NOPARAMS;
2.31 ! frystyk 316: </PRE>
2.14 luotonen 317:
2.31 ! frystyk 318: <H3>Delete request structure</H3>Frees also conversion list hanging
2.19 timbl 319: from req->conversions.
2.14 luotonen 320: <PRE>
321: PUBLIC void HTRequest_delete PARAMS((HTRequest * req));
2.31 ! frystyk 322: </PRE>
1.1 timbl 323:
2.31 ! frystyk 324: <H3>Clear a request structure</H3>
! 325: Clears a request structure so that it can be reused. The only thing that differs from using free/new is that the list of conversions is kept.
! 326: <PRE>
! 327: extern void HTRequest_clear PARAMS((HTRequest * req));
! 328: </PRE>
2.9 timbl 329:
2.5 timbl 330: <H2>Flags which may be set to control
331: this module</H2>
2.22 frystyk 332: <PRE>
2.23 frystyk 333: extern char * HTSaveLocallyDir; /* Dir home for "save locally" files */
334: extern char * HTCacheDir; /* Cache dir, default NULL: no cache */
1.1 timbl 335: extern char * HTClientHost; /* Name or number of telnetting host */
2.27 frystyk 336: extern FILE * HTlogfile; /* File to output one-liners to */
2.7 timbl 337: extern BOOL HTSecure; /* Disable security holes? */
2.28 luotonen 338: extern char * HTImServer; /* If I'm cern_httpd */
2.21 luotonen 339: extern BOOL HTImProxy; /* If I'm cern_httpd as a proxy */
2.23 frystyk 340: extern BOOL HTForceReload; /* Force reload from cache or net */
1.1 timbl 341:
2.5 timbl 342: </PRE>
343: <H2>Load a document from relative name</H2>
344: <H3>On Entry,</H3>
345: <DL>
346: <DT>relative_name
2.6 timbl 347: <DD> The relative address
2.5 timbl 348: of the file to be accessed.
349: <DT>here
2.6 timbl 350: <DD> The anchor of the object being
2.5 timbl 351: searched
2.9 timbl 352: <DT>request->anchor
353: <DD> not filled in yet
2.5 timbl 354: </DL>
355:
356: <H3>On Exit,</H3>
357: <DL>
358: <DT>returns YES
2.6 timbl 359: <DD> Success in opening
2.5 timbl 360: file
361: <DT>NO
2.6 timbl 362: <DD> Failure
2.5 timbl 363: </DL>
1.1 timbl 364:
2.5 timbl 365: <PRE>extern BOOL HTLoadRelative PARAMS((
1.1 timbl 366: CONST char * relative_name,
2.9 timbl 367: HTParentAnchor * here,
368: HTRequest * request));
1.1 timbl 369:
370:
2.5 timbl 371: </PRE>
372: <H2>Load a document from absolute name</H2>
373: <H3>On Entry,</H3>
374: <DL>
375: <DT>addr
2.6 timbl 376: <DD> The absolute address of the
377: document to be accessed.
2.5 timbl 378: <DT>filter
2.6 timbl 379: <DD> if YES, treat document as
380: HTML
2.9 timbl 381: <DT>request->anchor
382: <DD> not filled in yet
2.5 timbl 383: </DL>
1.1 timbl 384:
2.5 timbl 385: <PRE>
386: </PRE>
387: <H3>On Exit,</H3>
388: <PRE>
389: </PRE>
390: <DL>
391: <DT>returns YES
2.6 timbl 392: <DD> Success in opening document
2.5 timbl 393: <DT>NO
2.6 timbl 394: <DD> Failure
2.5 timbl 395: </DL>
1.1 timbl 396:
2.9 timbl 397: <PRE>extern BOOL HTLoadAbsolute PARAMS((CONST char * addr,
398: HTRequest * request));
1.1 timbl 399:
400:
2.5 timbl 401: </PRE>
402: <H2>Load a document from absolute name
403: to a stream</H2>
404: <H3>On Entry,</H3>
405: <DL>
406: <DT>addr
2.6 timbl 407: <DD> The absolute address of the
408: document to be accessed.
2.5 timbl 409: <DT>filter
2.6 timbl 410: <DD> if YES, treat document as
411: HTML
2.9 timbl 412: <DT>request->anchor
413: <DD> not filled in yet
2.5 timbl 414: </DL>
415:
416: <H3>On Exit,</H3>
417: <DL>
418: <DT>returns YES
2.6 timbl 419: <DD> Success in opening document
2.5 timbl 420: <DT>NO
2.6 timbl 421: <DD> Failure
2.5 timbl 422: </DL>
423: Note: This is equivalent to HTLoadDocument
2.9 timbl 424: <PRE>extern BOOL HTLoadToStream PARAMS((
425: CONST char * addr,
426: BOOL filter,
427: HTRequest * request));
1.1 timbl 428:
429:
2.5 timbl 430: </PRE>
431: <H2>Load if necessary, and select an
2.9 timbl 432: anchor</H2>The anchor parameter may be a child
433: anchor. The anchor in the request
434: is set to the parent anchor.
2.5 timbl 435: <H3>On Entry,</H3>
436: <DL>
2.9 timbl 437: <DT>anchor
438: <DD> may be a child or parenet
439: anchor or 0 in which case there is
440: no effect.
441: <DT>request->anchor
442: <DD> Not set
443: yet.
2.5 timbl 444: </DL>
445:
446: <H3>On Exit,</H3>
447: <PRE>
448: </PRE>
449: <DL>
450: <DT>returns YES
2.6 timbl 451: <DD> Success
2.5 timbl 452: <DT>returns NO
2.6 timbl 453: <DD> Failure
2.9 timbl 454: <DT>request->anchor
455: <DD> The parenet anchor.
2.5 timbl 456: </DL>
457:
2.9 timbl 458: <PRE>extern BOOL HTLoadAnchor PARAMS((HTAnchor * a,
459: HTRequest * request));
1.1 timbl 460:
461:
2.5 timbl 462: </PRE>
2.24 luotonen 463:
464: <H2>Load a Document</H2>
465: This is an internal routine, which has an address AND a matching
466: anchor. (The public routines are called with one OR the other.)
467: This is, however, recursively called from file load module to
468: try ftp.
469:
470: <H3>On entry,</H3>
471: request->
472: <DL>
473: <DT> anchor <DD> a parent anchor with fully qualified
474: hypertext reference as its address set
475: <DT> output_format <DD> valid
476: <DT> output_stream <DD> valid on NULL
477: </DL>
478:
479: <H3>On exit,</H3>
480: returns
481: <DL>
482: <DT> <0 <DD> Error has occured.
483: <DT> HT_LOADED <DD> Success
484: <DT> HT_NO_DATA <DD> Success, but no document loaded.
485: (telnet sesssion started etc)
486: </DL>
487:
488: <PRE>
489: PUBLIC int HTLoad PARAMS((HTRequest * request));
490: </PRE>
491:
492:
2.20 frystyk 493: <H2>Bind an anchor to a request structure
494: without loading</H2>The anchor parameter may be a child
495: anchor. The anchor in the request
496: is set to the parent anchor. This
497: is useful in non-interactive mode
498: if no home-anchor is known. Actually
499: the same as HTLoadAnchor(), but without
500: loading
501: <H3>On Entry,</H3>
502: <DL>
503: <DT>anchor
504: <DD> may be a child or parenet
505: anchor or 0 in which case there is
506: no effect.
507: <DT>request->anchor
508: <DD> Not set yet.
509: </DL>
510:
511: <H3>On Exit,</H3>
512: <PRE>
513: </PRE>returns YES Success<P>
514: returns NO Failure <P>
515: request->anchor The parenet anchor.
516: <PRE>
517: extern BOOL HTBindAnchor PARAMS((HTAnchor *anchor, HTRequest *request));
518:
519:
520: </PRE>
2.5 timbl 521: <H2>Make a stream for Saving object back</H2>
522: <H3>On Entry,</H3>
523: <DL>
2.9 timbl 524: <DT>request->anchor
525: <DD> is valid anchor which
526: has previously beeing loaded
2.5 timbl 527: </DL>
528:
529: <H3>On exit,</H3>
530: <DL>
531: <DT>returns
2.6 timbl 532: <DD> 0 if error else a stream
533: to save the object to.
2.5 timbl 534: </DL>
535:
536: <PRE>
537:
2.13 timbl 538: extern HTStream * HTSaveStream PARAMS((HTRequest * request));
1.1 timbl 539:
540:
2.5 timbl 541: </PRE>
542: <H2>Search</H2>Performs a search on word given by
543: the user. Adds the search words to
544: the end of the current address and
545: attempts to open the new address.
546: <H3>On Entry,</H3>
547: <DL>
548: <DT>*keywords
2.6 timbl 549: <DD> space-separated keyword
2.5 timbl 550: list or similar search list
551: <DT>here
2.6 timbl 552: <DD> The anchor of the object being
2.5 timbl 553: searched
554: </DL>
1.1 timbl 555:
2.9 timbl 556: <PRE>extern BOOL HTSearch PARAMS((
557: CONST char * keywords,
558: HTParentAnchor* here,
559: HTRequest * request));
1.1 timbl 560:
561:
2.5 timbl 562: </PRE>
563: <H2>Search Given Indexname</H2>Performs a keyword search on word
564: given by the user. Adds the keyword
565: to the end of the current address
566: and attempts to open the new address.
567: <H3>On Entry,</H3>
568: <DL>
569: <DT>*keywords
2.6 timbl 570: <DD> space-separated keyword
2.5 timbl 571: list or similar search list
572: <DT>*indexname
2.6 timbl 573: <DD> is name of object search
2.5 timbl 574: is to be done on.
575: </DL>
1.1 timbl 576:
2.5 timbl 577: <PRE>extern BOOL HTSearchAbsolute PARAMS((
2.9 timbl 578: CONST char * keywords,
579: CONST char * indexname,
580: HTRequest * request));
1.1 timbl 581:
582:
2.5 timbl 583: </PRE>
2.9 timbl 584: <H2>Register an access method</H2>An access method is defined by an
585: HTProtocol structure which point
586: to the routines for performing the
587: various logical operations on an
588: object: in HTTP terms, GET, PUT,
589: and POST.<P>
590: Each of these routine takes as a
591: parameter a <A
592: NAME="z2" HREF="#z1">request structure</A> containing
593: details ofthe request. When the
594: protocol class routine is called,
595: the anchor elemnt in the request
596: is already valid (made valid by HTAccess).
597: <PRE>typedef struct _HTProtocol {
1.1 timbl 598: char * name;
599:
2.11 timbl 600: int (*load)PARAMS((HTRequest * request));
1.1 timbl 601:
2.11 timbl 602: HTStream* (*saveStream)PARAMS((HTRequest * request));
603:
2.9 timbl 604: HTStream* (*postStream)PARAMS((
605: HTRequest * request,
606: HTParentAnchor* postTo));
1.1 timbl 607:
608: } HTProtocol;
609:
610: extern BOOL HTRegisterProtocol PARAMS((HTProtocol * protocol));
611:
612:
2.5 timbl 613: </PRE>
614: <H2>Generate the anchor for the home
615: page</H2>
616: <PRE>
617: </PRE>As it involves file access, this
618: should only be done once when the
619: program first runs. This is a default
620: algorithm -- browser don't HAVE to
621: use this.
622: <PRE>extern HTParentAnchor * HTHomeAnchor NOPARAMS;
1.1 timbl 623:
2.25 luotonen 624: </PRE>
625:
626: <H2>Error Diagnostics</H2>
627: <PRE>
628:
629: PUBLIC void HTAddError PARAMS((HTRequest * req,
2.26 luotonen 630: CONST char * msg));
2.25 luotonen 631:
632: PUBLIC void HTAddError2 PARAMS((HTRequest * req,
2.26 luotonen 633: CONST char * msg,
634: CONST char * param));
2.25 luotonen 635:
636: PUBLIC void HTAddErrorN PARAMS((HTRequest * req,
2.26 luotonen 637: CONST char * msg,
2.25 luotonen 638: int param));
639:
640: PUBLIC void HTClearErrors PARAMS((HTRequest * req));
641:
642: </PRE>
643:
644: <PRE>
645:
1.1 timbl 646: #endif /* HTACCESS_H */
2.11 timbl 647:
2.25 luotonen 648: </PRE>
649: end of HTAccess
650: </BODY>
2.9 timbl 651: </HTML>
Webmaster