Update of /cvsroot/aolserver/aolserver/nsd In directory vz-cvs-4.sog:/tmp/cvs-serv9402/nsd Modified Files: conn.c connio.c driver.c filter.c nsd.h op.c queue.c server.c tclrequest.c Log Message: add various functions, mostly from SF RFEs - pre-write filter, response content modification, insert/append filter, priority filters, ns_conn gzip flag, re-run filters on redirect with new config option "filterredirect", add new constants, fix STREQ macro Index: nsd.h =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/nsd.h,v retrieving revision 1.124 retrieving revision 1.125 diff -C2 -d -r1.124 -r1.125 *** nsd.h 7 Oct 2011 17:06:30 -0000 1.124 --- nsd.h 11 Oct 2011 08:03:27 -0000 1.125 *************** *** 513,516 **** --- 513,522 ---- /* + * output buffers, used if needed + */ + char *sbuf; /* pointer to content requested to be sent */ + Tcl_DString *rbuf; /* buffer for response content. */ + + /* * The following offsets are used to manage the * buffer read-ahead process. *************** *** 585,588 **** --- 591,595 ---- #define SERV_NOTICEDETAIL 0x0008 /* Add detail to notice messages. */ #define SERV_GZIP 0x0010 /* Enable GZIP compression. */ + #define SERV_FILTERREDIRECT 0x0020 /* re-run filters on redirects */ /* *************** *** 1099,1102 **** --- 1106,1110 ---- extern int NsConnRunProxyRequest(Ns_Conn *conn); + extern int NsConnRunDirectRequest(Ns_Conn *conn); #endif Index: conn.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/conn.c,v retrieving revision 1.51 retrieving revision 1.52 diff -C2 -d -r1.51 -r1.52 *** conn.c 5 Aug 2011 11:49:45 -0000 1.51 --- conn.c 11 Oct 2011 08:03:27 -0000 1.52 *************** *** 1006,1009 **** --- 1006,1065 ---- *---------------------------------------------------------------------- * + * Ns_ConnGetResponseContent + * Ns_ConnSetResponseContent + * Ns_ConnAppendResponseContent + * + * get, set, or append to the response content + * + * Results: + * the current content buffer + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + char *Ns_ConnGetResponseContent(Ns_Conn *conn) + { + Conn *connPtr = (Conn *) conn; + + if (connPtr->rbuf!= NULL) { + return Tcl_DStringValue(connPtr->rbuf); + } else { + return connPtr->sbuf; + } + } + + char *Ns_ConnSetResponseContent(Ns_Conn *conn, char *content) + { + Conn *connPtr = (Conn *) conn; + + if (connPtr->rbuf == NULL) { + connPtr->rbuf=ns_malloc(sizeof(Tcl_DString)); + Tcl_DStringInit(connPtr->rbuf); + } + Tcl_DStringSetLength(connPtr->rbuf,0); + Tcl_DStringAppend(connPtr->rbuf, content, -1); + return Tcl_DStringValue(connPtr->rbuf); + } + + char *Ns_ConnAppendResponseContent(Ns_Conn *conn, char *content) + { + Conn *connPtr = (Conn *) conn; + + if (connPtr->rbuf == NULL) { + connPtr->rbuf=ns_malloc(sizeof(Tcl_DString)); + Tcl_DStringInit(connPtr->rbuf); + Tcl_DStringAppend(connPtr->rbuf, connPtr->sbuf, -1); + } + Tcl_DStringAppend(connPtr->rbuf, content, -1); + return Tcl_DStringValue(connPtr->rbuf); + } + + + + /* + *---------------------------------------------------------------------- + * * NsTclConnObjCmd -- * *************** *** 1044,1048 **** "query", "request", "server", "sock", "start", "status", "url", "urlc", "urlencoding", "urlv", "version", ! "write_encoded", "interp", NULL }; enum { --- 1100,1104 ---- "query", "request", "server", "sock", "start", "status", "url", "urlc", "urlencoding", "urlv", "version", ! "write_encoded", "interp","gzip","responsecontent", NULL }; enum { *************** *** 1055,1059 **** CProtocolIdx, CQueryIdx, CRequestIdx, CServerIdx, CSockIdx, CStartIdx, CStatusIdx, CUrlIdx, CUrlcIdx, CUrlEncodingIdx, ! CUrlvIdx, CVersionIdx, CWriteEncodedIdx, CInterpIdx } opt; --- 1111,1116 ---- CProtocolIdx, CQueryIdx, CRequestIdx, CServerIdx, CSockIdx, CStartIdx, CStatusIdx, CUrlIdx, CUrlcIdx, CUrlEncodingIdx, ! CUrlvIdx, CVersionIdx, CWriteEncodedIdx, CInterpIdx, ! CGzipIdx, CRespContentIdx } opt; *************** *** 1394,1397 **** --- 1451,1475 ---- Tcl_SetLongObj(result, (long) interp); break; + + case CGzipIdx: + if (objc > 2) { + int flag; + if (Tcl_GetBooleanFromObj(interp, objv[2], &flag) != TCL_OK) { + return TCL_ERROR; + } + Ns_ConnSetGzipFlag(conn, flag); + } + Tcl_SetIntObj(result, Ns_ConnGetGzipFlag(conn)); + break; + + case CRespContentIdx: + if (objc == 2) { + Tcl_SetResult(interp, Ns_ConnGetResponseContent(connPtr), TCL_STATIC); + } else if (objc == 3) { + Tcl_SetResult(interp, Ns_ConnSetResponseContent(connPtr, Tcl_GetString(objv[2])), TCL_STATIC); + } else { + Tcl_WrongNumArgs(interp, 2, objv, "?value?"); + return TCL_ERROR; + } } *************** *** 1640,1643 **** --- 1718,1724 ---- connPtr->sockPtr->sock = sock; } + if (chan != NULL) { + Tcl_Ungets(chan,connPtr->content, connPtr->avail, 0); + } return chan; Index: connio.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/connio.c,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** connio.c 8 Dec 2009 04:12:19 -0000 1.28 --- connio.c 11 Oct 2011 08:03:27 -0000 1.29 *************** *** 136,139 **** --- 136,149 ---- int status; + connPtr->sbuf=buf; + if (NsRunFilters((Ns_Conn *) connPtr, NS_FILTER_PRE_WRITE) != NS_OK) { + return NS_ERROR; + } + if (connPtr->rbuf != NULL) { + /* the content was set by pre-write filters */ + buf=Tcl_DStringValue(connPtr->rbuf); + len=Tcl_DStringLength(connPtr->rbuf); + } + Tcl_DStringInit(&enc); Tcl_DStringInit(&gzip); Index: op.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/op.c,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** op.c 16 Jul 2011 09:25:29 -0000 1.17 --- op.c 11 Oct 2011 08:03:27 -0000 1.18 *************** *** 291,295 **** { Conn *connPtr = (Conn *) conn; - int status; ++connPtr->recursionCount; --- 291,294 ---- *************** *** 305,328 **** */ ! status = Ns_AuthorizeRequest(Ns_ConnServer(conn), conn->request->method, ! conn->request->url, conn->authUser, ! conn->authPasswd, Ns_ConnPeer(conn)); ! switch (status) { ! case NS_OK: ! status = Ns_ConnRunRequest(conn); ! break; ! case NS_FORBIDDEN: ! status = Ns_ConnReturnForbidden(conn); ! break; ! case NS_UNAUTHORIZED: ! status = Ns_ConnReturnUnauthorized(conn); ! break; ! case NS_ERROR: ! default: ! status = Ns_ConnReturnInternalError(conn); ! break; ! } ! ! return status; } --- 304,308 ---- */ ! return NsConnRunDirectRequest(conn); } *************** *** 472,475 **** --- 452,527 ---- *---------------------------------------------------------------------- * + * NsConnRunDirectRequest -- + * + * runs pre/post-auth filters and main connection + * + * Results: + * Standard request procedure result, normally NS_OK. + * + * Side effects: + * Depends on request procedure. + * + *---------------------------------------------------------------------- + */ + + int NsConnRunDirectRequest(Ns_Conn *conn) + { + int status; + Conn *connPtr = (Conn *) conn; + + /* + * always run pre/post-auth filters on initial request; + * if this is an internal redirect then only run them + * if the "filterredirect" option is set + */ + int runFilters = (connPtr->recursionCount == 0 || + connPtr->servPtr->opts.flags & SERV_FILTERREDIRECT); + + status = runFilters ? + NsRunFilters(conn, NS_FILTER_PRE_AUTH) : + NS_OK; + if (status == NS_OK) { + status = Ns_AuthorizeRequest(Ns_ConnServer(conn), + conn->request->method, conn->request->url, + conn->authUser, conn->authPasswd, Ns_ConnPeer(conn)); + switch (status) { + case NS_OK: + status = runFilters ? + NsRunFilters(conn, NS_FILTER_POST_AUTH) : + NS_OK; + if (status == NS_OK) { + status = Ns_ConnRunRequest(conn); + } + break; + + case NS_FORBIDDEN: + Ns_ConnReturnForbidden(conn); + break; + + case NS_UNAUTHORIZED: + Ns_ConnReturnUnauthorized(conn); + break; + + case NS_ERROR: + default: + Ns_ConnReturnInternalError(conn); + break; + } + } else if (status != NS_FILTER_RETURN) { + /* if not ok or filter_return, then the pre-auth filter coughed + * an error. We are not going to proceed, but also we + * can't count on the filter to have sent a response + * back to the client. So, send an error response. + */ + Ns_ConnReturnInternalError(conn); + status = NS_FILTER_RETURN; /* to allow tracing to happen */ + } + return status; + } + + + /* + *---------------------------------------------------------------------- + * * FreeReq -- * Index: filter.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/filter.c,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** filter.c 28 Sep 2002 19:23:39 -0000 1.10 --- filter.c 11 Oct 2011 08:03:27 -0000 1.11 *************** *** 58,61 **** --- 58,63 ---- } Trace; + #define FILTER_GETPRIO(when) ((signed char)((when & 0xFF000000) >> 24)) + static Trace *NewTrace(Ns_TraceProc *proc, void *arg); static void RunTraces(Ns_Conn *conn, Trace *firstPtr); *************** *** 96,104 **** fPtr->when = when; fPtr->arg = arg; - fPtr->nextPtr = NULL; fPtrPtr = &servPtr->filter.firstFilterPtr; ! while (*fPtrPtr != NULL) { fPtrPtr = &((*fPtrPtr)->nextPtr); } *fPtrPtr = fPtr; return (void *) fPtr; --- 98,115 ---- fPtr->when = when; fPtr->arg = arg; fPtrPtr = &servPtr->filter.firstFilterPtr; ! /* locate the first filter at this priority */ ! while (*fPtrPtr != NULL ! && FILTER_GETPRIO(fPtr->when) > FILTER_GETPRIO((*fPtrPtr)->when)) { fPtrPtr = &((*fPtrPtr)->nextPtr); } + /* if appending, locate last filter in the same priority group */ + if (!(when & NS_FILTER_INSERT)) { + while (*fPtrPtr != NULL + && FILTER_GETPRIO(fPtr->when) == FILTER_GETPRIO((*fPtrPtr)->when)) { + fPtrPtr = &((*fPtrPtr)->nextPtr); + } + } + fPtr->nextPtr = *fPtrPtr; *fPtrPtr = fPtr; return (void *) fPtr; Index: server.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/server.c,v retrieving revision 1.50 retrieving revision 1.51 diff -C2 -d -r1.50 -r1.51 *** server.c 7 Oct 2011 17:06:31 -0000 1.50 --- server.c 11 Oct 2011 08:03:27 -0000 1.51 *************** *** 271,274 **** --- 271,277 ---- servPtr->opts.flags |= SERV_NOTICEDETAIL; } + if (!Ns_ConfigGetBool(path, "filterredirect", &i) || i) { + servPtr->opts.flags |= SERV_FILTERREDIRECT; + } p = Ns_ConfigGetValue(path, "headercase"); if (p != NULL && STRIEQ(p, "tolower")) { Index: queue.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/queue.c,v retrieving revision 1.50 retrieving revision 1.51 diff -C2 -d -r1.50 -r1.51 *** queue.c 5 Aug 2011 11:49:45 -0000 1.50 --- queue.c 11 Oct 2011 08:03:27 -0000 1.51 *************** *** 597,635 **** status = NsConnRunProxyRequest((Ns_Conn *) connPtr); } else { ! status = NsRunFilters(conn, NS_FILTER_PRE_AUTH); ! if (status == NS_OK) { ! status = Ns_AuthorizeRequest(servPtr->server, ! connPtr->request->method, connPtr->request->url, ! connPtr->authUser, connPtr->authPasswd, connPtr->peer); ! switch (status) { ! case NS_OK: ! status = NsRunFilters(conn, NS_FILTER_POST_AUTH); ! if (status == NS_OK) { ! status = Ns_ConnRunRequest(conn); ! } ! break; ! ! case NS_FORBIDDEN: ! Ns_ConnReturnForbidden(conn); ! break; ! ! case NS_UNAUTHORIZED: ! Ns_ConnReturnUnauthorized(conn); ! break; ! ! case NS_ERROR: ! default: ! Ns_ConnReturnInternalError(conn); ! break; ! } ! } else if (status != NS_FILTER_RETURN) { ! /* if not ok or filter_return, then the pre-auth filter coughed ! * an error. We are not going to proceed, but also we ! * can't count on the filter to have sent a response ! * back to the client. So, send an error response. ! */ ! Ns_ConnReturnInternalError(conn); ! status = NS_FILTER_RETURN; /* to allow tracing to happen */ ! } } Ns_ConnClose(conn); --- 597,601 ---- status = NsConnRunProxyRequest((Ns_Conn *) connPtr); } else { ! status = NsConnRunDirectRequest((Ns_Conn *) connPtr); } Ns_ConnClose(conn); Index: tclrequest.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/tclrequest.c,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** tclrequest.c 8 Dec 2009 04:12:19 -0000 1.14 --- tclrequest.c 11 Oct 2011 08:03:27 -0000 1.15 *************** *** 258,279 **** int when, i; static CONST char *wopt[] = { ! "read", "write", "prequeue", "preauth", "postauth", "trace", NULL }; enum { ! ReadIdx, WriteIdx, PreQueueIdx, PreAuthIdx, PostAuthIdx, TraceIdx, } widx; if (objc < 2) { ! Tcl_WrongNumArgs(interp, 1, objv, "option ?args?"); return TCL_ERROR; } ! if (objc != 5 && objc != 6) { ! Tcl_WrongNumArgs(interp, 1, objv, "when method url script ?arg?"); ! return TCL_ERROR; } if (Tcl_ListObjGetElements(interp, objv[1], &lobjc, &lobjv) != TCL_OK) { return TCL_ERROR; } - when = 0; for (i = 0; i < lobjc; ++i) { if (Tcl_GetIndexFromObj(interp, lobjv[i], wopt, "when", 0, --- 258,305 ---- int when, i; static CONST char *wopt[] = { ! "read", "prewrite", "write", "prequeue", "preauth", "postauth", "trace", NULL }; enum { ! ReadIdx, PreWriteIdx, WriteIdx, PreQueueIdx, PreAuthIdx, PostAuthIdx, TraceIdx, } widx; if (objc < 2) { ! error: ! Tcl_SetResult(interp, "wrong arguments: should be ns_register_filter " ! "?-insert? ?-priority num? when method url script ?arg?", ! TCL_STATIC); return TCL_ERROR; } ! when = 0; ! for (i = 1; i < objc; i++) { ! char *arg = Tcl_GetString(objv[i]); ! if (*arg != '-') break; ! if (STRIEQ(arg, "-insert")) { ! when |= NS_FILTER_INSERT; ! } else if (STRIEQ(arg, "-priority")) { ! if (++i >= objc) goto error; ! int prio; ! if (Tcl_GetIntFromObj(interp,objv[i],&prio) != TCL_OK) { ! return TCL_ERROR; ! } ! if (prio < -128 || prio > 127) { ! Tcl_SetResult(interp, "priority must be in range -128 .. 127", ! TCL_STATIC); ! return TCL_ERROR; ! } ! when |= NS_FILTER_PRIORITY(prio); ! } else { ! goto error; ! } ! } ! objc-=(i-1); ! objv+=(i-1); ! ! if (objc < 5 || objc > 6) { ! goto error; } if (Tcl_ListObjGetElements(interp, objv[1], &lobjc, &lobjv) != TCL_OK) { return TCL_ERROR; } for (i = 0; i < lobjc; ++i) { if (Tcl_GetIndexFromObj(interp, lobjv[i], wopt, "when", 0, *************** *** 285,288 **** --- 311,317 ---- when |= NS_FILTER_READ; break; + case PreWriteIdx: + when |= NS_FILTER_PRE_WRITE; + break; case WriteIdx: when |= NS_FILTER_WRITE; *************** *** 514,517 **** --- 543,549 ---- Tcl_DStringAppendElement(&script, "read"); break; + case NS_FILTER_PRE_WRITE: + Tcl_DStringAppendElement(&script, "prewrite"); + break; case NS_FILTER_WRITE: Tcl_DStringAppendElement(&script, "write"); Index: driver.c =================================================================== RCS file: /cvsroot/aolserver/aolserver/nsd/driver.c,v retrieving revision 1.62 retrieving revision 1.63 diff -C2 -d -r1.62 -r1.63 *** driver.c 9 Jul 2011 10:06:46 -0000 1.62 --- driver.c 11 Oct 2011 08:03:27 -0000 1.63 *************** *** 2326,2329 **** --- 2326,2334 ---- Ns_SetFree(connPtr->outputheaders); + if (connPtr->rbuf != NULL) { + Tcl_DStringFree(connPtr->rbuf); + ns_free(connPtr->rbuf); + } + /* * Truncate the I/O buffers, zero remaining elements of the Conn, |