/*- * Copyright (c) 2008, 2013, 2016 Peter Pentchev * 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 AUTHOR 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 AUTHOR 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 #include #include #include #include #include "confget.h" #include "confget_common.h" #include "confget_http_get.h" static void readfile_http_get(void); confget_backend confget_http_get_backend = { "http_get", common_openfile_null, readfile_http_get, common_closefile, }; static char *strdup_urldecode(const char * const _s, size_t _len); /*** * Function: * readfile_http_get - scan CGI GET data for the requested variable * Inputs: * None. * Returns: * Nothing; exits on error. * Modifies: * May write to standard output if the variable has been found. * May write to standard error and terminate the program. */ static void readfile_http_get(void) { if (section == NULL) section = "QUERY_STRING"; const char *qstr = getenv(section); if (qstr == NULL) errx(1, "No CGI GET data - undefined environment variable %s", section); while (*qstr != '\0') { const char *start = qstr; while (*qstr != '\0' && *qstr != '&' && *qstr != '=') qstr++; char * const vname = strdup_urldecode(start, qstr - start); if (*qstr != '=') { foundvar("", vname, ""); free(vname); if (*qstr == '\0') return; if (strncmp(qstr + 1, "amp;", 4) == 0) qstr += 5; else qstr++; continue; } start = ++qstr; while (*qstr != '\0' && *qstr != '&') qstr++; char * const vvalue = strdup_urldecode(start, qstr - start); foundvar("", vname, vvalue); free(vname); free(vvalue); if (*qstr == '\0') return; if (strncmp(qstr + 1, "amp;", 4) == 0) qstr += 5; else qstr++; } } /* * Function: * strdup_urldecode - duplicate a string, decoding the URL-style * %XX escape sequences * Inputs: * s - the string to duplicate * Returns: * A pointer to the duplicated string on success, exits on error. * Modifies: * Allocates memory, may write to stderr and terminate the program. */ static char * strdup_urldecode(const char * const s, size_t len) { const char *p; char *q, *t, *v, *eh; char h[3]; long l; t = malloc(len + 1); if (t == NULL) err(1, "Out of memory"); p = s; q = t; while (len > 0) { v = memchr(p, '%', len); if (v == NULL) { memcpy(q, p, len); q += len; p += len; len = 0; break; } else if (v != p) { memcpy(q, p, v - p); q += v - p; len -= v - p; p = v; } p++; if (len < 2) errx(1, "Not enough hex digits in a %%XX URL escape"); h[0] = p[0]; h[1] = p[1]; h[2] = '\0'; l = strtol(h, &eh, 16); if (eh != h + 2) errx(1, "Invalid hex string in a %%XX URL escape"); else if (l < 0 || l > 255) errx(1, "Invalid hex value in a %%XX URL escape"); p += 2; *q++ = l; len -= 3; } *q++ = '\0'; return (t); }