//============================================================================= // YHTTPD // mod_weblog : Logging of HTTPD-Requests/Responses //----------------------------------------------------------------------------- // Normally //============================================================================= #include #include #include #include #include "mod_weblog.h" #include "helper.h" //============================================================================= // Initialization of static variables //============================================================================= pthread_mutex_t CmWebLog::WebLog_mutex = PTHREAD_MUTEX_INITIALIZER; FILE *CmWebLog::WebLogFile = NULL; int CmWebLog::RefCounter = 0; std::string CmWebLog::WebLogFilename=LOG_FILE; std::string CmWebLog::LogFormat =LOG_FORMAT; //============================================================================= // Constructor & Destructor //============================================================================= CmWebLog::CmWebLog(void) { pthread_mutex_lock(&WebLog_mutex); // yea, its mine RefCounter++; pthread_mutex_unlock(&WebLog_mutex); } //----------------------------------------------------------------------------- CmWebLog::~CmWebLog(void) { pthread_mutex_lock(&WebLog_mutex); // yea, its mine --RefCounter; if(RefCounter <= 0) CloseLogFile(); pthread_mutex_unlock(&WebLog_mutex); } //============================================================================= // HOOKS //============================================================================= //----------------------------------------------------------------------------- // HOOK: Hook_EndConnection //----------------------------------------------------------------------------- THandleStatus CmWebLog::Hook_EndConnection(CyhookHandler *hh) { if(LogFormat == "CLF") AddLogEntry_CLF(hh); else if(LogFormat == "ELF") AddLogEntry_ELF(hh); return HANDLED_CONTINUE; // even on Log-Error: continue } //----------------------------------------------------------------------------- // HOOK: Hook_ReadConfig // This hook ist called from ReadConfig //----------------------------------------------------------------------------- THandleStatus CmWebLog::Hook_ReadConfig(CConfigFile *Config, CStringList &ConfigList) { LogFormat = Config->getString("mod_weblog.log_format", LOG_FORMAT); WebLogFilename = Config->getString("mod_weblog.logfile", LOG_FILE); return HANDLED_CONTINUE; } //----------------------------------------------------------------------------- bool CmWebLog::OpenLogFile() { if(WebLogFilename == "") return false; if(WebLogFile == NULL) { bool isNew = false; pthread_mutex_lock(&WebLog_mutex); // yeah, its mine if(access(WebLogFilename.c_str(), 4) != 0) isNew = true; WebLogFile = fopen(WebLogFilename.c_str(),"a"); if(isNew) { if(LogFormat == "ELF") { printf("#Version: 1.0\n"); printf("#Remarks: yhttpd" WEBSERVERNAME "\n"); printf("#Fields: c-ip username date time x-request cs-uri sc-status cs-method bytes time-taken x-time-request x-time-response cached\n"); } } pthread_mutex_unlock(&WebLog_mutex); } return (WebLogFile != NULL); } //----------------------------------------------------------------------------- void CmWebLog::CloseLogFile() { if(WebLogFile != NULL) { pthread_mutex_lock(&WebLog_mutex); // yeah, its mine fclose(WebLogFile); WebLogFile = NULL; pthread_mutex_unlock(&WebLog_mutex); } } //----------------------------------------------------------------------------- #define bufferlen 1024*8 bool CmWebLog::printf(const char *fmt, ...) { if(!OpenLogFile()) return false; bool success = false; char buffer[bufferlen]; if(WebLogFile != NULL) { pthread_mutex_lock(&WebLog_mutex); // yeah, its mine va_list arglist; va_start( arglist, fmt ); // if(arglist) vsnprintf( buffer, bufferlen, fmt, arglist ); va_end(arglist); unsigned int len = strlen(buffer); success = (fwrite(buffer, len, 1, WebLogFile) == len); fflush(WebLogFile); pthread_mutex_unlock(&WebLog_mutex); } return success; } //----------------------------------------------------------------------------- // CLF - Common Logfile Format // // Example: 127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 // // The common logfile format is as follows: // remotehost rfc931 authuser [date] "request" status bytes // // remotehost: Remote hostname (or IP number if DNS hostname is not available, or if DNSLookup is Off. // rfc931: The remote logname of the user. // authuser: The username as which the user has authenticated himself. // [date]: Date and time of the request. // "request": The request line exactly as it came from the client. // status: The HTTP status code returned to the client. // bytes: The content-length of the document transferred. //----------------------------------------------------------------------------- void CmWebLog::AddLogEntry_CLF(CyhookHandler *hh) { std::string cs_method; switch (hh->Method) { case M_GET: cs_method = "GET"; break; case M_POST: cs_method = "POST"; break; case M_HEAD: cs_method = "HEAD"; break; default: cs_method = "unknown"; break; } std::string c_ip = hh->UrlData["clientaddr"].c_str(); std::string request_startline = hh->UrlData["startline"].c_str(); int s_status = hh->httpStatus; int bytes = hh->GetContentLength(); struct tm *time_now; time_t now = time(NULL); char request_time[80]; time_now = localtime(&now); strftime(request_time, 80, "[%d/%b/%Y:%H:%M:%S]", time_now); printf("%s - - %s \"%s\" %d %d\n", c_ip.c_str(), request_time, request_startline.c_str(), s_status, bytes); } //----------------------------------------------------------------------------- /* Definition: (ELF) Extended Log File Format W3C Working Draft WD-logfile-960323 (http://www.w3.org/pub/WWW/TR/WD-logfile-960323.html) An extended log file contains a sequence of lines containing ASCII characters terminated by either the sequence LF or CRLF. Log file generators should follow the line termination convention for the platform on which they are executed. Analyzers should accept either form. Each line may contain either a directive or an entry. Entries consist of a sequence of fields relating to a single HTTP transaction. Fields are separated by whitespace, the use of tab characters for this purpose is encouraged. If a field is unused in a particular entry dash "-" marks the omitted field. Directives record information about the logging process itself. Lines beginning with the # character contain directives. The following directives are defined: - Version: . The version of the extended log file format used. This draft defines version 1.0. - Fields: [...] Specifies the fields recorded in the log. - Software: string Identifies the software which generated the log. - Start-Date: