Annotation of embedaddon/libpdel/http/test/main.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (c) 2001-2002 Packet Design, LLC.
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Subject to the following obligations and disclaimer of warranty,
        !             7:  * use and redistribution of this software, in source or object code
        !             8:  * forms, with or without modifications are expressly permitted by
        !             9:  * Packet Design; provided, however, that:
        !            10:  * 
        !            11:  *    (i)  Any and all reproductions of the source or object code
        !            12:  *         must include the copyright notice above and the following
        !            13:  *         disclaimer of warranties; and
        !            14:  *    (ii) No rights are granted, in any manner or form, to use
        !            15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
        !            16:  *         on advertising, endorsements, or otherwise except as such
        !            17:  *         appears in the above copyright notice or in the software.
        !            18:  * 
        !            19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
        !            20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
        !            21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
        !            22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
        !            23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
        !            24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
        !            25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
        !            26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
        !            27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
        !            28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
        !            29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
        !            30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
        !            31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
        !            32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
        !            33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
        !            35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
        !            36:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            37:  *
        !            38:  * Author: Archie Cobbs <archie@freebsd.org>
        !            39:  */
        !            40: 
        !            41: #include <sys/stat.h>
        !            42: #include <sys/param.h>
        !            43: 
        !            44: #include <stdio.h>
        !            45: #include <stdlib.h>
        !            46: #include <signal.h>
        !            47: #include <stdarg.h>
        !            48: #include <string.h>
        !            49: #include <unistd.h>
        !            50: #include <errno.h>
        !            51: #include <assert.h>
        !            52: #include <netdb.h>
        !            53: #include <err.h>
        !            54: #include <regex.h>
        !            55: #include <pthread.h>
        !            56: 
        !            57: #include <netinet/in_systm.h>
        !            58: #include <netinet/in.h>
        !            59: #include <arpa/inet.h>
        !            60: 
        !            61: #include <openssl/ssl.h>
        !            62: 
        !            63: #include <pdel/structs/structs.h>
        !            64: #include <pdel/structs/type/array.h>
        !            65: 
        !            66: #include <pdel/tmpl/tmpl.h>
        !            67: #include <pdel/util/typed_mem.h>
        !            68: #include <pdel/util/pevent.h>
        !            69: 
        !            70: #include <pdel/http/http_defs.h>
        !            71: #include <pdel/http/http_server.h>
        !            72: #include <pdel/http/http_servlet.h>
        !            73: #include <pdel/http/servlet/tmpl.h>
        !            74: #include <pdel/http/servlet/file.h>
        !            75: #include <pdel/http/servlet/basicauth.h>
        !            76: #include <pdel/http/servlet/redirect.h>
        !            77: #include <pdel/http/servlet/cookieauth.h>
        !            78: 
        !            79: #define DEMO_MEM_TYPE          "demo"
        !            80: #define DEMO_COOKIE_NAME       "demo_cookie"
        !            81: #define TMPL_MEM_TYPE          "tmpl"
        !            82: #define NUM_IN_CACHE           2
        !            83: #define CACHE_TIMEOUT_SECS     10
        !            84: #define NUM_CACHE_LOOP         10
        !            85: #define PATH_KERNEL            "/kernel"
        !            86: 
        !            87: #ifndef MIN
        !            88: #define MIN(a, b)      ((a) > (b) ? (a) : (b))
        !            89: #endif
        !            90: 
        !            91: /*
        !            92:  * Servlets
        !            93:  */
        !            94: static struct  http_servlet *demo_servlet_create(void);
        !            95: static struct  http_servlet *cgi_servlet_create(void);
        !            96: static struct  http_servlet *getkernel_servlet_create(void);
        !            97: 
        !            98: /*
        !            99:  * Internal functions
        !           100:  */
        !           101: 
        !           102: static http_logger_t           demo_logger;
        !           103: 
        !           104: static tmpl_handler_t          demo_tmpl_handler;
        !           105: static tmpl_errfmtr_t          demo_tmpl_errfmtr;
        !           106: 
        !           107: static http_servlet_basicauth_t        demo_basicauth;
        !           108: 
        !           109: static http_servlet_cookieauth_reqd_t  demo_auth_reqd;
        !           110: 
        !           111: static void    demo_file_upload(struct http_request *req,
        !           112:                        struct http_response *resp, FILE *op);
        !           113: static int     demo_client(struct pevent_ctx *ctx, int nurls,
        !           114:                        char **urls, int count);
        !           115: 
        !           116: /* SSL typed_mem(3) wrappers */
        !           117: static void    *ssl_malloc(size_t size);
        !           118: static void    *ssl_realloc(void *mem, size_t size);
        !           119: static void    ssl_free(void *mem);
        !           120: 
        !           121: static void    usage(void);
        !           122: 
        !           123: /*
        !           124:  * Internal variables
        !           125:  */
        !           126: 
        !           127: /* SSL info */
        !           128: static const struct http_server_ssl ssl_info = {
        !           129:        "demo.crt",                     /* SSL x509 certificate file */
        !           130:        "demo.key",                     /* SSL RSA private key file */
        !           131:        NULL                            /* no password for private key needed */
        !           132: };
        !           133: 
        !           134: static const   char *redirect_url;
        !           135: static const   struct in_addr zero_ip;
        !           136: static pid_t   main_pid;
        !           137: 
        !           138: static const   u_char demo_id[] = { 'd', 'e', 'm', 'o' };
        !           139: 
        !           140: static const   char *vhost = NULL;
        !           141: static const   struct http_server_ssl *ssl = NULL;
        !           142: static int     port = 0;
        !           143: 
        !           144: static struct  http_servlet *cookieauth_servlet;
        !           145: 
        !           146: /* Info for "demo.tmpl" template servlet */
        !           147: static struct http_servlet_tmpl_info tmpl_servlet_info = {
        !           148:        "demo.tmpl",                    /* pathname of template file */
        !           149:        NULL,                           /* guess the mime type for me */
        !           150:        NULL,                           /* guess the mime encoding for me */
        !           151:        demo_logger,                    /* error logging routine */
        !           152:        {                               /* info required by tmpl library */
        !           153:                TMPL_SKIP_NL_WHITE,             /* flags for tmpl_execute() */
        !           154:                TMPL_MEM_TYPE,                  /* tmpl string typed mem type */
        !           155:                demo_tmpl_handler,              /* handler for custom @funcs */
        !           156:                demo_tmpl_errfmtr,              /* handler for errors */
        !           157:                NULL,                           /* opaque user cookie */
        !           158:        }
        !           159: };
        !           160: 
        !           161: /* Info for "logon.tmpl" template servlet */
        !           162: static struct http_servlet_tmpl_info logon_servlet_info = {
        !           163:        "logon.tmpl",                   /* pathname of template file */
        !           164:        NULL,                           /* guess the mime type for me */
        !           165:        NULL,                           /* guess the mime encoding for me */
        !           166:        demo_logger,                    /* error logging routine */
        !           167:        {                               /* info required by tmpl library */
        !           168:                TMPL_SKIP_NL_WHITE,             /* flags for tmpl_execute() */
        !           169:                TMPL_MEM_TYPE,                  /* tmpl string typed mem type */
        !           170:                demo_tmpl_handler,              /* handler for custom @funcs */
        !           171:                demo_tmpl_errfmtr,              /* handler for errors */
        !           172:                NULL,                           /* opaque user cookie */
        !           173:        }
        !           174: };
        !           175: 
        !           176: /* Info for "vhost.tmpl" template servlet */
        !           177: static struct http_servlet_tmpl_info vhost_servlet_info = {
        !           178:        "vhost.tmpl",                   /* pathname of template file */
        !           179:        NULL,                           /* guess the mime type for me */
        !           180:        NULL,                           /* guess the mime encoding for me */
        !           181:        demo_logger,                    /* error logging routine */
        !           182:        {                               /* info required by tmpl library */
        !           183:                TMPL_SKIP_NL_WHITE,             /* flags for tmpl_execute() */
        !           184:                TMPL_MEM_TYPE,                  /* tmpl string typed mem type */
        !           185:                demo_tmpl_handler,              /* handler for custom @funcs */
        !           186:                demo_tmpl_errfmtr,              /* handler for errors */
        !           187:                NULL,                           /* opaque user cookie */
        !           188:        }
        !           189: };
        !           190: 
        !           191: /* Info for BIND docs file servlet */
        !           192: static struct http_servlet_file_info bind_servlet_info = {
        !           193:        "/usr/share/doc/bind/html",     /* document root for this servlet */
        !           194:        0,                              /* don't allow escape from docroot */
        !           195:        NULL,                           /* derive filename from URL */
        !           196:        "/file",                        /* URL prefix to strip from pathname */
        !           197:        NULL,                           /* guess the mime type for me */
        !           198:        NULL,                           /* guess the mime encoding for me */
        !           199:        demo_logger,                    /* error logging routine */
        !           200:        NULL,                           /* don't hide any files */
        !           201:        { }                             /* don't support templates */
        !           202: };
        !           203: 
        !           204: /*
        !           205:  * Start a HTTP server.
        !           206:  */
        !           207: int
        !           208: main(int argc, char **argv)
        !           209: {
        !           210:        struct pevent_ctx *ctx;
        !           211:        char hostname[255] = { '\0' };
        !           212:        struct http_servlet *servlet;
        !           213:        struct http_server *server;
        !           214:        int do_client = 0;
        !           215:        sigset_t sigs;
        !           216:        int count = 1;
        !           217:        int sig;
        !           218:        int ret;
        !           219:        int ch;
        !           220: 
        !           221:        /* Parse command line arguments */
        !           222:        while ((ch = getopt(argc, argv, "sp:c:r:h:v:")) != -1) {
        !           223:                switch (ch) {
        !           224:                case 'c':
        !           225:                        count = atoi(optarg);
        !           226:                        break;
        !           227:                case 'h':
        !           228:                        snprintf(hostname, sizeof(hostname), "%s", optarg);
        !           229:                        break;
        !           230:                case 's':
        !           231:                        ssl = &ssl_info;
        !           232:                        break;
        !           233:                case 'p':
        !           234:                        port = atoi(optarg);
        !           235:                        break;
        !           236:                case 'r':
        !           237:                        redirect_url = optarg;
        !           238:                        break;
        !           239:                case 'v':
        !           240:                        vhost = optarg;
        !           241:                        break;
        !           242:                default:
        !           243:                        usage();
        !           244:                }
        !           245:        }
        !           246:        argc -= optind;
        !           247:        argv += optind;
        !           248:        switch (argc) {
        !           249:        default:
        !           250:                do_client = 1;
        !           251:                break;
        !           252:        case 0:
        !           253:                break;
        !           254:        }
        !           255:        if (port == 0)
        !           256:                port = (ssl != NULL) ? 443 : 80;
        !           257:        if (*hostname == '\0') {
        !           258:                if (gethostname(hostname, sizeof(hostname)) == -1)
        !           259:                        err(1, "gethostname");
        !           260:                hostname[sizeof(hostname) - 1] = '\0';
        !           261:        }
        !           262: 
        !           263:        /* Make OpenSSL use our malloc/free wrappers */
        !           264:        if (ssl != NULL) {
        !           265:                ret = CRYPTO_set_mem_functions(ssl_malloc,
        !           266:                    ssl_realloc, ssl_free);
        !           267:                assert(ret);
        !           268:                ret = CRYPTO_set_locked_mem_functions(ssl_malloc, ssl_free);
        !           269:                assert(ret);
        !           270:        }
        !           271:        main_pid = getpid();
        !           272: 
        !           273:        /* Enable typed memory */
        !           274:        if (typed_mem_enable() == -1)
        !           275:                err(1, "typed_mem_enable");
        !           276: 
        !           277:        /* Block SIGPIPE */
        !           278:        (void)signal(SIGPIPE, SIG_IGN);
        !           279: 
        !           280:        /* Get event context */
        !           281:        if ((ctx = pevent_ctx_create("demo_server.ctx", NULL)) == NULL)
        !           282:                err(1, "pevent_ctx_create");
        !           283: 
        !           284:        /* If client mode, do that */
        !           285:        if (do_client) {
        !           286:                demo_client(ctx, argc, argv, count);
        !           287:                goto shutdown;
        !           288:        }
        !           289: 
        !           290:        /* Start HTTP server */
        !           291:        printf("demo_server: starting http server on port %d, SSL %sabled\n",
        !           292:            port, ssl ? "en" : "dis");
        !           293:        if ((server = http_server_start(ctx, zero_ip,
        !           294:            port, ssl, "Demo/1.0", demo_logger)) == NULL)
        !           295:                err(1, "http_server_start");
        !           296: 
        !           297:        /* Register default virtual host servlet if vhost defined */
        !           298:        if (vhost != NULL) {
        !           299:                /* Register "vhost.tmpl" servlet */
        !           300:                if ((servlet = http_servlet_tmpl_create(
        !           301:                    &vhost_servlet_info)) == NULL)
        !           302:                        err(1, "http_servlet_tmpl_create");
        !           303:                if (http_server_register_servlet(server,
        !           304:                    servlet, NULL, "^/", 0) == -1)
        !           305:                        err(1, "http_server_register_servlet");
        !           306:        }
        !           307: 
        !           308:        /* Register redirect servlet */
        !           309:        if (redirect_url != NULL) {
        !           310:                if ((servlet = http_servlet_redirect_create(redirect_url,
        !           311:                    HTTP_SERVLET_REDIRECT_NO_APPEND)) == NULL)
        !           312:                        err(1, "redirect_servlet_create");
        !           313:                if (http_server_register_servlet(server,
        !           314:                    servlet, vhost, "^/redirect", 0) == -1)
        !           315:                        err(1, "http_server_register_servlet");
        !           316:        }
        !           317: 
        !           318:        /* Register cookie auth servlet */
        !           319:        {
        !           320:                char logurl[128];
        !           321: 
        !           322:                if ((ssl && port == 443) || (!ssl && port == 80)) {
        !           323:                        snprintf(logurl, sizeof(logurl),
        !           324:                            "http%s://%s/logon", ssl ? "s" : "", hostname);
        !           325:                } else {
        !           326:                        snprintf(logurl, sizeof(logurl),
        !           327:                            "http%s://%s:%u/logon", ssl ? "s" : "",
        !           328:                            hostname, port);
        !           329:                }
        !           330:                if ((cookieauth_servlet = http_servlet_cookieauth_create(
        !           331:                    logurl, HTTP_SERVLET_REDIRECT_APPEND_URL,
        !           332:                    demo_auth_reqd, NULL, NULL, "demo.key", demo_id,
        !           333:                    sizeof(demo_id), DEMO_COOKIE_NAME)) == NULL)
        !           334:                        err(1, "http_servlet_cookieauth_create");
        !           335:                if (http_server_register_servlet(server,
        !           336:                    cookieauth_servlet, vhost, "^/.*", -20) == -1)
        !           337:                        err(1, "http_server_register_servlet");
        !           338:        }
        !           339: 
        !           340:        /* Register logon page */
        !           341:        if ((servlet = http_servlet_tmpl_create(&logon_servlet_info)) == NULL)
        !           342:                err(1, "http_servlet_tmpl_create");
        !           343:        if (http_server_register_servlet(server,
        !           344:            servlet, vhost, "^/logon$", 0) == -1)
        !           345:                err(1, "http_server_register_servlet");
        !           346: 
        !           347:        /* Register demo servlet */
        !           348:        if ((servlet = demo_servlet_create()) == NULL)
        !           349:                err(1, "demo_servlet_create");
        !           350:        if (http_server_register_servlet(server,
        !           351:            servlet, vhost, "^/$", 0) == -1)
        !           352:                err(1, "http_server_register_servlet");
        !           353: 
        !           354:        /* Register "demo.tmpl" servlet */
        !           355:        if ((servlet = http_servlet_tmpl_create(&tmpl_servlet_info)) == NULL)
        !           356:                err(1, "http_servlet_tmpl_create");
        !           357:        if (http_server_register_servlet(server,
        !           358:            servlet, vhost, "^/tmpl$", 0) == -1)
        !           359:                err(1, "http_server_register_servlet");
        !           360: 
        !           361:        /* Register authorization servlet */
        !           362:        if ((servlet = http_servlet_basicauth_create(
        !           363:            demo_basicauth, NULL, NULL)) == NULL)
        !           364:                err(1, "http_servlet_basicauth_create");
        !           365:        if (http_server_register_servlet(server,
        !           366:            servlet, vhost, "^/[^l].*$", -10) == -1)
        !           367:                err(1, "http_server_register_servlet");
        !           368: 
        !           369:        /* Register BIND docs servlet */
        !           370:        if ((servlet = http_servlet_file_create(&bind_servlet_info)) == NULL)
        !           371:                err(1, "http_servlet_file_create");
        !           372:        if (http_server_register_servlet(server,
        !           373:            servlet, vhost, "^/file", 0) == -1)
        !           374:                err(1, "http_server_register_servlet");
        !           375: 
        !           376:        /* Register CGI servlet, at two different URLs */
        !           377:        if ((servlet = cgi_servlet_create()) == NULL)
        !           378:                err(1, "cgi_servlet_create");
        !           379:        if (http_server_register_servlet(server,
        !           380:            servlet, vhost, "^/cgi/get$", 0) == -1)
        !           381:                err(1, "http_server_register_servlet");
        !           382:        if ((servlet = cgi_servlet_create()) == NULL)
        !           383:                err(1, "cgi_servlet_create");
        !           384:        if (http_server_register_servlet(server,
        !           385:            servlet, vhost, "^/cgi/post$", 0) == -1)
        !           386:                err(1, "http_server_register_servlet");
        !           387: 
        !           388:        /* Register kernel servlet */
        !           389:        if ((servlet = getkernel_servlet_create()) == NULL)
        !           390:                err(1, "getkernel_servlet_create");
        !           391:        if (http_server_register_servlet(server,
        !           392:            servlet, vhost, "^/kernel", 0) == -1)
        !           393:                err(1, "http_server_register_servlet");
        !           394: 
        !           395:        /* Wait for interrupt */
        !           396:        sigemptyset(&sigs);
        !           397:        sigaddset(&sigs, SIGINT);
        !           398:        sigaddset(&sigs, SIGTERM);
        !           399:        if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1)
        !           400:                err(1, "sigprocmask");
        !           401:        if (sigwait(&sigs, &sig) == -1)
        !           402:                err(1, "sigwait");
        !           403: 
        !           404:        /* Shut down server */
        !           405:        printf("Rec'd signal %d, shutting down http server...\n", sig);
        !           406:        http_server_stop(&server);
        !           407: 
        !           408: shutdown:
        !           409:        /* Destroy event context */
        !           410:        pevent_ctx_destroy(&ctx);
        !           411:        usleep(100000);
        !           412: 
        !           413:        /* Done */
        !           414:        printf("Done. Displaying unfreed memory...\n");
        !           415: 
        !           416:        /* Show memory usage */
        !           417:        typed_mem_dump(stdout);
        !           418:        return (0);
        !           419: }
        !           420: 
        !           421: /***********************************************************************
        !           422:                        SUPPORT ROUTINES
        !           423: ***********************************************************************/
        !           424: 
        !           425: /*
        !           426:  * Do client loop
        !           427:  */
        !           428: static int
        !           429: demo_client(struct pevent_ctx *ctx, int nurls, char **urls, int count)
        !           430: {
        !           431:        struct http_client *client;
        !           432:        struct hostent *hent;
        !           433:        struct in_addr ip;
        !           434:        char buf[256];
        !           435:        regex_t reg;
        !           436:        int i, j;
        !           437:        int r;
        !           438: 
        !           439:        /* Compile URL pattern */
        !           440:        if ((r = regcomp(&reg,
        !           441:            "^(http|https)://([-.[:alnum:]]+)(:[[:digit:]]+)?(/.*)?$",
        !           442:            REG_EXTENDED)) != 0) {
        !           443:                regerror(r, &reg, buf, sizeof(buf));
        !           444:                errx(1, "invalid URL pattern: %s", buf);
        !           445:        }
        !           446: 
        !           447:        /* Create client */
        !           448:        if ((client = http_client_create(ctx, "DemoClient/1.0",
        !           449:            5, 3, 7, demo_logger)) == NULL)
        !           450:                err(1, "http_client_create");
        !           451: 
        !           452:        printf("Fetching %d URLs %d times...\n", nurls, count);
        !           453:        for (i = 0; i < count; i++) {
        !           454:            for (j = 0; j < nurls; j++) {
        !           455:                const char *const url = urls[j];
        !           456:                struct http_client_connection *cc;
        !           457:                struct http_request *req;
        !           458:                struct http_response *resp;
        !           459:                regmatch_t match[5];
        !           460:                char host[256];
        !           461:                char path[256];
        !           462:                int https = 0;
        !           463:                int port;
        !           464: 
        !           465:                /* Parse URL */
        !           466:                if ((r = regexec(&reg, url, sizeof(match) / sizeof(*match),
        !           467:                    match, 0)) != 0) {
        !           468:                        regerror(r, &reg, buf, sizeof(buf));
        !           469:                        errx(1, "invalid URL \"%s\": %s", url, buf);
        !           470:                }
        !           471:                if (match[1].rm_eo - match[1].rm_so == 4)
        !           472:                        port = 80;
        !           473:                else {
        !           474:                        port = 443;
        !           475:                        https = 1;
        !           476:                }
        !           477:                if (match[3].rm_so != match[3].rm_eo) {
        !           478:                        strncpy(buf, url + match[3].rm_so, sizeof(buf) - 1);
        !           479:                        buf[sizeof(buf) - 1] = '\0';
        !           480:                        if ((port = strtoul(buf + 1, NULL, 10)) == 0)
        !           481:                                errx(1, "invalid port");
        !           482:                }
        !           483:                memset(&host, 0, sizeof(host));
        !           484:                strncpy(host, url + match[2].rm_so,
        !           485:                    MIN(sizeof(host) - 1, (match[2].rm_eo - match[2].rm_so)));
        !           486:                if (match[4].rm_so != match[4].rm_eo) {
        !           487:                        memset(&path, 0, sizeof(path));
        !           488:                        strncpy(path, url + match[4].rm_so,
        !           489:                            MIN(sizeof(path) - 1, (match[4].rm_eo
        !           490:                              - match[4].rm_so)));
        !           491:                } else
        !           492:                        strcpy(path, "/");
        !           493:                if (!inet_aton(host, &ip)) {
        !           494:                        if ((hent = gethostbyname(host)) == NULL)
        !           495:                                err(1, "%s: %s", host, hstrerror(h_errno));
        !           496:                        ip = *((struct in_addr **)hent->h_addr_list)[0];
        !           497:                }
        !           498:                printf("\nFetching %s://%s:%d%s\n", https ? "https" : "http",
        !           499:                    host, port, path);
        !           500: 
        !           501:                /* Create/get client connection */
        !           502:                if ((cc = http_client_connect(client, ip, port, https)) == NULL)
        !           503:                        err(1, "http_client_connect");
        !           504: 
        !           505:                /* Set up request */
        !           506:                req = http_client_get_request(cc);
        !           507:                if (http_request_set_method(req, "GET") == -1)
        !           508:                        err(1, "http_request_set_method");
        !           509:                if (http_request_set_path(req, path) == -1)
        !           510:                        err(1, "%s(%s)", "http_request_set_path", path);
        !           511:                if (http_request_set_header(req, 0,
        !           512:                    HTTP_HEADER_HOST, "%s:%u", host, port) == -1)
        !           513:                        err(1, "http_request_set_header");
        !           514: 
        !           515:                /* Send request */
        !           516:                if ((resp = http_client_get_response(cc)) == NULL)
        !           517:                        printf("Error: %s\n", http_client_get_reason(cc));
        !           518:                else {
        !           519:                        FILE *fp;
        !           520:                        int ch;
        !           521:                        int lnum;
        !           522: 
        !           523:                        printf("********** RESPONSE (first 20 lines): %d %s\n",
        !           524:                            http_response_get_code(resp),
        !           525:                            http_response_get_header(resp, HDR_REPLY_REASON));
        !           526:                        if ((fp = http_response_get_input(resp)) == NULL)
        !           527:                                err(1, "http_response_get_input");
        !           528:                        for (lnum = 0; (ch = getc(fp)) != EOF; ) {
        !           529:                                putchar(ch);
        !           530:                                if (ch == '\n') {
        !           531:                                        if (++lnum == 20)
        !           532:                                                break;
        !           533:                                }
        !           534:                        }
        !           535:                        printf("*********************************\n\n\n");
        !           536:                }
        !           537: 
        !           538:                /* Release client connection */
        !           539:                http_client_close(&cc);
        !           540: 
        !           541:                /* Pause */
        !           542:                sleep(1);
        !           543:            }
        !           544:        }
        !           545: 
        !           546:        /* Release client */
        !           547:        if (http_client_destroy(&client) == -1)
        !           548:                err(1, "http_client_free");
        !           549:        regfree(&reg);
        !           550:        return (0);
        !           551: }
        !           552: 
        !           553: /*
        !           554:  * Demo CGI file upload handler
        !           555:  */
        !           556: static void
        !           557: demo_file_upload(struct http_request *req, struct http_response *resp, FILE *fp)
        !           558: {
        !           559:        static const char *hr = "-----------------------------------------\n";
        !           560:        struct mime_multipart *mp;
        !           561:        u_int count;
        !           562:        int i;
        !           563: 
        !           564:        /* Read multipart MIME */
        !           565:        if ((mp = http_request_read_mime_multipart(req)) == NULL) {
        !           566:                http_response_send_error(resp,
        !           567:                    HTTP_STATUS_INTERNAL_SERVER_ERROR,
        !           568:                    "Can't read multi-part MIME input: %s", strerror(errno));
        !           569:                return;
        !           570:        }
        !           571: 
        !           572:        /* Display parts */
        !           573:        count = http_mime_multipart_get_count(mp);
        !           574:        fprintf(fp, "Read %d parts:\n\n", count);
        !           575:        fprintf(fp, "%s", hr);
        !           576:        for (i = 0; i < count; i++) {
        !           577:                struct mime_part *const part
        !           578:                    = http_mime_multipart_get_part(mp, i);
        !           579:                u_char *const data = http_mime_part_get_data(part);
        !           580:                const u_int dlen = http_mime_part_get_length(part);
        !           581:                const char *const cd = http_mime_part_get_header(part,
        !           582:                    HTTP_HEADER_CONTENT_DISPOSITION);
        !           583: 
        !           584:                fprintf(fp, "PART #%u: %u bytes\n%s: %s\n%s",
        !           585:                    i + 1, dlen, HTTP_HEADER_CONTENT_DISPOSITION,
        !           586:                    cd == NULL ? "<< NONE >>" : cd, hr);
        !           587:                fwrite(data, 1, dlen, fp);
        !           588:                fprintf(fp, "\n%s", hr);
        !           589:        }
        !           590: 
        !           591:        /* Free multipart data */
        !           592:        http_mime_multipart_free(&mp);
        !           593: }
        !           594: 
        !           595: /*
        !           596:  * Exit after printing usage string
        !           597:  */
        !           598: static void
        !           599: usage(void)
        !           600: {
        !           601:        (void)fprintf(stderr,
        !           602:           "Usage: demo_server [-s] [-p port] [-c count]\n"
        !           603:           "\t[-r redirect url] [-h hostname] [-v virtual-host] [url ...]\n");
        !           604:        exit(1);
        !           605: }
        !           606: 
        !           607: /***********************************************************************
        !           608:                        HTTP CALLBACKS
        !           609: ***********************************************************************/
        !           610: 
        !           611: /*
        !           612:  * Logger for the HTTP server.
        !           613:  */
        !           614: static void
        !           615: demo_logger(int sev, const char *fmt, ...)
        !           616: {
        !           617:        static char buf[512];
        !           618:        va_list args;
        !           619: 
        !           620:        snprintf(buf, sizeof(buf), "http_server: %s", fmt);
        !           621:        va_start(args, fmt);
        !           622:        vfprintf(stderr, buf, args);
        !           623:        fprintf(stderr, "\n");
        !           624:        va_end(args);
        !           625: }
        !           626: 
        !           627: /***********************************************************************
        !           628:                        AUTHORIZOR SERVLETS
        !           629: ***********************************************************************/
        !           630: 
        !           631: static int
        !           632: demo_auth_reqd(void *arg, struct http_request *req)
        !           633: {
        !           634:        const char *path = http_request_get_path(req);
        !           635: 
        !           636:        return (strcmp(path, "/logon") != 0);
        !           637: }
        !           638: 
        !           639: static const char *
        !           640: demo_basicauth(void *arg, struct http_request *req,
        !           641:        const char *username, const char *password)
        !           642: {
        !           643:        if (strcmp(username, "demo") != 0 || strcmp(password, "demo") != 0)
        !           644:                return ("HTTP Server Demo");
        !           645:        return (NULL);
        !           646: }
        !           647: 
        !           648: /***********************************************************************
        !           649:                        DEMO SERVLET
        !           650: ***********************************************************************/
        !           651: 
        !           652: static http_servlet_run_t      demo_servlet_run;
        !           653: static http_servlet_destroy_t  demo_servlet_destroy;
        !           654: 
        !           655: /*
        !           656:  * Demo servlet
        !           657:  */
        !           658: static struct http_servlet *
        !           659: demo_servlet_create(void)
        !           660: {
        !           661:        struct http_servlet *servlet;
        !           662: 
        !           663:        if ((servlet = MALLOC(DEMO_MEM_TYPE, sizeof(*servlet))) == NULL)
        !           664:                return (NULL);
        !           665:        memset(servlet, 0, sizeof(*servlet));
        !           666:        servlet->run = demo_servlet_run;
        !           667:        servlet->destroy = demo_servlet_destroy;
        !           668:        return (servlet);
        !           669: }
        !           670: 
        !           671: static int
        !           672: demo_servlet_run(struct http_servlet *servlet,
        !           673:        struct http_request *req, struct http_response *resp)
        !           674: {
        !           675:        const time_t now = time(NULL);
        !           676:        char buf[32];
        !           677:        FILE *fp;
        !           678:        char *u;
        !           679: 
        !           680:        /* Get output stream */
        !           681:        if ((fp = http_response_get_output(resp, 1)) == NULL) {
        !           682:                http_response_send_error(resp,
        !           683:                    HTTP_STATUS_INTERNAL_SERVER_ERROR,
        !           684:                    "Can't get output stream");
        !           685:                return (1);
        !           686:        }
        !           687: 
        !           688:        /* Set content type */
        !           689:        http_response_set_header(resp, 0,
        !           690:            HTTP_HEADER_CONTENT_TYPE, "text/html");
        !           691: 
        !           692:        /* Tell browser not to cache me */
        !           693:         http_response_set_header(resp, 1, HTTP_HEADER_PRAGMA, "no-cache");
        !           694:        http_response_set_header(resp, 0,
        !           695:            HTTP_HEADER_CACHE_CONTROL, "no-cache");
        !           696: 
        !           697:        /* Send some output */
        !           698:        fprintf(fp, "<html><head><title>Demo Servlet</title></head>\n");
        !           699:        fprintf(fp, "<body bgcolor=\"#ffffff\">\n");
        !           700:        fprintf(fp, "<h3>Demo Servlet in C</h3>\n");
        !           701:        fprintf(fp, "This servlet is implemented directly in C code.\n");
        !           702:        fprintf(fp, "See http_servlet(3) for details.\n<br>\n");
        !           703:        fprintf(fp, "<p>The time is <code>%s</code>\n", ctime_r(&now, buf));
        !           704:        if ((u = http_servlet_cookieauth_user("demo.key", demo_id,
        !           705:            sizeof(demo_id), DEMO_COOKIE_NAME, req, TYPED_MEM_TEMP)) == NULL) {
        !           706:                if (errno == EACCES)
        !           707:                        u = STRDUP(TYPED_MEM_TEMP, "(nobody)");
        !           708:        }
        !           709:        if (u != NULL) {
        !           710:                fprintf(fp, "<p>You are logged on as <b>%s</b>.", u);
        !           711:                FREE(TYPED_MEM_TEMP, u);
        !           712:        } else
        !           713:                fprintf(fp, "<p><b>Error with user: %s</b>.", strerror(errno));
        !           714:        fprintf(fp, "<p>Click <a href=\"tmpl\">HERE</a>"
        !           715:            " for tmpl servlet demo (login as <b>demo</b>"
        !           716:            " password <b>demo</b>)\n");
        !           717:        fprintf(fp, "</body></html>\n");
        !           718:        fclose(fp);
        !           719:        return (1);
        !           720: }
        !           721: 
        !           722: static void
        !           723: demo_servlet_destroy(struct http_servlet *servlet)
        !           724: {
        !           725:        FREE(DEMO_MEM_TYPE, servlet);
        !           726: }
        !           727: 
        !           728: /***********************************************************************
        !           729:                        KERNEL SERVLET
        !           730: ***********************************************************************/
        !           731: 
        !           732: static http_servlet_run_t      getkernel_servlet_run;
        !           733: static http_servlet_destroy_t  getkernel_servlet_destroy;
        !           734: 
        !           735: /*
        !           736:  * Kernel servlet
        !           737:  */
        !           738: static struct http_servlet *
        !           739: getkernel_servlet_create(void)
        !           740: {
        !           741:        struct http_servlet *servlet;
        !           742: 
        !           743:        if ((servlet = MALLOC(DEMO_MEM_TYPE, sizeof(*servlet))) == NULL)
        !           744:                return (NULL);
        !           745:        memset(servlet, 0, sizeof(*servlet));
        !           746:        servlet->run = getkernel_servlet_run;
        !           747:        servlet->destroy = getkernel_servlet_destroy;
        !           748:        return (servlet);
        !           749: }
        !           750: 
        !           751: static int
        !           752: getkernel_servlet_run(struct http_servlet *servlet,
        !           753:        struct http_request *req, struct http_response *resp)
        !           754: {
        !           755:        struct stat sb;
        !           756:        time_t timestamp;
        !           757:        char date[64];
        !           758:        struct tm tm;
        !           759: 
        !           760:        /* Make this "web page" not cachable */
        !           761:        http_response_set_header(resp, 1, HTTP_HEADER_PRAGMA, "no-cache");
        !           762:        http_response_set_header(resp, 0,
        !           763:            HTTP_HEADER_CACHE_CONTROL, "no-cache");
        !           764: 
        !           765:        /* Get timestamp of kernel file */
        !           766:        if (stat(PATH_KERNEL, &sb) != -1)
        !           767:                timestamp = sb.st_mtime;
        !           768:        else
        !           769:                timestamp = time(NULL); /* ok because servlet will fail too */
        !           770: 
        !           771:        /* Set MIME type */
        !           772:        http_response_set_header(resp, 0, HTTP_HEADER_CONTENT_TYPE,
        !           773:            "application/octet-stream");
        !           774: 
        !           775:        /* Set filename (via Content-Disposition) based on date */
        !           776:        strftime(date, sizeof(date), "%Y-%m-%d", localtime_r(&timestamp, &tm));
        !           777:        http_response_set_header(resp, 0, HTTP_HEADER_CONTENT_DISPOSITION,
        !           778:            "application/octet-stream; filename=\"kernel-%s\"", date);
        !           779: 
        !           780:        /* Piggy-back off of file servlet routine */
        !           781:        http_servlet_file_serve(PATH_KERNEL, demo_logger, req, resp);
        !           782:        return (1);
        !           783: }
        !           784: 
        !           785: static void
        !           786: getkernel_servlet_destroy(struct http_servlet *servlet)
        !           787: {
        !           788:        FREE(DEMO_MEM_TYPE, servlet);
        !           789: }
        !           790: 
        !           791: /***********************************************************************
        !           792:                            CGI SERVLET
        !           793: ***********************************************************************/
        !           794: 
        !           795: static http_servlet_run_t      cgi_servlet_run;
        !           796: static http_servlet_destroy_t  cgi_servlet_destroy;
        !           797: 
        !           798: /*
        !           799:  * Demo CGI
        !           800:  */
        !           801: static struct http_servlet *
        !           802: cgi_servlet_create(void)
        !           803: {
        !           804:        struct http_servlet *servlet;
        !           805: 
        !           806:        if ((servlet = MALLOC(DEMO_MEM_TYPE, sizeof(*servlet))) == NULL)
        !           807:                return (NULL);
        !           808:        memset(servlet, 0, sizeof(*servlet));
        !           809:        servlet->run = cgi_servlet_run;
        !           810:        servlet->destroy = cgi_servlet_destroy;
        !           811:        return (servlet);
        !           812: }
        !           813: 
        !           814: static int
        !           815: cgi_servlet_run(struct http_servlet *servlet,
        !           816:        struct http_request *req, struct http_response *resp)
        !           817: {
        !           818:        FILE *fp;
        !           819:        int i;
        !           820: 
        !           821:        /* Set no cache */
        !           822:        http_response_set_header(resp, 1, "Pragma", "no-cache");
        !           823:        http_response_set_header(resp, 0, "Cache-Control", "no-cache");
        !           824: 
        !           825:        /* Set MIME type */
        !           826:        http_response_set_header(resp, 0,
        !           827:            HTTP_HEADER_CONTENT_TYPE, "text/plain; charset=iso-8859-1");
        !           828: 
        !           829:        /* Get output stream */
        !           830:        if ((fp = http_response_get_output(resp, 0)) == NULL) {
        !           831:                http_response_send_error(resp,
        !           832:                    HTTP_STATUS_INTERNAL_SERVER_ERROR,
        !           833:                    "Can't get output stream");
        !           834:                return (1);
        !           835:        }
        !           836: 
        !           837:        /* For POST, read and decode input */
        !           838:        if (strcmp(http_request_get_method(req), "POST") == 0) {
        !           839:                const char *hval;
        !           840:                const char *s;
        !           841:                int nval;
        !           842: 
        !           843:                /* Check type of encoding */
        !           844:                if ((hval = http_request_get_header(req,
        !           845:                    HTTP_HEADER_CONTENT_TYPE)) == NULL) {
        !           846:                        http_response_send_error(resp,
        !           847:                            HTTP_STATUS_INTERNAL_SERVER_ERROR,
        !           848:                            "Missing %s header", HTTP_HEADER_CONTENT_TYPE);
        !           849:                        return (1);
        !           850:                }
        !           851: 
        !           852:                /* Special case form file upload */
        !           853:                if ((s = strchr(hval, ';')) != NULL
        !           854:                    && strncasecmp(hval,
        !           855:                      HTTP_CTYPE_MULTIPART_FORMDATA, s - hval) == 0) {
        !           856:                        demo_file_upload(req, resp, fp);
        !           857:                        return (1);
        !           858:                }
        !           859: 
        !           860:                /* Must be POST form data */
        !           861:                if (strcasecmp(hval, HTTP_CTYPE_FORM_URLENCODED) != 0) {
        !           862:                        http_response_send_error(resp,
        !           863:                            HTTP_STATUS_INTERNAL_SERVER_ERROR,
        !           864:                            "Weird content-type \"%s\"", hval);
        !           865:                        return (1);
        !           866:                }
        !           867: 
        !           868:                /* Read POST form data */
        !           869:                if ((nval = http_request_read_url_encoded_values(req)) == -1) {
        !           870:                        http_response_send_error(resp,
        !           871:                            HTTP_STATUS_INTERNAL_SERVER_ERROR,
        !           872:                            "Can't read POST input");
        !           873:                        return (1);
        !           874:                }
        !           875:                fprintf(fp, "Read %d values from input\n", nval);
        !           876:        }
        !           877: 
        !           878:        /* Get fields and display them */
        !           879:        for (i = 1; 1; i++) {
        !           880:                const char *value;
        !           881:                char fname[32];
        !           882: 
        !           883:                snprintf(fname, sizeof(fname), "field%d", i);
        !           884:                fprintf(fp, "FIELD \"%s\": ", fname);
        !           885:                if ((value = http_request_get_value(req, fname, 0)) == NULL) {
        !           886:                        fprintf(fp, "<< NOT FOUND >>\n");
        !           887:                        break;
        !           888:                } else
        !           889:                        fprintf(fp, "value=\"%s\"\n", value);
        !           890:        }
        !           891:        return (1);
        !           892: }
        !           893: 
        !           894: static void
        !           895: cgi_servlet_destroy(struct http_servlet *servlet)
        !           896: {
        !           897:        FREE(DEMO_MEM_TYPE, servlet);
        !           898: }
        !           899: 
        !           900: /***********************************************************************
        !           901:                        TMPL USER FUNCTIONS
        !           902: ***********************************************************************/
        !           903: 
        !           904: static tmpl_handler_t  authname_handler;
        !           905: static tmpl_handler_t  authorize_handler;
        !           906: static tmpl_handler_t  date_handler;
        !           907: static tmpl_handler_t  get_header_handler;
        !           908: static tmpl_handler_t  get_port_handler;
        !           909: static tmpl_handler_t  get_ssl_handler;
        !           910: static tmpl_handler_t  query_handler;
        !           911: static tmpl_handler_t  query_string_handler;
        !           912: static tmpl_handler_t  redirect_handler;
        !           913: static tmpl_handler_t  remote_ip_handler;
        !           914: static tmpl_handler_t  remote_port_handler;
        !           915: static tmpl_handler_t  shutdown_handler;
        !           916: static tmpl_handler_t  sleep_handler;
        !           917: static tmpl_handler_t  vhost_handler;
        !           918: 
        !           919: static const struct tmpl_func demo_tmpl_funcs[] = {
        !           920:        { "authname",           0, 0,   authname_handler        },
        !           921:        { "authorize",          0, 2,   authorize_handler       },
        !           922:        { "date",               0, 0,   date_handler            },
        !           923:        { "get_header",         1, 1,   get_header_handler      },
        !           924:        { "get_port",           0, 0,   get_port_handler        },
        !           925:        { "get_ssl",            0, 0,   get_ssl_handler         },
        !           926:        { "query",              1, 1,   query_handler           },
        !           927:        { "query_string",       0, 0,   query_string_handler    },
        !           928:        { "redirect",           0, 0,   redirect_handler        },
        !           929:        { "remote_ip",          0, 0,   remote_ip_handler       },
        !           930:        { "remote_port",        0, 0,   remote_port_handler     },
        !           931:        { "shutdown",           0, 0,   shutdown_handler        },
        !           932:        { "sleep",              1, 1,   sleep_handler           },
        !           933:        { "vhost",              0, 0,   vhost_handler           },
        !           934: };
        !           935: 
        !           936: static char *
        !           937: demo_tmpl_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !           938: {
        !           939:        return (tmpl_list_handler(ctx, demo_tmpl_funcs,
        !           940:            sizeof(demo_tmpl_funcs) / sizeof(*demo_tmpl_funcs),
        !           941:            errmsgp, ac, av));
        !           942: }
        !           943: 
        !           944: static char *
        !           945: remote_ip_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !           946: {
        !           947:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
        !           948:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !           949: 
        !           950:        return (STRDUP(mtype,
        !           951:            inet_ntoa(http_request_get_remote_ip(targ->req))));
        !           952: }
        !           953: 
        !           954: static char *
        !           955: remote_port_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !           956: {
        !           957:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
        !           958:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !           959:        char buf[32];
        !           960: 
        !           961:        snprintf(buf, sizeof(buf), "%u",
        !           962:            http_request_get_remote_port(targ->req));
        !           963:        return (STRDUP(mtype, buf));
        !           964: }
        !           965: 
        !           966: static char *
        !           967: redirect_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !           968: {
        !           969:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !           970: 
        !           971:        return (STRDUP(mtype, redirect_url ? redirect_url : ""));
        !           972: }
        !           973: 
        !           974: static char *
        !           975: date_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !           976: {
        !           977:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !           978:        const time_t now = time(NULL);
        !           979:        char buf[32];
        !           980: 
        !           981:        return (STRDUP(mtype, ctime_r(&now, buf)));
        !           982: }
        !           983: 
        !           984: static char *
        !           985: sleep_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !           986: {
        !           987:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
        !           988:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !           989: 
        !           990:        http_response_send_headers(targ->resp, 1);
        !           991:        sleep(atoi(av[1]));
        !           992:        return (STRDUP(mtype, ""));
        !           993: }
        !           994: 
        !           995: static char *
        !           996: authorize_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !           997: {
        !           998:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
        !           999:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1000: 
        !          1001:        /* Login */
        !          1002:        if (ac > 2 && *av[2] != '\0') {
        !          1003:                const u_long expiry = strtoul(av[2], NULL, 10);
        !          1004: 
        !          1005:                if (http_servlet_cookieauth_login(targ->resp,
        !          1006:                    "demo.key", av[1], 3600, expiry ? time(NULL) + expiry : 0,
        !          1007:                    expiry == 0, demo_id, sizeof(demo_id), DEMO_COOKIE_NAME,
        !          1008:                    "/", NULL, 0) == -1)
        !          1009:                        return (NULL);
        !          1010:                return (STRDUP(mtype, ""));
        !          1011:        }
        !          1012: 
        !          1013:        /* Logout */
        !          1014:        if (http_servlet_cookieauth_logout(DEMO_COOKIE_NAME,
        !          1015:            "/", NULL, targ->resp) == -1)
        !          1016:                return (NULL);
        !          1017:        return (STRDUP(mtype, ""));
        !          1018: }
        !          1019: 
        !          1020: static char *
        !          1021: authname_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !          1022: {
        !          1023:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
        !          1024:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1025:        char *name;
        !          1026: 
        !          1027:        if ((name = http_servlet_cookieauth_user("demo.key", demo_id,
        !          1028:            sizeof(demo_id), DEMO_COOKIE_NAME, targ->req, mtype)) == NULL) {
        !          1029:                if (errno == EACCES)
        !          1030:                        name = STRDUP(mtype, "");
        !          1031:        }
        !          1032:        if (name == NULL)
        !          1033:                return (NULL);
        !          1034:        return (name);
        !          1035: }
        !          1036: 
        !          1037: static char *
        !          1038: query_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !          1039: {
        !          1040:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
        !          1041:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1042:        const char *value;
        !          1043: 
        !          1044:        if ((value = http_request_get_value(targ->req, av[1], 0)) == NULL)
        !          1045:                value = "";
        !          1046:        return (STRDUP(mtype, value));
        !          1047: }
        !          1048: 
        !          1049: static char *
        !          1050: query_string_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !          1051: {
        !          1052:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
        !          1053:        const char *eqs = http_request_get_query_string(targ->req);
        !          1054:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1055:        char *dqs;
        !          1056: 
        !          1057:        /* URL-decode query string */
        !          1058:        if ((dqs = MALLOC(mtype, strlen(eqs) + 1)) == NULL)
        !          1059:                return (NULL);
        !          1060:        http_request_url_decode(eqs, dqs);
        !          1061: 
        !          1062:        /* Return it */
        !          1063:        return (dqs);
        !          1064: }
        !          1065: 
        !          1066: static char *
        !          1067: get_header_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !          1068: {
        !          1069:        struct http_servlet_tmpl_arg *const targ = tmpl_ctx_get_arg(ctx);
        !          1070:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1071:        const char *value;
        !          1072: 
        !          1073:        if ((value = http_request_get_header(targ->req, av[1])) == NULL)
        !          1074:                value = "";
        !          1075:        return (STRDUP(mtype, value));
        !          1076: }
        !          1077: 
        !          1078: static char *
        !          1079: get_port_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !          1080: {
        !          1081:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1082:        char buf[32];
        !          1083: 
        !          1084:        snprintf(buf, sizeof(buf), "%u", port);
        !          1085:        return (STRDUP(mtype, buf));
        !          1086: }
        !          1087: 
        !          1088: static char *
        !          1089: get_ssl_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !          1090: {
        !          1091:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1092: 
        !          1093:        return (STRDUP(mtype, ssl != NULL ? "1" : "0"));
        !          1094: }
        !          1095: 
        !          1096: static char *
        !          1097: vhost_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !          1098: {
        !          1099:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1100: 
        !          1101:        return (STRDUP(mtype, vhost == NULL ? "" : vhost));
        !          1102: }
        !          1103: 
        !          1104: static char *
        !          1105: shutdown_handler(struct tmpl_ctx *ctx, char **errmsgp, int ac, char **av)
        !          1106: {
        !          1107:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1108: 
        !          1109:        kill(main_pid, SIGTERM);
        !          1110:        return (STRDUP(mtype, ""));
        !          1111: }
        !          1112: 
        !          1113: /*
        !          1114:  * Error formatter for templates.
        !          1115:  */
        !          1116: static char *
        !          1117: demo_tmpl_errfmtr(struct tmpl_ctx *ctx, const char *errmsg)
        !          1118: {
        !          1119:        static const char fmt[] =
        !          1120:            "<font color=\"#ff0000\"><strong>Error: %s</strong></font>";
        !          1121:        const char *const mtype = tmpl_ctx_get_mtype(ctx);
        !          1122:        char *string;
        !          1123:        int slen;
        !          1124: 
        !          1125:        slen = sizeof(fmt) + strlen(errmsg);
        !          1126:        if ((string = MALLOC(mtype, slen)) == NULL)
        !          1127:                return (NULL);
        !          1128:        snprintf(string, slen, fmt, errmsg);
        !          1129:        return (string);
        !          1130: }
        !          1131: 
        !          1132: /***********************************************************************
        !          1133:                        SSL MEMORY WRAPPERS
        !          1134: ***********************************************************************/
        !          1135: 
        !          1136: /*
        !          1137:  * OpenSSL malloc() wrappers
        !          1138:  */
        !          1139: static void
        !          1140: *ssl_malloc(size_t size)
        !          1141: {
        !          1142:        return (MALLOC("OpenSSL", size));
        !          1143: }
        !          1144: 
        !          1145: static void
        !          1146: *ssl_realloc(void *mem, size_t size)
        !          1147: {
        !          1148:        return (REALLOC("OpenSSL", mem, size));
        !          1149: }
        !          1150: 
        !          1151: static void
        !          1152: ssl_free(void *mem)
        !          1153: {
        !          1154:        return (FREE("OpenSSL", mem));
        !          1155: }
        !          1156: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>