Annotation of parser3/src/targets/apache13/mod_parser3.c, revision 1.1.2.2

1.1.2.1   paf         1: /** @file
                      2: Parser: apache 1.3 module, part, compiled by Apache.
                      3: 
                      4:        Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
                      5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
                      6: */
                      7: 
1.1.2.2 ! paf         8: static const char* IDENT_MOD_PARSER3_C="$Date: 2003/07/23 11:49:07 $";
1.1.2.1   paf         9: 
                     10: #include "httpd.h"
                     11: #include "http_config.h"
                     12: #include "http_core.h"
                     13: #include "http_log.h"
                     14: #include "http_main.h"
                     15: #include "http_protocol.h"
1.1.2.2 ! paf        16: #include "util_script.h"
1.1.2.1   paf        17: #include "ap_md5.h"
1.1.2.2 ! paf        18: 
        !            19: #include "pa_httpd.h"
1.1.2.1   paf        20: 
                     21: /*
                     22: * Declare ourselves so the configuration routines can find and know us.
                     23: * We'll fill it in at the end of the module.
                     24: */
                     25: extern module MODULE_VAR_EXPORT parser3_module;
                     26: 
                     27: /*
                     28: * Locate our directory configuration record for the current request.
                     29: */
                     30: static Parser_module_config *our_dconfig(request_rec *r) {
                     31:        return (Parser_module_config *) 
                     32:                ap_get_module_config(r->per_dir_config, &parser3_module);
                     33: }
                     34: 
                     35: static const char* cmd_parser_config(cmd_parms *cmd, void *mconfig, char *file_spec) {
                     36:        Parser_module_config *cfg = (Parser_module_config *) mconfig;
                     37:        
                     38:        // remember assigned filespec into cfg
                     39:        cfg->parser_config_filespec=file_spec;
                     40:        
                     41:        return NULL;
                     42: }
                     43: static const char* cmd_parser_status_allowed(cmd_parms *cmd, void *mconfig, char *file_spec) {
                     44:        //_asm int 3;
                     45:        Parser_module_config *cfg = (Parser_module_config *) mconfig;
                     46:        
                     47:        cfg->parser_status_allowed=true;
                     48:        
                     49:        return NULL;
                     50: }
                     51: 
                     52: 
                     53: /*--------------------------------------------------------------------------*/
                     54: /*                                                                          */
                     55: /* Now we declare our content handlers, which are invoked when the server   */
                     56: /* encounters a document which our module is supposed to have a chance to   */
                     57: /* see.  (See mod_mime's SetHandler and AddHandler directives, and the      */
                     58: /* mod_info and mod_status examples, for more details.)                     */
                     59: /*                                                                          */
                     60: /* Since content handlers are dumping data directly into the connexion      */
                     61: /* (using the r*() routines, such as rputs() and rprintf()) without         */
                     62: /* intervention by other parts of the server, they need to make             */
                     63: /* sure any accumulated HTTP headers are sent first.  This is done by       */
                     64: /* calling send_http_header().  Otherwise, no header will be sent at all,   */
                     65: /* and the output sent to the client will actually be HTTP-uncompliant.     */
                     66: /*--------------------------------------------------------------------------*/
                     67: /* 
                     68: * Sample content handler.  All this does is display the call list that has
                     69: * been built up so far.
                     70: *
                     71: * The return value instructs the caller concerning what happened and what to
                     72: * do next:
                     73: *  OK ("we did our thing")
                     74: *  DECLINED ("this isn't something with which we want to get involved")
                     75: *  HTTP_mumble ("an error status should be reported")
                     76: */
                     77: 
                     78: 
                     79: /*--------------------------------------------------------------------------*/
                     80: /*                                                                          */
                     81: /* Now let's declare routines for each of the callback phase in order.      */
                     82: /* (That's the order in which they're listed in the callback list, *not     */
                     83: /* the order in which the server calls them!  See the command_rec           */
                     84: /* declaration near the bottom of this file.)  Note that these may be       */
                     85: /* called for situations that don't relate primarily to our function - in   */
                     86: /* other words, the fixup handler shouldn't assume that the request has     */
                     87: /* to do with "example" stuff.                                              */
                     88: /*                                                                          */
                     89: /* With the exception of the content handler, all of our routines will be   */
                     90: /* called for each request, unless an earlier handler from another module   */
                     91: /* aborted the sequence.                                                    */
                     92: /*                                                                          */
                     93: /* Handlers that are declared as "int" can return the following:            */
                     94: /*                                                                          */
                     95: /*  OK          Handler accepted the request and did its thing with it.     */
                     96: /*  DECLINED    Handler took no action.                                     */
                     97: /*  HTTP_mumble Handler looked at request and found it wanting.             */
                     98: /*                                                                          */
                     99: /* What the server does after calling a module handler depends upon the     */
                    100: /* handler's return value.  In all cases, if the handler returns            */
                    101: /* DECLINED, the server will continue to the next module with an handler    */
                    102: /* for the current phase.  However, if the handler return a non-OK,         */
                    103: /* non-DECLINED status, the server aborts the request right there.  If      */
                    104: /* the handler returns OK, the server's next action is phase-specific;      */
                    105: /* see the individual handler comments below for details.                   */
                    106: /*                                                                          */
                    107: /*--------------------------------------------------------------------------*/
1.1.2.2 ! paf       108: 
        !           109: static int parser_handler(request_rec *ar) {
        !           110:        // record clone
        !           111:        struct pa_request_rec lr={
        !           112:                ar,
        !           113:                ar->pool,
        !           114:                ar->header_only,
        !           115:                ar->status,
        !           116:                ar->method,
        !           117:                ar->headers_out,
        !           118:                ar->subprocess_env,
        !           119:                ar->content_type,
        !           120:                ar->uri,
        !           121:                ar->filename,
        !           122:                ar->path_info,
        !           123:                ar->args,
        !           124:                &ar->finfo
        !           125:        };
        !           126: 
        !           127:        // config
        !           128:        Parser_module_config *dcfg=our_dconfig(ar);
        !           129:        
        !           130:        return pa_parser_handler(&lr, dcfg);
        !           131: }
        !           132: 
1.1.2.1   paf       133: /* 
                    134: * This function is called during server initialisation.  Any information
                    135: * that needs to be recorded must be in static cells, since there's no
                    136: * configuration record.
                    137: *
                    138: * There is no return value.
                    139: */
                    140: 
                    141: static void parser_server_init(server_rec *s, pool *p) {
                    142: #if MODULE_MAGIC_NUMBER >= 19980527
                    143:        ap_add_version_component(pa_version());
                    144: #endif 
                    145:        
                    146:        /*
                    147:        * Set up any module cells that ought to be initialised.
                    148:        */
                    149:        pa_setup_module_cells();
                    150: }
                    151: 
                    152: /*
                    153: * This function gets called to create a per-directory configuration
                    154: * record.  This will be called for the "default" server environment, and for
                    155: * each directory for which the parser finds any of our directives applicable.
                    156: * If a directory doesn't have any of our directives involved (i.e., they
                    157: * aren't in the .htaccess file, or a <Location>, <Directory>, or related
                    158: * block), this routine will *not* be called - the configuration for the
                    159: * closest ancestor is used.
                    160: *
                    161: * The return value is a pointer to the created module-specific
                    162: * structure.
                    163: */
                    164: static void *parser_create_dir_config(pool *p, char *dirspec) {
                    165:        //_asm int 3;
                    166:        /*
                    167:        * Allocate the space for our record from the pool supplied.
                    168:        */
                    169:        Parser_module_config *cfg=
                    170:                (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
                    171:                /*
                    172:                * Now fill in the defaults.  If there are any `parent' configuration
                    173:                * records, they'll get merged as part of a separate callback.
                    174:        */
                    175:        
                    176:        return (void *) cfg;
                    177: }
                    178: 
                    179: /*
                    180: * This function gets called to merge two per-directory configuration
                    181: * records.  This is typically done to cope with things like .htaccess files
                    182: * or <Location> directives for directories that are beneath one for which a
                    183: * configuration record was already created.  The routine has the
                    184: * responsibility of creating a new record and merging the contents of the
                    185: * other two into it appropriately.  If the module doesn't declare a merge
                    186: * routine, the record for the closest ancestor location (that has one) is
                    187: * used exclusively.
                    188: *
                    189: * The routine MUST NOT modify any of its arguments!
                    190: *
                    191: * The return value is a pointer to the created module-specific structure
                    192: * containing the merged values.
                    193: 
                    194:  20011126 paf: noticed, that this is called even on virtual root merge with something "parent",
                    195:  while thought that that is part of merge_server...
                    196:  
                    197: */
                    198: static void *parser_merge_dir_config(pool *p, void *parent_conf,
                    199:                                     void *newloc_conf) {
                    200:        //_asm int 3;
                    201:        Parser_module_config *merged_config = 
                    202:                (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
                    203:        Parser_module_config *pconf = (Parser_module_config *) parent_conf;
                    204:        Parser_module_config *nconf = (Parser_module_config *) newloc_conf;
                    205:        
                    206:        merged_config->parser_config_filespec = ap_pstrdup(p, nconf->parser_config_filespec?
                    207:                nconf->parser_config_filespec:pconf->parser_config_filespec);
                    208:        merged_config->parser_status_allowed=
                    209:                pconf->parser_status_allowed ||
                    210:                nconf->parser_status_allowed;
                    211:        
                    212:                /*
                    213:                * Some things get copied directly from the more-specific record, rather
                    214:                * than getting merged.
                    215:        */
                    216:        
                    217:        return (void *) merged_config;
                    218: }
                    219: 
                    220: /*
                    221: * This function gets called to create a per-server configuration
                    222: * record.  It will always be called for the "default" server.
                    223: *
                    224: * The return value is a pointer to the created module-specific
                    225: * structure.
                    226: */
                    227: static void *parser_create_server_config(pool *p, server_rec *s) {
                    228:        //_asm int 3;
                    229:        /*
                    230:        * As with the parser_create_dir_config() routine, we allocate and fill
                    231:        * in an empty record.
                    232:        */
                    233:        Parser_module_config *cfg=
                    234:                (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
                    235:        
                    236:        return (void *) cfg;
                    237: }
                    238: 
                    239: /*
                    240: * This function gets called to merge two per-server configuration
                    241: * records.  This is typically done to cope with things like virtual hosts and
                    242: * the default server configuration  The routine has the responsibility of
                    243: * creating a new record and merging the contents of the other two into it
                    244: * appropriately.  If the module doesn't declare a merge routine, the more
                    245: * specific existing record is used exclusively.
                    246: *
                    247: * The routine MUST NOT modify any of its arguments!
                    248: *
                    249: * The return value is a pointer to the created module-specific structure
                    250: * containing the merged values.
                    251: */
                    252: static void *parser_merge_server_config(pool *p, void *server1_conf,
                    253:                                        void *server2_conf)
                    254: {
                    255:        //_asm int 3;
                    256:        
                    257:        Parser_module_config *merged_config = 
                    258:                (Parser_module_config *) ap_pcalloc(p, sizeof(Parser_module_config));
                    259:        Parser_module_config *s1conf = (Parser_module_config *) server1_conf;
                    260:        Parser_module_config *s2conf = (Parser_module_config *) server2_conf;
                    261:        
                    262:        /*
                    263:        * Our inheritance rules are our own, and part of our module's semantics.
                    264:        * Basically, just note whence we came.
                    265:        */
                    266:        merged_config->parser_config_filespec = ap_pstrdup(p, s2conf->parser_config_filespec?
                    267:                s2conf->parser_config_filespec:s1conf->parser_config_filespec);
                    268:        merged_config->parser_status_allowed=
                    269:                s1conf->parser_status_allowed || 
                    270:                s2conf->parser_status_allowed;
                    271:        
                    272:        return (void *) merged_config;
                    273: }
                    274: 
                    275: /*
                    276: * This routine gives our module an opportunity to translate the URI into an
                    277: * actual filename.  If we don't do anything special, the server's default
                    278: * rules (Alias directives and the like) will continue to be followed.
                    279: *
                    280: * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, no
                    281: * further modules are called for this phase.
                    282: */
                    283: static int parser_translate_handler(request_rec *r) {
                    284:        Parser_module_config *cfg=our_dconfig(r);
                    285:        return DECLINED;
                    286: }
                    287: 
                    288: /*
                    289: * This routine is called to check the authentication information sent with
                    290: * the request (such as looking up the user in a database and verifying that
                    291: * the [encrypted] password sent matches the one in the database).
                    292: *
                    293: * The return value is OK, DECLINED, or some HTTP_mumble error (typically
                    294: * HTTP_UNAUTHORIZED).  If we return OK, no other modules are given a chance
                    295: * at the request during this phase.
                    296: */
                    297: static int parser_check_user_id(request_rec *r) {
                    298:        Parser_module_config *cfg=our_dconfig(r);
                    299:        return DECLINED;
                    300: }
                    301: 
                    302: /*
                    303: * This routine is called to check to see if the resource being requested
                    304: * requires authorisation.
                    305: *
                    306: * The return value is OK, DECLINED, or HTTP_mumble.  If we return OK, no
                    307: * other modules are called during this phase.
                    308: *
                    309: * If *all* modules return DECLINED, the request is aborted with a server
                    310: * error.
                    311: */
                    312: static int parser_auth_checker(request_rec *r) {
                    313:        Parser_module_config *cfg=our_dconfig(r);
                    314:        return DECLINED;
                    315: }
                    316: 
                    317: /*
                    318: * This routine is called to check for any module-specific restrictions placed
                    319: * upon the requested resource.  (See the mod_access module for an example.)
                    320: *
                    321: * The return value is OK, DECLINED, or HTTP_mumble.  All modules with an
                    322: * handler for this phase are called regardless of whether their predecessors
                    323: * return OK or DECLINED.  The first one to return any other status, however,
                    324: * will abort the sequence (and the request) as usual.
                    325: */
                    326: static int parser_access_checker(request_rec *r) {
                    327:        
                    328:        Parser_module_config *cfg=our_dconfig(r);
                    329:        return DECLINED;
                    330: }
                    331: 
                    332: /*--------------------------------------------------------------------------*/
                    333: /*                                                                          */
                    334: /* All of the routines have been declared now.  Here's the list of          */
                    335: /* directives specific to our module, and information about where they      */
                    336: /* may appear and how the command parser should pass them to us for         */
                    337: /* processing.  Note that care must be taken to ensure that there are NO    */
                    338: /* collisions of directive names between modules.                           */
                    339: /*                                                                          */
                    340: /*--------------------------------------------------------------------------*/
                    341: /* 
                    342: * List of directives specific to our module.
                    343: */
                    344: static const command_rec parser_cmds[] =
                    345: {
                    346:        {
                    347:                "ParserConfig",              /* directive name */
                    348:                        (const char* (*)(void))((void *)cmd_parser_config), // config action routine
                    349:                        (void*)0,                   /* argument to include in call */
                    350:                        (int)(OR_OPTIONS),             /* where available */
                    351:                        TAKE1,                /* arguments */
                    352:                        "Parser config filespec" // directive description
                    353:        },
                    354:        {
                    355:                "ParserStatusAllowed",              /* directive name */
                    356:                        (const char* (*)(void))((void *)cmd_parser_status_allowed), // config action routine
                    357:                        (void*)0,                   /* argument to include in call */
                    358:                        (int)(ACCESS_CONF),             /* where available */
                    359:                        NO_ARGS,                /* arguments */
                    360:                        "Parser status class can be used" // directive description
                    361:        },
                    362:        {NULL}
                    363: };
                    364: 
                    365: /*--------------------------------------------------------------------------*/
                    366: /*                                                                          */
                    367: /* Now the list of content handlers available from this module.             */
                    368: /*                                                                          */
                    369: /*--------------------------------------------------------------------------*/
                    370: /* 
                    371: * List of content handlers our module supplies.  Each handler is defined by
                    372: * two parts: a name by which it can be referenced (such as by
                    373: * {Add,Set}Handler), and the actual routine name.  The list is terminated by
                    374: * a NULL block, since it can be of variable length.
                    375: *
                    376: * Note that content-handlers are invoked on a most-specific to least-specific
                    377: * basis; that is, a handler that is declared for "text/plain" will be
                    378: * invoked before one that was declared for "text / *".  Note also that
                    379: * if a content-handler returns anything except DECLINED, no other
                    380: * content-handlers will be called.
                    381: */
                    382: static const handler_rec parser_handlers[] =
                    383: {
                    384:        {"parser3-handler", parser_handler},
                    385:        {NULL}
                    386: };
                    387: 
                    388: /*--------------------------------------------------------------------------*/
                    389: /*                                                                          */
                    390: /* Finally, the list of callback routines and data structures that          */
                    391: /* provide the hooks into our module from the other parts of the server.    */
                    392: /*                                                                          */
                    393: /*--------------------------------------------------------------------------*/
                    394: /* 
                    395: * Module definition for configuration.  If a particular callback is not
                    396: * needed, replace its routine name below with the word NULL.
                    397: *
                    398: * The number in brackets indicates the order in which the routine is called
                    399: * during request processing.  Note that not all routines are necessarily
                    400: * called (such as if a resource doesn't have access restrictions).
                    401: */
                    402: module MODULE_VAR_EXPORT parser3_module =
                    403: {
                    404:        STANDARD_MODULE_STUFF,
                    405:        parser_server_init,          /* module initializer */
                    406:        parser_create_dir_config,    /* per-directory config creator */
                    407:        parser_merge_dir_config,     /* dir config merger */
                    408:        parser_create_server_config, /* server config creator */
                    409:        parser_merge_server_config,  /* server config merger */
                    410:        parser_cmds,                 /* command table */
                    411:        parser_handlers,             /* [9] list of handlers */
                    412:        parser_translate_handler,    /* [2] filename-to-URI translation */
                    413:        parser_check_user_id,        /* [5] check/validate user_id */
                    414:        parser_auth_checker,         /* [6] check user_id is valid *here* */
                    415:        parser_access_checker,       /* [4] check access by host address */
                    416:        0,                           /* [7] MIME type checker/setter */
                    417:        0,                           /* [8] fixups */
                    418:        0                            /* [10] logger */
                    419: };
                    420: 
                    421: #if defined(_MSC_VER)
                    422: #      define APACHE_WIN32_SRC "/parser3project/win32/apache13/src"
                    423: #      ifdef _DEBUG
                    424: #              pragma comment(lib, APACHE_WIN32_SRC "/CoreD/ApacheCore.lib")
                    425: #      else
                    426: #              pragma comment(lib, APACHE_WIN32_SRC "/CoreR/ApacheCore.lib")
                    427: #      endif
                    428: #endif
1.1.2.2 ! paf       429: 
        !           430: 
        !           431: // interface to C++
        !           432: 
        !           433: #define        PA_APLOG_EMERG  0       /* system is unusable */
        !           434: #define        PA_APLOG_ALERT  1       /* action must be taken immediately */
        !           435: #define        PA_APLOG_CRIT   2       /* critical conditions */
        !           436: #define        PA_APLOG_ERR    3       /* error conditions */
        !           437: #define        PA_APLOG_WARNING        4       /* warning conditions */
        !           438: #define        PA_APLOG_NOTICE 5       /* normal but significant condition */
        !           439: #define        PA_APLOG_INFO   6       /* informational */
        !           440: #define        PA_APLOG_DEBUG  7       /* debug-level messages */
        !           441: 
        !           442: #define        PA_APLOG_LEVELMASK      7       /* mask off the level value */
        !           443: 
        !           444: #define PA_APLOG_NOERRNO               (PA_APLOG_LEVELMASK + 1)
        !           445: 
        !           446: #define PA_APLOG_MARK  __FILE__,__LINE__
        !           447: 
        !           448: void pa_ap_log_rerror(const char *file, int line, int level,
        !           449:                      const pa_request_rec *s, const char *fmt, ...) {
        !           450:        va_list l;
        !           451:        va_start(l, fmt); 
        !           452:        const char* str=va_arg(l, const char*);
        !           453:        va_end(l); 
        !           454: 
        !           455:        ap_log_rerror(file, line, level,
        !           456:                      (request_rec*)s->real_request_rec, "%s", str);
        !           457: }
        !           458: 
        !           459: 
        !           460: void pa_ap_log_error(const char *file, int line, int level,
        !           461:                     const pa_server_rec *s, const char *fmt, ...) {
        !           462:        va_list l;
        !           463:        va_start(l, fmt); 
        !           464:        const char* str=va_arg(l, const char*);
        !           465:        va_end(l); 
        !           466: 
        !           467:        ap_log_error(file, line, level,
        !           468:                      (server_rec*)s, "%s", str);
        !           469: }
        !           470: 
        !           471: // ap_alloc.h
        !           472: 
        !           473: const char * pa_ap_table_get(const pa_table *, const char *);
        !           474: void pa_ap_table_addn(pa_table *, const char *name, const char *val);
        !           475: 
        !           476: int pa_ap_table_size(const pa_table *);
        !           477: 
        !           478: void pa_ap_table_do(int (*comp) (void *, const char *, const char *), 
        !           479:                                     void *rec, const pa_table *t,...);
        !           480: 
        !           481: char * pa_ap_pstrdup(pa_pool *, const char *s);
        !           482: 
        !           483: // http_protocol.h
        !           484: 
        !           485: /* Possible values for request_rec.read_body (set by handling module):
        !           486:  *    REQUEST_NO_BODY          Send 413 error if message has any body
        !           487:  *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
        !           488:  *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
        !           489:  *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
        !           490:  */
        !           491: #define PA_REQUEST_NO_BODY          0
        !           492: #define PA_REQUEST_CHUNKED_ERROR    1
        !           493: #define PA_REQUEST_CHUNKED_DECHUNK  2
        !           494: #define PA_REQUEST_CHUNKED_PASS     3
        !           495: 
        !           496: int pa_ap_setup_client_block(pa_request_rec *r, int read_policy);
        !           497: int pa_ap_should_client_block(pa_request_rec *r);
        !           498: long pa_ap_get_client_block(pa_request_rec *r, char *buffer, int bufsiz);
        !           499: void pa_ap_send_http_header(pa_request_rec *l);
        !           500: int pa_ap_rwrite(const void *buf, int nbyte, pa_request_rec *r);
        !           501: 
        !           502: 
        !           503: // http_main.h
        !           504: 
        !           505: void pa_ap_hard_timeout(char *, pa_request_rec *);
        !           506: void pa_ap_reset_timeout(pa_request_rec *);
        !           507: void pa_ap_kill_timeout(pa_request_rec *);
        !           508: 
        !           509: 
        !           510: // util_script.h
        !           511: 
        !           512: void pa_ap_add_cgi_vars(pa_request_rec *r);
        !           513: void pa_ap_add_common_vars(pa_request_rec *r);
        !           514: 
        !           515: // httpd.h
        !           516: 
        !           517: #define PA_HTTP_NOT_FOUND                     404
        !           518: #define PA_OK 0                        /* Module has handled this stage. */
        !           519: 
        !           520: 
        !           521: // ap_md5.h
        !           522: 
        !           523: void pa_MD5Init(AP_MD5_CTX *context) { ap_MD5Init((AP_MD5_CTX*)context); }
        !           524: void pa_MD5Update(AP_MD5_CTX *context, const unsigned char *input,
        !           525:                              unsigned int inputLen) { ap_MD5Update((AP_MD5_CTX *)context, input, inputLen); }
        !           526: void pa_MD5Final(unsigned char digest[MD5_DIGESTSIZE],
        !           527:                             AP_MD5_CTX *context) { ap_MD5Final(digest, (AP_MD5_CTX *)context); }
        !           528: void pa_MD5Encode(const unsigned char *password,
        !           529:                              const unsigned char *salt,
        !           530:                              char *result, size_t nbytes) { ap_MD5Encode(password, salt, result, nbytes); }
        !           531: void pa_to64(char *s, unsigned long v, int n) { ap_to64(s, v, n); }
        !           532: 
        !           533: 
        !           534: // signal.h
        !           535: 
        !           536: #define PA_SIGPIPE 1 /* must translate to real one */
        !           537: #define PA_SIG_IGN (void (__cdecl *)(int))1           /* must translate to real one */
        !           538: 
        !           539: void (*pa_signal (int sig, void (*disp)(int)))(int);
        !           540: 
        !           541: 
        !           542: 
        !           543: 

E-mail: