/* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution 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. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY * DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that Software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. */ /* * read_post.c: Example NSAPI functions to read POST data from a request that * may have chunked bodies */ #ifdef XP_WIN32 #define NSAPI_PUBLIC __declspec(dllexport) #else /* !XP_WIN32 */ #define NSAPI_PUBLIC #endif /* !XP_WIN32 */ #include "nsapi.h" #include #ifndef XP_WIN32 #include /* sleep */ #else /* XP_WIN32 */ #include #endif /* XP_WIN32 */ /* write the string buffer */ static int write_string(SYS_NETFD sd, const char *format, ...) { va_list args; va_start(args, format); char buf[1024]; vsnprintf(buf, sizeof(buf), format, args); va_end(args); return net_write(sd, buf, strlen(buf)); } /* * Read the clen data and print int in response. */ static int process_content_length(Session * sn, Request * rq, int clen, int *read_bytes) { int bufsize = 1024; char buf[bufsize]; int bytes_rcvd; while (clen > 0) { bytes_rcvd = netbuf_getbytes(sn->inbuf, buf, bufsize); if (bytes_rcvd != NETBUF_EOF || bytes_rcvd != NETBUF_ERROR) { clen -= bytes_rcvd; *read_bytes += bytes_rcvd; } else { log_error(LOG_WARN, "read_post", sn, rq, "netbuf_getbytes reported %d", bytes_rcvd); write_string(sn->csd, "Request ended with netbuf_getbytes error\n"); return -1; } } return 0; } /* * Read data from sn->inbuf until EOF */ static int process_chunked_data(Session * sn, Request * rq, int *read_bytes) { int bufsize = 1024; char buf[bufsize]; int bytes_rcvd; while (1) { bytes_rcvd = netbuf_getbytes(sn->inbuf, buf, bufsize); if (bytes_rcvd == NETBUF_EOF) break; if (bytes_rcvd == NETBUF_ERROR) { log_error(LOG_WARN, "read_post", sn, rq, "netbuf_getbytes reported NETBUF_ERROR"); write_string(sn->csd, "Request ended with netbuf_getbytes error\n"); break; } *read_bytes += bytes_rcvd; } return 0; } /* function : read_post * * this function will look at the rq->headers and read the post data according * to request headers. If content length is set then read the conent-length * bytes from sn->inbuf othewise read the sn->inbuf until EOF. * * The function will output the debug messages in response. Error messages will * appear in Web Server log files. */ #ifdef __cplusplus extern "C" #endif NSAPI_PUBLIC int read_post(pblock * pb, Session * sn, Request * rq) { char *content_len = NULL; char *transenc = NULL; int read_bytes = 0; int rv1; int rv2; char buf[1024]; memset(buf, 0, sizeof(buf)); /* remove content-type header from response, insert new content-type */ param_free(pblock_remove("content-type", rq->srvhdrs)); pblock_nvinsert("content-type", "text/html", rq->srvhdrs); /* this is a simple plugin, always give a successful response status * setup http response status, start the response */ protocol_status(sn, rq, PROTOCOL_OK, NULL); protocol_start_response(sn, rq); pblock_pblock2str(rq->headers, buf); write_string(sn->csd, "rq->headers contains : %s\n", buf); /* check for a request body */ rv1 = request_header("content-length", &content_len, sn, rq); rv2 = request_header("transfer-encoding", &transenc, sn, rq); if ((rv1 == REQ_ABORTED) || (rv2 == REQ_ABORTED)) { log_error(LOG_INFORM, "read_post", sn, rq, "Request does not have a body"); write_string(sn->csd, "Request does not have a body\n"); return REQ_PROCEED; } if ((rv1 != REQ_ABORTED) && content_len) { write_string(sn->csd, "content-length in rq->headers : %s\n", content_len); } if ((rv2 != REQ_ABORTED) && transenc) { write_string(sn->csd, "transfer-encoding in rq->headers : %s\n", transenc); } if (content_len != NULL) { /* Content-length header was in the request, read the request body * based on the length of the content-length header */ int clen = atoi(content_len); write_string(sn->csd, "Trying to read content-length(%d) bytes from sn->inbuf\n", clen); if (process_content_length(sn, rq, clen, &read_bytes) < 0) { return REQ_PROCEED; } } else { /* transfer-encoding was present in the request and content-length is * not known so read the request body until EOF */ write_string(sn->csd, "Reading request data from sn->inbuf until EOF\n"); if (process_chunked_data(sn, rq, &read_bytes) < 0) { return REQ_PROCEED; } } write_string(sn->csd, "Number of bytes read successfully = %d\n", read_bytes); return REQ_PROCEED; }