📄 forms.c
字号:
/* =================================================================
*
* forms.c
*
* Handles form variables of GET and POST requests.
*
* =================================================================
* ####ECOSGPLCOPYRIGHTBEGIN####
* -------------------------------------------
* This file is part of eCos, the Embedded Configurable Operating
* System.
* Copyright (C) 2005 eCosCentric Ltd.
*
* eCos is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 or (at your option)
* any later version.
*
* eCos is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with eCos; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile this
* file and link it with other works to produce a work based on this
* file, this file does not by itself cause the resulting work to be
* covered by the GNU General Public License. However the source code
* for this file must still be made available in accordance with
* section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* -------------------------------------------
* ####ECOSGPLCOPYRIGHTEND####
* =================================================================
* #####DESCRIPTIONBEGIN####
*
* Author(s): Anthony Tonizzo (atonizzo@gmail.com)
* Contributors: Sergei Gavrikov (w3sg@SoftHome.net)
* Lars Povlsen (lpovlsen@vitesse.com)
* Date: 2006-06-12
* Purpose:
* Description:
*
* ####DESCRIPTIONEND####
*
* =================================================================
*/
#include <pkgconf/hal.h>
#include <pkgconf/kernel.h>
#include <pkgconf/io_fileio.h>
#include <cyg/kernel/kapi.h> // Kernel API.
#include <cyg/kernel/ktypes.h> // base kernel types.
#include <cyg/infra/diag.h> // For diagnostic printing.
#include <network.h>
#include <sys/uio.h>
#include <cyg/hal/hal_tables.h>
#include <stdlib.h>
#include <cyg/athttpd/http.h>
#include <cyg/athttpd/socket.h>
#include <cyg/athttpd/handler.h>
#include <cyg/athttpd/forms.h>
CYG_HAL_TABLE_BEGIN(cyg_httpd_fvars_table, httpd_fvars_table);
CYG_HAL_TABLE_END(cyg_httpd_fvars_table_end, httpd_fvars_table);
cyg_int8 blank[] = "";
cyg_int8
cyg_httpd_from_hex (cyg_int8 c)
{
return c >= '0' && c <= '9' ? c - '0'
: c >= 'A' && c <= 'F'? c - 'A' + 10
: c - 'a' + 10;
}
char*
cyg_httpd_store_form_variable(char *query, cyg_httpd_fvars_table_entry *entry)
{
char *p = query;
char *q = entry->buf;
int len = 0;
while (len < (entry->buflen - 1))
switch(*p)
{
case '%':
p++;
if (*p)
*q = cyg_httpd_from_hex(*p++) * 16;
if (*p)
*q = (*q + cyg_httpd_from_hex(*p++));
q++;
len++;
break;
case '+':
*q++ = ' ';
p++;
len++;
break;
case '&':
case ' ':
*q++ = '\0';
return p;
default:
*q++ = *p++;
len++;
}
*q = '\0';
while ((*p != ' ') && (*p != '&'))
p++;
return p;
}
// We'll try to parse the data from the form, and store it in the variables
// that have been defined by the user in the 'form_variable_table'.
char*
cyg_httpd_store_form_data(char *p)
{
char *p2;
cyg_int32 var_length;
cyg_httpd_fvars_table_entry *entry = cyg_httpd_fvars_table;
// We'll clear all the variables first, to avoid stale data.
while (entry != cyg_httpd_fvars_table_end)
{
entry->buf[0] = '\0';
entry++;
}
if (!p) /* No form data? just return after clearing variables */
return NULL;
while (*p && *p != ' ')
{
if (!(p2 = strchr(p, '=')))
return NULL; /* Malformed post? */
var_length = (cyg_int32)p2 - (cyg_int32)p;
entry = cyg_httpd_fvars_table;
while (entry != cyg_httpd_fvars_table_end)
{
if (!strncmp((const char*)p, entry->name, var_length ))
break;
entry++;
}
if (entry == cyg_httpd_fvars_table_end)
{
// No such variable. Run through the data.
while ((*p != '&') && (*p && *p != ' '))
p++;
if(*p == '&')
p++;
continue;
}
// Found the variable, store the name.
p = cyg_httpd_store_form_variable(++p2, entry);
#if CYGOPT_NET_ATHTTPD_DEBUG_LEVEL > 1
diag_printf("Stored form variable: %s Value: %s\n",
entry->name,
entry->buf);
#endif
if (*p == '&')
p++;
}
return p;
}
char*
cyg_httpd_find_form_variable(char *p)
{
cyg_httpd_fvars_table_entry *entry = cyg_httpd_fvars_table;
while (entry != cyg_httpd_fvars_table_end)
{
if (!strcmp((const char*)p, entry->name))
return entry->buf;
entry++;
}
return (char*)0;
}
void
cyg_httpd_handle_method_POST(void)
{
CYG_ASSERT(httpstate.post_data == NULL, "Leftover content data");
CYG_ASSERT(httpstate.header_end != NULL, "Cannot see POST data");
if (httpstate.content_len == 0 ||
httpstate.content_len > CYGNUM_ATHTTPD_SERVER_MAX_POST) {
cyg_httpd_send_error(CYG_HTTPD_STATUS_BAD_REQUEST);
return;
}
// The content data is only valid during a POST.
httpstate.post_data = (char*)malloc(httpstate.content_len + 1);
CYG_ASSERT(httpstate.post_data != NULL, "Cannot malloc POST buffer");
if (httpstate.post_data == NULL)
{
cyg_httpd_send_error(CYG_HTTPD_STATUS_SYSTEM_ERROR);
return;
}
/* Grab partial/all content from data read with headers */
/*
* TODO: This does NOT (yet) support multipart/form-data!
*/
int header_len = (int)httpstate.header_end - (int)httpstate.inbuffer;
int post_data_len = httpstate.inbuffer_len - header_len;
// Some POST data might have come along with the header frame, and the
// rest is coming in on following frames. Copy the data that already
// arriced into the post buffer.
memcpy(httpstate.post_data, httpstate.header_end, post_data_len);
// Do we need additional data?
if (post_data_len < httpstate.content_len)
{
while (post_data_len < httpstate.content_len)
{
cyg_int32 len = read(httpstate.sockets[httpstate.client_index].
descriptor,
httpstate.post_data + post_data_len,
httpstate.content_len - post_data_len);
if (len < 0)
{
/* This releases POST data area*/
free(httpstate.post_data);
httpstate.post_data = NULL;
return;
}
post_data_len += len;
}
}
CYG_ASSERT(post_data_len == httpstate.content_len, "Partial read");
/* httpstate.content remains available in handler */
httpstate.post_data[httpstate.content_len] = '\0';
// This assumes that the data that arrived in the POST body is of
// multipart/form-data MIME type. We need to change this, if we are to
// support things such as HTTP file transfer.
if (httpstate.mode & CYG_HTTPD_MODE_FORM_DATA)
cyg_httpd_store_form_data(httpstate.post_data);
#if defined(CYGOPT_NET_ATHTTPD_USE_CGIBIN_OBJLOADER) || \
defined(CYGOPT_NET_ATHTTPD_USE_CGIBIN_TCL)
// See if we are trying to execute a CGI via one of the supported methods.
// If we the GET request is trying to access a file in the
// CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR directory then it is assumed that
// we are trying to execute a CGI script. The extension of the file will
// determine the appropriate interpreter to use.
if (httpstate.url[0] == '/' &&
!strncmp(httpstate.url + 1,
CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR,
strlen(CYGDAT_NET_ATHTTPD_SERVEROPT_CGIDIR)))
{
// Here we'll look for extension to the file. We'll call the cgi
// handler only if the extension is '.o'.
cyg_httpd_exec_cgi();
free(httpstate.post_data);
httpstate.post_data = NULL;
return;
}
#endif
handler h = cyg_httpd_find_handler();
if (h != 0)
{
// A handler was found. We'll call the function associated to it.
h(&httpstate);
free(httpstate.post_data);
httpstate.post_data = NULL;
return;
}
// No handler of any kind for a post request. Must send 404.
cyg_httpd_send_error(CYG_HTTPD_STATUS_NOT_FOUND);
free(httpstate.post_data);
httpstate.post_data = NULL;
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -