int SSIEngine::startExecute( HttpSession *pSession, SSIScript * pScript ) { if ( !pScript ) return SC_500; SSIRuntime * pRuntime = pSession->getReq()->getSSIRuntime(); if ( !pRuntime ) { char ct[]= "text/html"; HttpReq * pReq = pSession->getReq(); pRuntime = new SSIRuntime(); if (!pRuntime ) return SC_500; pRuntime->init(); pRuntime->initConfig( pReq->getSSIConfig() ); pReq->setSSIRuntime( pRuntime ); pSession->getResp()->reset(); //pSession->getResp()->prepareHeaders( pReq ); //pSession->setupChunkOS( 0 ); HttpCgiTool::processContentType( pReq, pSession->getResp(), ct , 9 ); // pSession->setupRespCache(); if ( pReq->isXbitHackFull() ) { pSession->getResp()->appendLastMod( pReq->getLastMod() ); } int status = pReq->getStatusCode(); if (( status >= SC_300 )&&( status < SC_400 )) { if ( pReq->getLocation() != NULL ) { pSession->addLocationHeader(); } } pSession->setupGzipFilter(); pReq->andGzip( ~GZIP_ENABLED ); //disable GZIP } if ( pRuntime->push( pScript ) == -1 ) return SC_500; pSession->getReq()->backupPathInfo(); pScript->resetRuntime(); return resumeExecute( pSession ); }
int HttpCgiTool::processHeaderLine( HttpExtConnector * pExtConn, const char * pLineBegin, const char * pLineEnd, int &status ) { int index; const char * pKeyEnd; const char * pValue = pLineBegin; char * p; HttpResp* pResp = pExtConn->getHttpConn()->getResp(); HttpReq * pReq = pExtConn->getHttpConn()->getReq(); index = HttpHeader::getRespHeaderIndex( pValue ); if ( index < HttpHeader::H_HEADER_END ) { pValue += HttpHeader::getHeaderStringLen( index ); while( isspace(*pValue) ) ++pValue; pKeyEnd = pValue; if ( *pValue != ':' ) { index = HttpHeader::H_HEADER_END; } else { do { ++pValue; } while( isspace(*pValue) ); } } if ( index == HttpHeader::H_HEADER_END ) { pKeyEnd = (char *)memchr( pValue, ':', pLineEnd - pValue ); if ( pKeyEnd != NULL ) { pValue = pKeyEnd + 1; while( isspace(*pValue) ) ++pValue; } else { if ( !isspace( *pLineBegin ) ) return 0; } } switch( index ) { case HttpHeader::H_CONTENT_TYPE: p = (char *)memchr( pValue, ';', pLineEnd - pValue ); if ( pReq->gzipAcceptable() ) { register char ch = 0; register char *p1; if ( p ) { p1 = (char*)p; } else p1 = (char*)pLineEnd; ch = *p1; *p1 = 0; if ( !HttpGlobals::getMime()->compressable( pValue ) ) pReq->setGzip( 0 ); *p1 = ch; } if ( pReq->isKeepAlive() ) pReq->smartKeepAlive( pValue ); { if ( !HttpMime::needCharset( pValue ) ) break; const AutoStr2 * pCharset = pReq->getDefaultCharset(); if ( !pCharset ) break; if ( p ) { while( isspace( *(++p) ) ) ; if ( strncmp( p, "charset=", 8 ) == 0 ) break; } AutoBuf& buf = pResp->getOutputBuf(); if ( buf.available() < pLineEnd - pLineBegin + pCharset->len() + 4 ) { buf.grow( pLineEnd - pLineBegin + pCharset->len() + 4 ); } buf.appendNoCheck( pLineBegin, pLineEnd - pLineBegin ); buf.appendNoCheck( pCharset->c_str(), pCharset->len() ); buf.appendNoCheck( "\r\n", 2 ); } return 0; case HttpHeader::H_CONTENT_ENCODING: pReq->setGzip( 0 ); break; case HttpHeader::H_LOCATION: if ( pReq->getStatusCode() != SC_200 ) break; if ( *pValue != '/' ) { //set status code to 307 pReq->setStatusCode( SC_302 ); } else { pReq->setLocation( pValue, pLineEnd - pValue ); return 0; } break; case HttpHeader::CGI_STATUS: index = HttpStatusCode::codeToIndex( pValue ); if ( index != -1 ) { pReq->updateNoRespBodyByStatus( index ); if (( index >= SC_300 )&&( index < SC_400 )) { if ( *pReq->getLocation() ) { pResp->appendHeader( "Location: ", 10, pReq->getLocation(), pReq->getLocationLen() ); pReq->clearLocation(); } } if (( status & HEC_RESP_AUTHORIZER )&&( index == SC_200)) status |= HEC_RESP_AUTHORIZED; } return 0; case HttpHeader::H_TRANSFER_ENCODING: pResp->setContentLen( -1 ); return 0; case HttpHeader::H_PROXY_CONNECTION: case HttpHeader::H_CONNECTION: if ( strncasecmp( pValue, "close", 5 ) == 0 ) status |= HEC_RESP_CONN_CLOSE; return 0; case HttpHeader::H_CONTENT_LENGTH: if ( pResp->getContentLen() >= 0 ) { long lContentLen = strtol( pValue, NULL, 10 ); if (( lContentLen >= 0 )&&( lContentLen != LONG_MAX )) pResp->setContentLen( lContentLen ); } //fall through case HttpHeader::H_KEEP_ALIVE: case HttpHeader::H_SERVER: case HttpHeader::H_DATE: return 0; default: //"script-control: no-abort" is not supported break; } if ( status & HEC_RESP_AUTHORIZED ) { if (strncasecmp( pLineBegin, "Variable-", 9 ) == 0 ) { if ( pKeyEnd > pLineBegin + 9 ) pReq->addEnv( pLineBegin + 9, pKeyEnd - pLineBegin - 9, pValue, pLineEnd - pValue ); } return 0; } return pResp->appendHeaderLine( pLineBegin, pLineEnd ); }
int RequestVars::getReqVar( HttpSession *pSession, int type, char * &pValue, int bufLen) { HttpReq * pReq = pSession->getReq(); int i; char *p; if ( type < REF_STRING ) { pValue = (char *)pReq->getHeader( type ); if ( *pValue ) return pReq->getHeaderLen( type ); else return 0; } switch( type ) { case REF_REMOTE_HOST: //FIXME: use remote addr for now case REF_REMOTE_ADDR: pValue = (char *)pSession->getPeerAddrString(); return pSession->getPeerAddrStrLen(); case REF_REMOTE_PORT: return snprintf( pValue, bufLen, "%hu", pSession->getRemotePort() ); case REF_REMOTE_USER: pValue = (char *)pReq->getAuthUser(); return strlen( pValue ); case REF_REMOTE_IDENT: //do not support; return 0; case REF_REQ_METHOD: i = pReq->getMethod(); strcpy(pValue, HttpMethod::get( i ) ); return HttpMethod::getLen( i ); case REF_QUERY_STRING: pValue = (char *)pReq->getQueryString(); return pReq->getQueryStringLen(); case REF_AUTH_TYPE: //FIXME: hard code for now strncpy( pValue, "Basic", 6 ); return 5; case REF_REQUST_FN: case REF_SCRIPTFILENAME: case REF_SCRIPT_BASENAME: case REF_REQ_BASENAME: { const AutoStr2 * psTemp = pReq->getRealPath(); if ( psTemp ) { if (( type == REF_SCRIPT_BASENAME )|| ( type == REF_REQ_BASENAME )) { const char * pEnd = psTemp->c_str() + psTemp->len(); pValue = (char *)pEnd; while( pValue[-1] != '/' ) --pValue; return pEnd - pValue; } pValue = (char *)psTemp->c_str(); return psTemp->len(); } else return 0; } case REF_SCRIPT_UID: case REF_SCRIPT_GID: case REF_SCRIPT_USERNAME: case REF_SCRIPT_GRPNAME: case REF_SCRIPT_MODE: { const AutoStr2 * psTemp = pReq->getRealPath(); if ( psTemp ) { struct stat& st = pReq->getFileStat(); if ( type == REF_SCRIPT_UID ) { return snprintf( pValue, bufLen, "%d", st.st_uid ); } else if ( type == REF_SCRIPT_GID ) { return snprintf( pValue, bufLen, "%d", st.st_gid ); } else if ( type == REF_SCRIPT_MODE ) { return snprintf( pValue, bufLen, "%o", st.st_mode ); } else if ( type == REF_SCRIPT_USERNAME ) { struct passwd * pw = getpwuid( st.st_uid ); if ( pw ) return snprintf( pValue, bufLen, "%s", pw->pw_name ); } else { struct group * gr = getgrgid( st.st_gid ); if ( gr ) return snprintf( pValue, bufLen, "%s", gr->gr_name ); } } return 0; } case REF_PATH_INFO: pValue = (char *)pReq->getPathInfo(); return pReq->getPathInfoLen(); case REF_SCRIPT_NAME: pValue = (char *)pReq->getURI(); return pReq->getScriptNameLen(); case REF_SCRIPT_URI: p = pValue; if ( pSession->isSSL() ) { strcpy( p, "https://" ); p += 8; } else { strcpy( p, "http://" ); p += 7; } i = pReq->getHeaderLen( HttpHeader::H_HOST ); memmove( p, pReq->getHeader( HttpHeader::H_HOST ), i ); p += i; i = pReq->getOrgURILen(); memmove( p, pReq->getOrgURI(), i ); p += i; return p - pValue; case REF_ORG_REQ_URI: pValue = (char *)pReq->getOrgReqURL(); return pReq->getOrgReqURILen(); case REF_DOCUMENT_URI: return pReq->getDecodedOrgReqURI( pValue ); case REF_REQ_URI: pValue = (char *)pReq->getOrgReqURL(); return pReq->getOrgReqURLLen(); case REF_DOC_ROOT: pValue = (char *)pReq->getDocRoot()->c_str(); return pReq->getDocRoot()->len()-1; case REF_SERVER_ADMIN: if ( pReq->getVHost() ) { const AutoStr2 * pEmail = pReq->getVHost()->getAdminEmails(); pValue = (char *)pEmail->c_str(); return pEmail->len(); } return 0; case REF_VH_CNAME: if ( pReq->getVHost() ) { pValue = (char *)pReq->getVHost()->getVhName( i ); return i; } return 0; case REF_SERVER_NAME: pValue = (char *)pReq->getHostStr(); return pReq->getHostStrLen(); case REF_SERVER_ADDR: pValue = (char *)pReq->getLocalAddrStr()->c_str(); return pReq->getLocalAddrStr()->len(); case REF_SERVER_PORT: pValue = (char *)pReq->getPortStr().c_str(); return pReq->getPortStr().len(); case REF_SERVER_PROTO: i = pReq->getVersion(); pValue = (char *)HttpVer::getVersionString( i ); return HttpVer::getVersionStringLen( i ); case REF_SERVER_SOFT: pValue = (char *)HttpServerVersion::getVersion(); return HttpServerVersion::getVersionLen(); case REF_REQ_LINE: pValue = (char *)pReq->getOrgReqLine(); return pReq->getOrgReqLineLen(); case REF_IS_SUBREQ: strcpy( pValue, "false" ); return 5; case REF_RESP_BYTES: i = StringTool::str_off_t( pValue, bufLen, pSession->getResp()->getBodySent() ); return i; //case REF_COOKIE_VAL //case REF_STRFTIME 155 //case REF_CONN_STATE: case REF_REQ_TIME_MS: { struct timeval tv; gettimeofday( &tv, NULL ); DateTime::s_curTime = tv.tv_sec; DateTime::s_curTimeUs = tv.tv_usec; long lReqTime = (DateTime::s_curTime - pSession->getReqTime())*1000000 + (DateTime::s_curTimeUs - pSession->getReqTimeUs()); i = snprintf( pValue, bufLen, "%ld", lReqTime ); return i; } case REF_REQ_TIME_SEC: i = snprintf( pValue, bufLen, "%ld", (DateTime::s_curTime - pSession->getReqTime()) ); return i; case REF_DUMMY: return 0; case REF_PID: i = snprintf( pValue, bufLen, "%d", getpid() ); return i; case REF_STATUS_CODE: memmove( pValue, HttpStatusCode::getCodeString( pReq->getStatusCode() )+1, 3 ); pValue[3] = 0; return 3; case REF_CUR_URI: pValue = (char *)pReq->getURI(); i = pReq->getURILen(); return i; case REF_BYTES_IN: i = StringTool::str_off_t( pValue, bufLen, pSession->getBytesRecv() ); return i; case REF_BYTES_OUT: i = StringTool::str_off_t( pValue, bufLen, pSession->getBytesSent() ); return i; case REF_HTTPS: i = snprintf( pValue, bufLen, "%s", pSession->isSSL()?"on":"off" ); return i; case REF_DATE_GMT: case REF_DATE_LOCAL: case REF_LAST_MODIFIED: { time_t mtime = DateTime::s_curTime; struct tm * tm; if ( type == REF_LAST_MODIFIED ) { if ( pReq->getSSIRuntime() && pReq->getSSIRuntime()->getCurrentScript() ) { mtime = pReq->getSSIRuntime()->getCurrentScript()->getLastMod(); } else mtime = pReq->getFileStat().st_mtime; } if ( type == REF_DATE_GMT ) tm = gmtime( &mtime ); else tm = localtime( &mtime ); char fmt[101]; memccpy( fmt, pValue, 0, 100 ); fmt[100] = 0; i = strftime( pValue, bufLen, fmt, tm ); return i; } case REF_DOCUMENT_NAME: { const AutoStr2 * psTemp = pReq->getRealPath(); if ( psTemp ) { pValue = (char *)psTemp->c_str() + psTemp->len(); while( *(pValue -1) != '/' ) --pValue; return psTemp->c_str() + psTemp->len() - pValue; } else return 0; } case REF_QS_UNESCAPED: { int qsLen = pReq->getQueryStringLen(); const char * pQS = pReq->getQueryString(); if ( qsLen > 0 ) { qsLen = HttpUtil::unescape_n( pQS, qsLen, pValue, bufLen ); } return qsLen; } case REF_RESP_CONTENT_TYPE: i = 0; pValue = (char*)pSession->getResp()->getContentTypeHeader( i ); return i; case REF_RESP_CONTENT_LENGTH: { off_t l = pSession->getResp()->getContentLen(); if ( l <= 0 ) l = 0; i = StringTool::str_off_t( pValue, bufLen, l ); return i; } case REF_RESP_BODY: return 0; default: if ( type >= REF_TIME ) { time_t t = time(NULL); struct tm *tm = localtime(&t); switch( type ) { case REF_TIME: i = snprintf( pValue, bufLen, "%04d%02d%02d%02d%02d%02d", tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); break; case REF_TIME_YEAR: i = snprintf( pValue, bufLen, "%04d", tm->tm_year + 1900); break; case REF_TIME_MON: i = snprintf( pValue, bufLen, "%02d", tm->tm_mon+1 ); break; case REF_TIME_DAY: i = snprintf( pValue, bufLen, "%02d", tm->tm_mday); break; case REF_TIME_HOUR: i = snprintf( pValue, bufLen, "%02d", tm->tm_hour); break; case REF_TIME_MIN: i = snprintf( pValue, bufLen, "%02d", tm->tm_min); break; case REF_TIME_SEC: i = snprintf( pValue, bufLen, "%02d", tm->tm_sec); break; case REF_TIME_WDAY: i = snprintf( pValue, bufLen, "%d", tm->tm_wday); break; default: return 0; } return i; } return 0; } return 0; }
int HttpCgiTool::processHeaderLine(HttpExtConnector *pExtConn, const char *pLineBegin, const char *pLineEnd, int &status) { HttpRespHeaders::HEADERINDEX index; int tmpIndex; const char *pKeyEnd = NULL; const char *pValue = pLineBegin; char *p; HttpResp *pResp = pExtConn->getHttpSession()->getResp(); HttpReq *pReq = pExtConn->getHttpSession()->getReq(); index = HttpRespHeaders::getRespHeaderIndex(pValue); if (index < HttpRespHeaders::H_HEADER_END) { pValue += HttpRespHeaders::getHeaderStringLen(index); while (isspace(*pValue)) ++pValue; pKeyEnd = pValue; if (*pValue != ':') index = HttpRespHeaders::H_HEADER_END; else { do { ++pValue; } while (isspace(*pValue)); } } if (index == HttpRespHeaders::H_HEADER_END) { pKeyEnd = (char *)memchr(pValue, ':', pLineEnd - pValue); if (pKeyEnd != NULL) { pValue = pKeyEnd + 1; while (isspace(*pValue)) ++pValue; } else { if (!isspace(*pLineBegin)) return 0; } } switch (index) { case HttpRespHeaders::H_CONTENT_TYPE: if (pReq->getStatusCode() == SC_304) return 0; p = (char *)memchr(pValue, ';', pLineEnd - pValue); if (pReq->gzipAcceptable() == GZIP_REQUIRED) { char ch = 0; char *p1; if (p) p1 = (char *)p; else p1 = (char *)pLineEnd; ch = *p1; *p1 = 0; if (!HttpMime::getMime()->compressible(pValue)) pReq->andGzip(~GZIP_ENABLED); *p1 = ch; } if (pReq->isKeepAlive()) pReq->smartKeepAlive(pValue); { if (!HttpMime::needCharset(pValue)) break; const AutoStr2 *pCharset = pReq->getDefaultCharset(); if (!pCharset) break; if (p) { while (isspace(*(++p))) ; if (strncmp(p, "charset=", 8) == 0) break; } HttpRespHeaders &buf = pResp->getRespHeaders(); AutoStr2 str = ""; str.append(pLineBegin, pLineEnd - pLineBegin); str.append(pCharset->c_str(), pCharset->len()); str.append("\r\n", 2); buf.parseAdd(str.c_str(), str.len(), LSI_HEADEROP_ADD); } return 0; case HttpRespHeaders::H_CONTENT_ENCODING: if (pReq->getStatusCode() == SC_304) return 0; if (strncasecmp(pValue, "gzip", 4) == 0) pReq->orGzip(UPSTREAM_GZIP); else if (strncasecmp(pValue, "deflate", 7) == 0) pReq->orGzip(UPSTREAM_DEFLATE); // if ( !(pReq->gzipAcceptable() & REQ_GZIP_ACCEPT) ) // return 0; // } // else //if ( strncasecmp( pValue, "deflate", 7 ) == 0 ) // { // pReq->andGzip( ~GZIP_ENABLED ); // } break; case HttpRespHeaders::H_LOCATION: if ((status & HEC_RESP_PROXY) || (pReq->getStatusCode() != SC_200)) break; case HttpRespHeaders::H_LITESPEED_LOCATION: if (*pValue != '/') { //set status code to 307 pReq->setStatusCode(SC_302); } else { if ((pReq->getStatusCode() == SC_404) || (index == HttpRespHeaders::H_LITESPEED_LOCATION)) pReq->setStatusCode(SC_200); if (index == HttpRespHeaders::H_LITESPEED_LOCATION) { char ch = *pLineEnd; *((char *)pLineEnd) = 0; pReq->locationToUrl(pValue, pLineEnd - pValue); *((char *)pLineEnd) = ch; } else pReq->setLocation(pValue, pLineEnd - pValue); pExtConn->getHttpSession()->changeHandler(); //status |= HEC_RESP_LOC_SET; return 0; } break; case HttpRespHeaders::H_CGI_STATUS: tmpIndex = HttpStatusCode::getInstance().codeToIndex(pValue); if (tmpIndex != -1) { pReq->updateNoRespBodyByStatus(tmpIndex); if ((tmpIndex >= SC_300) && (tmpIndex < SC_400)) { if (pReq->getLocation() != NULL) { pResp->appendHeader("location: ", 10, pReq->getLocation(), pReq->getLocationLen()); pReq->clearLocation(); } } if ((status & HEC_RESP_AUTHORIZER) && (tmpIndex == SC_200)) status |= HEC_RESP_AUTHORIZED; } return 0; case HttpRespHeaders::H_TRANSFER_ENCODING: pResp->setContentLen(LSI_RSP_BODY_SIZE_CHUNKED); return 0; case HttpRespHeaders::H_SET_COOKIE: //pReq->getRespCacheCtrl().setHasCookie(); pReq->processSetCookieHeader(pValue, pLineEnd - pValue); break; case HttpRespHeaders::H_PROXY_CONNECTION: case HttpRespHeaders::H_CONNECTION: if (strncasecmp(pValue, "close", 5) == 0) status |= HEC_RESP_CONN_CLOSE; return 0; case HttpRespHeaders::H_CONTENT_LENGTH: if (pResp->getContentLen() == LSI_RSP_BODY_SIZE_UNKNOWN) { off_t lContentLen = strtoll(pValue, NULL, 10); if ((lContentLen >= 0) && (lContentLen != LLONG_MAX)) { pResp->setContentLen(lContentLen); status |= HEC_RESP_CONT_LEN; pReq->orContextState(RESP_CONT_LEN_SET); } } //fall through case HttpRespHeaders::H_KEEP_ALIVE: case HttpRespHeaders::H_SERVER: case HttpRespHeaders::H_DATE: return 0; default: //"script-control: no-abort" is not supported break; } if (status & HEC_RESP_AUTHORIZED) { if (strncasecmp(pLineBegin, "Variable-", 9) == 0) { if (pKeyEnd > pLineBegin + 9) RequestVars::setEnv(pExtConn->getHttpSession(), pLineBegin + 9, pKeyEnd - pLineBegin - 9, pValue, pLineEnd - pValue); } return 0; } assert(pKeyEnd); return pResp->appendHeader(pLineBegin, pKeyEnd - pLineBegin, pValue, pLineEnd - pValue); }
void AccessLog::log( HttpConnection* pConn ) { int n; HttpReq* pReq = pConn->getReq(); HttpResp* pResp = pConn->getResp(); const char * pUser = pReq->getAuthUser(); long contentWritten = pResp->getBodySent(); const ClientInfo * pInfo = pConn->getClientInfo(); const char * pAddr = pInfo->getHostName(); pResp->needLogAccess( 0 ); if ( m_iPipedLog ) { if ( !m_pManager ) return; m_pAppender = m_pManager->getAppender(); if ( !m_pAppender ) return; } if ( m_pCustomFormat ) return customLog( pConn ); if (( pAddr )&&( *pAddr )) { n = pInfo->getHostNameLen(); } else { pAddr = pInfo->getAddrString(); n = pInfo->getAddrStrLen(); } m_buf.appendNoCheck( pAddr, n ); if ( ! *pUser ) { m_buf.appendNoCheck( " - - ", 5 ); } else { n = safe_snprintf( m_buf.end(), 70, " - \"%s\" ", pUser ); m_buf.used( n ); } DateTime::getLogTime( pConn->getReqTime(), m_buf.end() ); m_buf.used( 30 ); n = pReq->getOrgReqLineLen(); char * pOrgReqLine = (char *)pReq->getOrgReqLine(); if ( pReq->getVersion() == HTTP_1_0 ) *(pOrgReqLine + n - 1) = '0'; if (( n > 4096 )||( m_buf.available() < 100 + n )) { flush(); m_pAppender->append( pOrgReqLine, n ); } else m_buf.appendNoCheck(pOrgReqLine, n ); m_buf.append( '"' ); m_buf.appendNoCheck( HttpStatusCode::getCodeString( pReq->getStatusCode() ), 5 ); if ( contentWritten == 0 ) { m_buf.append( '-' ); } else { n = safe_snprintf( m_buf.end(), 20, "%ld", contentWritten ); m_buf.used( n ); } if ( getAccessLogHeader() & LOG_REFERER ) { m_buf.append( ' ' ); appendStr( pReq->getHeader( HttpHeader::H_REFERER ), pReq->getHeaderLen( HttpHeader::H_REFERER )); } if ( getAccessLogHeader() & LOG_USERAGENT ) { m_buf.append( ' ' ); appendStr( pReq->getHeader( HttpHeader::H_USERAGENT), pReq->getHeaderLen( HttpHeader::H_USERAGENT) ); } if ( getAccessLogHeader() & LOG_VHOST ) { m_buf.append( ' ' ); appendStr( pReq->getHeader( HttpHeader::H_HOST ), pReq->getHeaderLen( HttpHeader::H_HOST ) ); } m_buf.append( '\n' ); if (( m_buf.available() < MAX_LOG_LINE_LEN ) ||!asyncAccessLog() ) { flush(); } }