?? put.c
字號:
/* put.c ** PUT CGI-SCRIPT ** ** (c) COPYRIGHT INRIA/MIT/W3C 1996. ** Please first read the full copyright statement in the file COPYRIGHT. ** ** DISCLAIMER: ** ** This is just an example script for handling PUT requests with the CERN ** server. It's provided in an as-is basis, without any guarantee over its ** functioning or any loss of data, accidental or intentional, coming ** from its use. Users of this script are encouraged to fully review it ** before integrating it into their systems. ** ** This script has been compiled with gcc and tested with the CERN 3.0 ** HTTP server, running under Solaris 2.5 and Linux 2.0.0. ** I tested the following clients against this server: ** Amaya 0.9a, Netscape Gold 3.0, and AOLpress 1.2 beta. ** Please email me if you use this script against/under something else. ** ** You may find a link to the latest version of this script at: ** http://www.w3.org/pub/WWW/Amaya/PutCern.html ** ** HISTORY: ** v0 20 May 96 Jose Kahan <kahan@w3.org> Created from zero ** v1.0 24 Dec 96 Jose Kahan Improved error detection ** Added HTTP/1.x return codes */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <time.h>#include <fcntl.h>#include <signal.h>#include <sys/uio.h>#include <sys/types.h>#include <sys/stat.h>#define LF "\r\n"/***** HTTP status codes this script supports *****/#define OK 1 /* 200 */#define CREATED 2 /* 201 */#define UPDATED 3 /* 204 */#define ERROR -1 /* 500 *//***** USER CONFIGURABLE OPTIONS *******//*** Here are some error status messages, in case you want to** customize them yourself*/#define INVALID_PATH_MSG "Server did not give a valid URL path"#define INVALID_METHOD_MSG "You must use a PUT method with this script"#define INVALID_CONTENT_LENGTH_MSG "Server did not send a correct Content-length"/*** Change the following flags to specify which will be the Unix access rights of** the files that this script can create */#define FILE_RIGHTS S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH/*** Maximum number of bytes to read/write in a single operation */#define MAX_BUF_LEN 4048 /*** trace_on == 1 for a simple debug mode.** Turned off by default*/int trace_on = 0; /*** According to the HTTP/1.1 standard, there are at least two** different response status that a PUT command can give:** (201) when creating a new resource and (204) when updating** it. To find out the state of a resource, the script does an extra** system call. This wastes some time, and well, today's** browsers are satisfied with the 204 response. Thus, undefine** the following macro if you don't need this feature. */#define CREATE_UPDATE/*** define the following macro when running the script on a** fully compliant HTTP/1.1 server. It'll activate** the generation of a Location header to be sent together** with an HTTP/1.1 201 response.*//**#define HTTP_11**//***** END OF USER CONFIGURABLE OPTIONS ******/extern char **environ;extern int errno;extern char *sys_errlist[];#if defined(__svr4__)#define CATCH_SIG#endif/*** Function Prototypes** -------------------*/void trace (char *trace_msg);int copy_content (char *filename, long cl, char ** status_msg);void dump_result (char *url, char *status_msg, int status);static void SetSignal (void);/* ------------------------------------------------------------------------- *//*** trace** -----** Prints error messages --- for debugging*/voidtrace (char *trace_msg){ if (trace_on) fprintf (stderr, "PUT TRACE: %s\n", trace_msg);}/*** dump_result** -----------** Outputs the PUT result thru stdout, according to the CGI** specification.*/voiddump_result (char *url, char *status_msg, int status){ switch(status) { case OK: /* not used for the moment, but it does not hurt to have this case here */ printf ("Status: 200%s", LF); printf ("Content-Type: text/html%s%s", LF, LF); printf ("<HTML><HEAD><TITLE>PUT success</TITLE></HEAD>%s" "<BODY><P>Created the following resource:<CODE>%s</CODE>" "</P>%s</BODY></HTML>",LF,LF,url); break; case UPDATED: trace ("Updating a file"); printf ("Status: 204%s%s", LF, LF); break; case CREATED: trace ("Creating a file"); printf ("Status: 201%s%s", LF, LF);#ifdef HTTP_11 /* printf ("Location:%s%s", url, LF);*/ printf ("Content-Type: text/html%s%s", LF, LF); printf ("<HTML><HEAD><TITLE>PUT success</TITLE></HEAD>%s" "<BODY><P>Created the following resource:</P><P><CODE>%s</CODE>" "</P>%s</BODY></HTML>",LF, LF, url);#endif /* HTTP/1.1 */ break; case ERROR: default: trace ("Uh oh, an error ..."); printf ("Status: 500 cgi PUT script error%s", LF); printf ("Content-Type: text/html%s%s",LF,LF); printf ("<HTML><HEAD><TITLE>cgi PUT script error</TITLE></HEAD>\n"); if(url && url[0] != '\0') printf("<BODY><P>Could not save the following URL:</P><P><CODE>%s</CODE></P>\n", url); else printf("<BODY><P>Could not save the URL</P>\n"); if(status_msg && status_msg[0] != '\0') printf("<P>Reason: <CODE>%s</CODE></P>\n", status_msg); printf("</BODY></HTML>"); break; } /* switch */}/*** SetSignal** ---------** This function sets up signal handlers. This might not be necessary to** call if the application has its own handlers.*/static voidSetSignal (void){ /* On some systems (SYSV) it is necessary to catch the SIGPIPE signal ** when attemting to connect to a remote host where you normally should ** get `connection refused' back */ if (signal (SIGPIPE, SIG_IGN) == SIG_ERR) trace("HTSignal.... Can't catch SIGPIPE"); else trace("HTSignal.... Ignoring SIGPIPE");}/*** copy_content** ------------** Creates a filename and then copies cl bytes from stdin into it ** If there's an error, it returns ERROR and sets status_msg to** the corresponding Unix system error message. Otherwise, it** returns either CREATED or UPDATED, depending whether the file** already existed or not. */ intcopy_content (char *filename, long cl, char **status_msg){ char buffer[MAX_BUF_LEN]; int fd_out; int nb_elements_read, nb_elements_write; int buf_len; int status; /* ** this is for verifying if the file already existed, to be compliant ** with HTTP/1.1. */#ifdef CREATE_UPDATE if((fd_out = open (filename, O_EXCL | O_WRONLY | O_CREAT | O_TRUNC, FILE_RIGHTS)) == -1) { if (errno == EEXIST) { trace("File existed !"); status = UPDATED; if ((fd_out = creat (filename, FILE_RIGHTS)) == -1) { *status_msg = sys_errlist[errno]; trace (*status_msg); return (ERROR); } } else { *status_msg = sys_errlist[errno]; trace (*status_msg); return(ERROR); } } else status = CREATED;#else if ((fd_out = creat (filename, FILE_RIGHTS)) == -1) { *status_msg = sys_errlist[errno]; trace (*status_msg); return (ERROR); } else status = CREATED;#endif /* CREATE_UPDATE */ buf_len = MAX_BUF_LEN; while (status != ERROR && cl) { if (cl < buf_len) buf_len = cl; nb_elements_read = read (0, buffer, buf_len); if (nb_elements_read == -1) { *status_msg = sys_errlist[errno]; trace (*status_msg); status = ERROR; break; } nb_elements_write = write (fd_out, buffer, nb_elements_read); if (nb_elements_write == -1 || nb_elements_write != nb_elements_read) { *status_msg = sys_errlist[errno]; trace (*status_msg); status = ERROR; break; } cl = cl - nb_elements_read; } if (close (fd_out) == -1) { *status_msg = sys_errlist[errno]; trace (*status_msg); status = ERROR; } return (status);} /*** main** ----** Does not receives any direct input parameters. They come from** the Unix environment variables, according to the** CGI specification.*/intmain (int argc, char *argv[]){ char *filename; char *method; char *url; char *status_msg; char *pcl; long cl; int status; trace ("I\'m alive (PUT)");#ifdef CATCH_SIG SetSignal ();#endif /* ** Read and control the CGI environment variables */ trace ("Reading CGI environment variables"); method = getenv ("REQUEST_METHOD"); url = getenv ("PATH_INFO"); filename = getenv ("PATH_TRANSLATED"); pcl = getenv ("CONTENT_LENGTH"); if(!url || !url[0] || !filename || !filename[0]) { status = ERROR; status_msg = INVALID_PATH_MSG; url = NULL; trace(status_msg); } else if (!method || strcmp(method, "PUT")) { status = ERROR; status_msg = INVALID_METHOD_MSG; trace(status_msg); } else if (!pcl || !pcl[0]) { status = ERROR; status_msg = INVALID_CONTENT_LENGTH_MSG; trace(status_msg); } else { if(trace_on) fprintf (stderr, "REQUEST_METHOD = %s\n" "PATH_INFO = %s\n" "PATH_TRANSLATED = %s\n" "CONTENT_LENGTH = %s\n", method, url, filename, pcl); /* set the number of bytes ( content length) to read */ cl = atol (pcl); /* **try to save the file */ status = copy_content(filename, cl, &status_msg); } /* if-else */ if(trace_on) fprintf(stderr,"status is %d\n", status); dump_result (url, status_msg, status); exit(0); }/*** end of module put.c*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -