@@ -27,18 +27,25 @@
** formatting function and its cousins, and routines to encode and
** decode strings in HTML or HTTP.
*/
#include "config.h"
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <time.h>
-#include <sys/times.h>
-#include <sys/time.h>
-#include <sys/wait.h>
+#ifdef __MINGW32__
+# include <windows.h> /* for Sleep once server works again */
+# include <winsock2.h> /* socket operations */
+# define sleep Sleep /* windows does not have sleep, but Sleep */
+# include <ws2tcpip.h>
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <sys/times.h>
+# include <sys/time.h>
+# include <sys/wait.h>
+# include <sys/select.h>
+#endif
+#include <time.h>
#include <stdio.h>
#include <stdlib.h>
-#include <sys/select.h>
#include <unistd.h>
#include "cgi.h"
#if INTERFACE
@@ -144,9 +151,9 @@
const char *zValue, /* Value of the cookie. Automatically escaped */
const char *zPath, /* Path cookie applies to. NULL means "/" */
int lifetime /* Expiration of the cookie in seconds from now */
){
- if( zPath==0 ) zPath = "/";
+ if( zPath==0 ) zPath = g.zTop;
if( lifetime>0 ){
lifetime += (int)time(0);
blob_appendf(&extraHeader,
"Set-Cookie: %s=%t; Path=%s; expires=%s; Version=1\r\n",
@@ -289,18 +296,25 @@
void cgi_redirect(const char *zURL){
char *zLocation;
CGIDEBUG(("redirect to %s\n", zURL));
if( strncmp(zURL,"http:",5)==0 || strncmp(zURL,"https:",6)==0 || *zURL=='/' ){
- cgi_panic("invalid redirect URL: %s", zURL);
- }
- zLocation = mprintf("Location: %s/%s\r\n", g.zBaseURL, zURL);
+ zLocation = mprintf("Location: %s\r\n", zURL);
+ }else{
+ zLocation = mprintf("Location: %s/%s\r\n", g.zBaseURL, zURL);
+ }
cgi_append_header(zLocation);
cgi_reset_content();
cgi_printf("<html>\n<p>Redirect to %h</p>\n</html>\n", zURL);
cgi_set_status(302, "Moved Temporarily");
free(zLocation);
cgi_reply();
exit(0);
+}
+void cgi_redirectf(const char *zFormat, ...){
+ va_list ap;
+ va_start(ap, zFormat);
+ cgi_redirect(vmprintf(zFormat, ap));
+ va_end(ap);
}
/*
** Information about all query parameters and cookies are stored
@@ -323,9 +337,9 @@
**
** zName and zValue are not copied and must not change or be
** deallocated after this routine returns.
*/
-static void cgi_set_parameter_nocopy(const char *zName, const char *zValue){
+void cgi_set_parameter_nocopy(const char *zName, const char *zValue){
if( nAllocQP<=nUsedQP ){
nAllocQP = nAllocQP*2 + 10;
aParamQP = realloc( aParamQP, nAllocQP*sizeof(aParamQP[0]) );
if( aParamQP==0 ) exit(1);
@@ -345,8 +359,20 @@
** Copies are made of both the zName and zValue parameters.
*/
void cgi_set_parameter(const char *zName, const char *zValue){
cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue));
+}
+
+/*
+** Replace a parameter with a new value.
+*/
+void cgi_replace_parameter(const char *zName, const char *zValue){
+ int i;
+ for(i=0; i<nUsedQP; i++){
+ if( strcmp(aParamQP[i].zName,zName)==0 ){
+ aParamQP[i].zValue = zValue;
+ }
+ }
}
/*
** Add a query parameter. The zName portion is fixed but a copy
@@ -703,8 +729,20 @@
return zDefault;
}
/*
+** Return the name of the i-th CGI parameter. Return NULL if there
+** are fewer than i registered CGI parmaeters.
+*/
+const char *cgi_parameter_name(int i){
+ if( i>=0 && i<nUsedQP ){
+ return aParamQP[i].zName;
+ }else{
+ return 0;
+ }
+}
+
+/*
** Print CGI debugging messages.
*/
void cgi_debug(const char *zFormat, ...){
va_list ap;
@@ -896,25 +934,15 @@
cgi_printf("%*s</select>\n", in, "");
}
/*
-** This function implements the callback from vxprintf.
-**
-** This routine sends nNewChar characters of text in zNewText to
-** CGI reply content buffer.
-*/
-static void sout(void *NotUsed, const char *zNewText, int nNewChar){
- cgi_append_content(zNewText, nNewChar);
-}
-
-/*
** This routine works like "printf" except that it has the
** extra formatting capabilities such as %h and %t.
*/
void cgi_printf(const char *zFormat, ...){
va_list ap;
va_start(ap,zFormat);
- vxprintf(sout,0,zFormat,ap);
+ vxprintf(&cgiContent,zFormat,ap);
va_end(ap);
}
/*
@@ -921,9 +949,9 @@
** This routine works like "vprintf" except that it has the
** extra formatting capabilities such as %h and %t.
*/
void cgi_vprintf(const char *zFormat, va_list ap){
- vxprintf(sout,0,zFormat,ap);
+ vxprintf(&cgiContent,zFormat,ap);
}
/*
@@ -949,9 +977,9 @@
"<html><body><h1>Internal Server Error</h1>\n"
"<plaintext>"
);
va_start(ap, zFormat);
- vxprintf(sout,0,zFormat,ap);
+ vxprintf(&cgiContent,zFormat,ap);
va_end(ap);
cgi_reply();
exit(1);
}
@@ -1017,9 +1045,9 @@
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
if( zToken[i] ) zToken[i++] = 0;
cgi_setenv("PATH_INFO", zToken);
cgi_setenv("QUERY_STRING", &zToken[i]);
- if( getpeername(fileno(stdin), (struct sockaddr*)&remoteName, &size)>=0 ){
+ if( getpeername(fileno(stdin), (struct sockaddr*)&remoteName, (socklen_t*)&size)>=0 ){
char *zIpAddr = inet_ntoa(remoteName.sin_addr);
cgi_setenv("REMOTE_ADDR", zIpAddr);
/* Set the Global.zIpAddr variable to the server we are talking to.
@@ -1077,8 +1105,12 @@
** out of this procedure call. The child will handle the request.
** The parent never returns from this procedure.
*/
void cgi_http_server(int iPort){
+#ifdef __MINGW32__
+ fprintf(stderr,"server not yet available in windows version of fossil\n");
+ exit(1);
+#else
int listener; /* The server socket */
int connection; /* A socket for each individual connection */
fd_set readfds; /* Set of file descriptors for select() */
size_t lenaddr; /* Length of the inaddr structure */
@@ -1116,9 +1148,9 @@
FD_ZERO(&readfds);
FD_SET( listener, &readfds);
if( select( listener+1, &readfds, 0, 0, &delay) ){
lenaddr = sizeof(inaddr);
- connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr);
+ connection = accept(listener, (struct sockaddr*)&inaddr, (socklen_t*) &lenaddr);
if( connection>=0 ){
child = fork();
if( child!=0 ){
if( child>0 ) nchildren++;
@@ -1143,8 +1175,9 @@
}
}
/* NOT REACHED */
exit(1);
+#endif
}
/*
** Name of days and months.