📄 post2a.c
字号:
/*******************************************************************************
Samples\TCPIP\HTTP\post2a.c
Z-World, 2000
This is an alternate version of post2.c that uses the ZSERVER.LIB
functionality to build the server table. Comparison with post2.c
shows how a program can be converted from using http_flashspec
to ZSERVER.LIB functionality.
This uses the post.c style form submission, and the ssi.c style
dynamic pages to build a fully functional and audited contoller.
When users first access the page, they enter their name in a form,
that is then stored in a HTTP cookie. This is used to later build
an audit trail of what changes each user makes.
*******************************************************************************/
#class auto
/***********************************
* Configuration *
* ------------- *
* All fields in this section must *
* be altered to match your local *
* network settings. *
***********************************/
/*
* Pick the predefined TCP/IP configuration for this sample. See
* LIB\TCPIP\TCP_CONFIG.LIB for instructions on how to set the
* configuration.
*/
#define TCPCONFIG 1
/*
* TCP/IP modification - reduce TCP socket buffer
* size, to allow more connections. This can be increased,
* with increased performance, if the number of sockets
* are reduced. Note that this buffer size is split in
* two for TCP sockets--1024 bytes for send and 1024 bytes
* for receive.
*/
#define TCP_BUF_SIZE 2048
/*
* Web server configuration
*/
/*
* only one socket and server are needed for a reserved port
*/
#define HTTP_MAXSERVERS 1
#define MAX_TCP_SOCKET_BUFFERS 1
/*
* Increase the number of spec entries
*/
#define SSPEC_MAXSPEC 19
/*
* Don't use the FlashSpec structure
*/
#define HTTP_NO_FLASHSPEC
/*
* Our web server as seen from the clients.
* This should be the address that the clients (netscape/IE)
* use to access your server. Usually, this is your IP address.
* If you are behind a firewall, though, it might be a port on
* the proxy, that will be forwarded to the Rabbit board. The
* commented out line is an example of such a situation.
*/
#define REDIRECTHOST _PRIMARY_STATIC_IP
//#define REDIRECTHOST "proxy.domain.com:1212"
/********************************
* End of configuration section *
********************************/
/*
* REDIRECTTO is used by each ledxtoggle cgi's to tell the
* browser which page to hit next. The default REDIRECTTO
* assumes that you are serving a page that does not have
* any address translation applied to it.
*
*/
#define REDIRECTTO "http://" REDIRECTHOST "/index.shtml"
#define REGISTERFORM "http://" REDIRECTHOST "/register.html"
#memmap xmem
#use "dcrtcp.lib"
#use "http.lib"
#ximport "samples/tcpip/http/pages/form.html" reg_form
#ximport "samples/tcpip/http/pages/ssi2.shtml" index_html
#ximport "samples/tcpip/http/pages/rabbit1.gif" rabbit1_gif
#ximport "samples/tcpip/http/pages/ledon.gif" ledon_gif
#ximport "samples/tcpip/http/pages/ledoff.gif" ledoff_gif
#ximport "samples/tcpip/http/pages/button.gif" button_gif
#ximport "samples/tcpip/http/pages/showsrc.shtml" showsrc_shtml
#ximport "samples/tcpip/http/post2a.c" ssi_c
/* the default for / must be first */
SSPEC_MIMETABLE_START
SSPEC_MIME_FUNC(".shtml", "text/html", shtml_handler),
SSPEC_MIME(".html", "text/html"),
SSPEC_MIME(".gif", "image/gif"),
SSPEC_MIME(".cgi", "")
SSPEC_MIMETABLE_END
#define MAX_FORMSIZE 64
typedef struct {
char *name;
char value[MAX_FORMSIZE];
} FORMType;
FORMType FORMSpec[2];
char led1[15];
char led2[15];
char led3[15];
char led4[15];
/*
* The audit list - stores the last NUM_ENTRIES changes to the site
*/
#define NUM_ENTRIES 16
typedef struct {
char who[HTTP_MAXNAME];
char which; /* which LED changed */
char led1; /* updated status of all LEDs */
char led2;
char led3;
char led4;
} AUDITLine;
AUDITLine audit_list[NUM_ENTRIES];
int current_line;
char get_led_status(char *led)
{
if (strcmp(led,"ledon.gif")==0)
return 1;
else
return 0;
}
void AuditInitLine(AUDITLine* line)
{
line->who[0] = '\0';
line->led1 = get_led_status(led1);
line->led2 = get_led_status(led2);
line->led3 = get_led_status(led3);
line->led4 = get_led_status(led4);
}
void AuditInit(void)
{
int i;
for(i=0;i<NUM_ENTRIES;i++) {
AuditInitLine(&audit_list[i]);
}
current_line = 0;
}
/**
* print the audit list. Call by SSI exec command in "SSI2.shtml"
* (ie, it holds the static areas of the HTML page).
*/
int audit_list_print(HttpState* state)
{
int printline;
AUDITLine* p;
if(state->substate >= NUM_ENTRIES)
return 1;
printline = current_line - state->substate;
if(printline < 0)
printline += NUM_ENTRIES;
p = &audit_list[printline];
if('\0' == p->who[0]) {
state->substate++;
return 0;
}
sprintf(state->buffer, "<tr><td>%s</td><td>led%d</td><td>%c%c%c%c</td></tr>\r\n",
p->who,
p->which,
1 == p->led1 ? 'O' : 'X',
1 == p->led2 ? 'O' : 'X',
1 == p->led3 ? 'O' : 'X',
1 == p->led4 ? 'O' : 'X'
);
state->headerlen = strlen(state->buffer);
state->headeroff = 0;
state->substate++;
return 0;
}
void add_audit(HttpState* state, char which)
{
struct sockaddr sock_addr;
current_line++;
if(current_line >= NUM_ENTRIES)
current_line = 0;
AuditInitLine(&audit_list[current_line]);
audit_list[current_line].which = which;
strcpy(audit_list[current_line].who, state->cookie);
}
/*
* Instead of sending other text back from the cgi's
* we have decided to redirect them to the original page.
* the cgi_redirectto forms a header which will redirect
* the browswer back to the main page.
*
*/
int led1toggle(HttpState* state)
{
if('\0' == state->cookie[0]) {
cgi_redirectto(state,REGISTERFORM);
return 0;
}
if (strcmp(led1,"ledon.gif")==0)
strcpy(led1,"ledoff.gif");
else
strcpy(led1,"ledon.gif");
add_audit(state, 1);
cgi_redirectto(state,REDIRECTTO);
return 0;
}
int led2toggle(HttpState* state)
{
if('\0' == state->cookie[0]) {
cgi_redirectto(state,REGISTERFORM);
return 0;
}
if (strcmp(led2,"ledon.gif")==0)
strcpy(led2,"ledoff.gif");
else
strcpy(led2,"ledon.gif");
add_audit(state, 2);
cgi_redirectto(state,REDIRECTTO);
return 0;
}
int led3toggle(HttpState* state)
{
if('\0' == state->cookie[0]) {
cgi_redirectto(state,REGISTERFORM);
return 0;
}
if (strcmp(led3,"ledon.gif")==0)
strcpy(led3,"ledoff.gif");
else
strcpy(led3,"ledon.gif");
add_audit(state, 3);
cgi_redirectto(state,REDIRECTTO);
return 0;
}
int led4toggle(HttpState* state)
{
if('\0' == state->cookie[0]) {
cgi_redirectto(state,REGISTERFORM);
return 0;
}
if (strcmp(led4,"ledon.gif")==0)
strcpy(led4,"ledoff.gif");
else
strcpy(led4,"ledon.gif");
add_audit(state, 4);
cgi_redirectto(state,REDIRECTTO);
return 0;
}
/*
* parse the url-encoded POST data into the FORMSpec struct
* (ie: parse 'foo=bar&baz=qux' into the struct
*/
int parse_post(HttpState* state)
{
auto int retval;
auto int i;
// state->s is the socket structure, and state->p is pointer
// into the HTTP state buffer (initially pointing to the beginning
// of the buffer). Note that state->p was set up in the submit
// CGI function. Also note that we read up to the content_length,
// or HTTP_MAXBUFFER, whichever is smaller. Larger POSTs will be
// truncated.
retval = sock_aread(&state->s, state->p,
(state->content_length < HTTP_MAXBUFFER-1)?
(int)state->content_length:HTTP_MAXBUFFER-1);
if (retval < 0) {
// Error--just bail out
return 1;
}
// Using the subsubstate to keep track of how much data we have received
state->subsubstate += retval;
if (state->subsubstate >= state->content_length) {
// NULL-terminate the content buffer
state->buffer[(int)state->content_length] = '\0';
// Scan the received POST information into the FORMSpec structure
for(i=0; i<(sizeof(FORMSpec)/sizeof(FORMType)); i++) {
http_scanpost(FORMSpec[i].name, state->buffer, FORMSpec[i].value,
MAX_FORMSIZE);
}
// Finished processing--returning 1 indicates that we are done
return 1;
}
// Processing not finished--return 0 so that we can be called again
return 0;
}
/*
* Sample submit.cgi function
*/
int submit(HttpState* state)
{
int i;
if(state->length) {
/* buffer to write out */
if(state->offset < state->length) {
state->offset += sock_fastwrite(&state->s,
state->buffer + (int)state->offset,
(int)state->length - (int)state->offset);
} else {
state->offset = 0;
state->length = 0;
}
} else {
switch(state->substate) {
case 0:
strcpy(state->buffer, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n");
break;
case 1:
/* init the FORMSpec data */
FORMSpec[0].value[0] = '\0';
FORMSpec[1].value[0] = '\0';
state->p = state->buffer;
parse_post(state);
state->substate++;
return 0;
case 2:
http_setcookie(state->buffer, FORMSpec[0].value);
break;
case 3:
strcpy(state->buffer, "\r\n\r\n<html><head><title>Results</title></head><body>\r\n");
break;
case 4:
sprintf(state->buffer, "<p>Username: %s<p>\r\n<p>Email: %s<p>\r\n",
FORMSpec[0].value, FORMSpec[1].value);
break;
case 5:
strcpy(state->buffer, "<p>Go <a href=\"/\">home</a></body></html>\r\n");
break;
default:
state->substate = 0;
return 1;
}
state->length = strlen(state->buffer);
state->offset = 0;
state->substate++;
}
return 0;
}
void main()
{
/* FORM stuff */
sspec_addxmemfile("register.html", reg_form, SERVER_HTTP);
sspec_addfunction("submit.cgi", submit, SERVER_HTTP);
/* normal SSI button stuff */
sspec_addxmemfile("/", index_html, SERVER_HTTP);
sspec_addxmemfile("index.shtml", index_html, SERVER_HTTP);
sspec_addxmemfile("showsrc.shtml", showsrc_shtml, SERVER_HTTP);
sspec_addxmemfile("rabbit1.gif", rabbit1_gif, SERVER_HTTP);
sspec_addxmemfile("ledon.gif", ledon_gif, SERVER_HTTP);
sspec_addxmemfile("ledoff.gif", ledoff_gif, SERVER_HTTP);
sspec_addxmemfile("button.gif", button_gif, SERVER_HTTP);
sspec_addxmemfile("ssi.c", ssi_c, SERVER_HTTP);
sspec_addvariable("led1", led1, PTR16, "%s", SERVER_HTTP);
sspec_addvariable("led2", led2, PTR16, "%s", SERVER_HTTP);
sspec_addvariable("led3", led3, PTR16, "%s", SERVER_HTTP);
sspec_addvariable("led4", led4, PTR16, "%s", SERVER_HTTP);
sspec_addfunction("led1tog.cgi", led1toggle, SERVER_HTTP);
sspec_addfunction("led2tog.cgi", led2toggle, SERVER_HTTP);
sspec_addfunction("led3tog.cgi", led3toggle, SERVER_HTTP);
sspec_addfunction("led4tog.cgi", led4toggle, SERVER_HTTP);
sspec_addfunction("audit", audit_list_print, SERVER_HTTP);
strcpy(led1,"ledon.gif");
strcpy(led2,"ledon.gif");
strcpy(led3,"ledoff.gif");
strcpy(led4,"ledon.gif");
/* Init the audit history */
AuditInit();
/* init FORM searchable names - must init ALL FORMSpec structs! */
FORMSpec[0].name = "user_name";
FORMSpec[1].name = "user_email";
sock_init();
http_init();
tcp_reserveport(80);
while (1) {
http_handler();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -