/* * The contents of this file are subject to the AOLserver Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://aolserver.com/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is AOLserver Code and related documentation * distributed by AOL. * * The Initial Developer of the Original Code is America Online, * Inc. Portions created by AOL are Copyright (C) 1999 America Online, * Inc. All Rights Reserved. * * Alternatively, the contents of this file may be used under the terms * of the GNU General Public License (the "GPL"), in which case the * provisions of GPL are applicable instead of those above. If you wish * to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the * License, indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by the GPL. * If you do not delete the provisions above, a recipient may use your * version of this file under either the License or the GPL. */ /* * adprequest.c -- * * ADP connection request support. */ static const char *RCSID = "@(#) $Header: /cvsroot/aolserver/aolserver/nsd/adprequest.c,v 1.32 2006/06/23 02:18:20 shmooved Exp $, compiled: " __DATE__ " " __TIME__; #include "nsd.h" /* * Static functions defined in this file. */ /* *---------------------------------------------------------------------- * * NsAdpProc -- * * Check for a normal file and call Ns_AdpRequest. * * Results: * A standard AOLserver request result. * * Side effects: * Depends on code embedded within page. * *---------------------------------------------------------------------- */ int NsAdpProc(void *arg, Ns_Conn *conn) { Ns_Time *ttlPtr = arg; Ns_DString file; int status; Ns_DStringInit(&file); Ns_UrlToFile(&file, Ns_ConnServer(conn), conn->request->url); status = Ns_AdpRequestEx(conn, file.string, ttlPtr); Ns_DStringFree(&file); return status; } /* *---------------------------------------------------------------------- * * Ns_AdpRequest, Ns_AdpRequestEx - * * Invoke a file for an ADP request with an optional cache * timeout. * * Results: * A standard AOLserver request result. * * Side effects: * Depends on code embedded within page. * *---------------------------------------------------------------------- */ int Ns_AdpRequest(Ns_Conn *conn, char *file) { return Ns_AdpRequestEx(conn, file, NULL); } int Ns_AdpRequestEx(Ns_Conn *conn, char *file, Ns_Time *ttlPtr) { Conn *connPtr = (Conn *) conn; Tcl_Interp *interp; NsInterp *itPtr; char *start, *type; Ns_Set *query; NsServer *servPtr; Tcl_Obj *objv[2]; int result; interp = Ns_GetConnInterp(conn); itPtr = NsGetInterpData(interp); /* * Verify the file exists. */ if (access(file, R_OK) != 0) { return Ns_ConnReturnNotFound(conn); } /* * Set the output type based on the file type. */ type = Ns_GetMimeType(file); if (type == NULL || STREQ(type, "*/*")) { type = NSD_TEXTHTML; } Ns_ConnSetType(conn, type); Ns_ConnSetStatus(conn, 200); /* * Enable TclPro debugging if requested. */ servPtr = connPtr->servPtr; if ((itPtr->servPtr->adp.flags & ADP_DEBUG) && STREQ(conn->request->method, "GET") && (query = Ns_ConnGetQuery(conn)) != NULL) { itPtr->adp.debugFile = Ns_SetIGet(query, "debug"); } /* * Include the ADP with the special start page and null args. */ itPtr->adp.conn = conn; start = servPtr->adp.startpage ? servPtr->adp.startpage : file; objv[0] = Tcl_NewStringObj(start, -1); objv[1] = Tcl_NewStringObj(file, -1); Tcl_IncrRefCount(objv[0]); Tcl_IncrRefCount(objv[1]); result = NsAdpInclude(itPtr, 2, objv, start, ttlPtr); Tcl_DecrRefCount(objv[0]); Tcl_DecrRefCount(objv[1]); if (NsAdpFlush(itPtr, 0) != TCL_OK || result != TCL_OK) { return NS_ERROR; } return NS_OK; } /* *---------------------------------------------------------------------- * * NsAdpFlush -- * * Flush output to connection response buffer. * * Results: * TCL_ERROR if flush failed, TCL_OK otherwise. * * Side effects: * Output buffer is truncated in all cases. * *---------------------------------------------------------------------- */ int NsAdpFlush(NsInterp *itPtr, int stream) { Ns_Conn *conn; Tcl_Interp *interp = itPtr->interp; int len, wrote, result = TCL_ERROR, flags = itPtr->adp.flags; char *buf; /* * Verify output context. */ if (itPtr->adp.conn == NULL && itPtr->adp.chan == NULL) { Tcl_SetResult(interp, "no adp output context", TCL_STATIC); return TCL_ERROR; } buf = itPtr->adp.output.string; len = itPtr->adp.output.length; /* * If enabled, trim leading whitespace if no content has been sent yet. */ if ((flags & ADP_TRIM) && !(flags & ADP_FLUSHED)) { while (len > 0 && isspace(UCHAR(*buf))) { ++buf; --len; } } /* * Leave error messages if output is disabled or failed. Otherwise, * send data if there's any to send or stream is 0, indicating this * is the final flush call. */ Tcl_ResetResult(interp); if (itPtr->adp.exception == ADP_ABORT) { Tcl_SetResult(interp, "adp flush disabled: adp aborted", TCL_STATIC); } else if (len == 0 && stream) { result = TCL_OK; } else { if (itPtr->adp.chan != NULL) { while (len > 0) { wrote = Tcl_Write(itPtr->adp.chan, buf, len); if (wrote < 0) { Tcl_AppendResult(interp, "write failed: ", Tcl_PosixError(interp), NULL); break; } buf += wrote; len -= wrote; } if (len == 0) { result = TCL_OK; } } else if (NsTclGetConn(itPtr, &conn) == TCL_OK) { if (conn->flags & NS_CONN_CLOSED) { Tcl_SetResult(interp, "adp flush failed: connection closed", TCL_STATIC); } else { if (flags & ADP_GZIP) { Ns_ConnSetGzipFlag(conn, 1); } if (!(flags & ADP_FLUSHED) && (flags & ADP_EXPIRE)) { Ns_ConnCondSetHeaders(conn, "Expires", "now"); } if (Ns_ConnFlush(itPtr->conn, buf, len, stream) == NS_OK) { result = TCL_OK; } else { Tcl_SetResult(interp, "adp flush failed: connection flush error", TCL_STATIC); } } } itPtr->adp.flags |= ADP_FLUSHED; /* * Raise an abort exception if autoabort is enabled. */ if (result != TCL_OK && (flags & ADP_AUTOABORT)) { Tcl_AddErrorInfo(interp, "\n abort exception raised"); NsAdpLogError(itPtr); itPtr->adp.exception = ADP_ABORT; } } Tcl_DStringTrunc(&itPtr->adp.output, 0); if (!stream) { NsAdpReset(itPtr); } return result; }