Mon, 12 Aug 2024 21:20:17 +0200
fix memory leak in case handle_request fails (some illegal requests)
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2013 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "admin.h" #include "../util/pblock.h" #include "../config/conf.h" #include "../config/objconf.h" static Page *root_page; int admin_init(pblock *pb, Session *sn, Request *rq) { log_ereport(LOG_VERBOSE, "admin-init"); pool_handle_t *pool = pool_create(); root_page = admin_page_create(pool, NULL, admin_root); Page *ls_page = admin_page_create(pool, "listener", adm_listener); admin_add_page(root_page, ls_page); Page *cfgls_page = admin_page_create(pool, NULL, adm_cfglistener); admin_add_page(ls_page, cfgls_page); Page *auth_page = admin_page_create(pool, "auth", adm_auth); admin_add_page(root_page, auth_page); return REQ_PROCEED; } int admin_service(pblock *pb, Session *sn, Request *rq) { pblock_removekey(pb_key_content_type, rq->srvhdrs); pblock_nvinsert("content-type", "text/plain", rq->srvhdrs); protocol_status(sn, rq, 200, NULL); http_start_response(sn, rq); char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); uri++; uri = strchr(uri, '/'); size_t uri_len = uri ? strlen(uri) : 0; // start with second character to skip leading '/' int s = 0; int i = 1; Page *page = root_page; for(;i<=uri_len;i++) { char c = uri[i]; if(c == '/' || c == '\0') { if(i-s > 1) { // we have the path element name char *name = uri+s+1; size_t name_len = i-s-1; // get matching admin page Page *child = page->children; page = NULL; while(child) { if(child->name) { if(!strncmp(child->name, name, name_len)) { page = child; break; } } else { page = child; break; } child = child->next; } if(!page) { break; } s = i; } } } // service admin page if(page) { AdminRequest arq; arq.sn = sn; arq.rq = rq; page->service(page, &arq); } else { net_printf(sn->csd, "page not found\n"); } return REQ_PROCEED; } int admin_root(Page *page, AdminRequest *rq) { return REQ_PROCEED; } int adm_listener(Page *page, AdminRequest *rq) { SYS_NETFD out = rq->sn->csd; return REQ_PROCEED; } int adm_cfglistener(Page *page, AdminRequest *rq) { printf("adm_cfglistener\n"); return REQ_PROCEED; } int adm_auth(Page *page, AdminRequest *rq) { printf("adm_auth\n"); return REQ_PROCEED; } // public admin API Page* admin_page_create(pool_handle_t *pool, char *name, admin_service_f f) { Page *p = pool_malloc(pool, sizeof(Page)); ZERO(p, sizeof(Page)); if(name) { p->name = pool_strdup(pool, name); } p->service = f; return p; } void admin_add_page(Page *parent, Page *child) { child->parent = parent; Page *ch = parent->children; if(ch) { while(ch->next) { ch = ch->next; } ch->next = child; } else { parent->children = child; } }