void time_check_exploded(lua_State *L, int idx, apr_time_exp_t *components, int default_to_now) { int i; char *field; apr_status_t status; if (default_to_now && lua_isnoneornil(L, idx)) { status = apr_time_exp_lt(components, apr_time_now()); if (status != APR_SUCCESS) raise_error_status(L, status); } else if (lua_isnumber(L, idx)) { status = apr_time_exp_lt(components, time_get(L, idx)); if (status != APR_SUCCESS) raise_error_status(L, status); } else { luaL_checktype(L, idx, LUA_TTABLE); for (i = 0; i < count(fields); i++) { lua_getfield(L, idx, fields[i].name); field = (char*)components + fields[i].byte_offset; *(apr_int32_t*)field = lua_tointeger(L, -1) - fields[i].value_offset; lua_pop(L, 1); } lua_getfield(L, idx, "isdst"); components->tm_isdst = lua_toboolean(L, -1); lua_pop(L, 1); } }
/** Explode time to human readable form. */ log4cxx_status_t explode( apr_time_exp_t * result, log4cxx_time_t input ) const { apr_status_t stat; // APR 1.1 and early mishandles microseconds on dates // before 1970, APR bug 32520 if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0)) { apr_time_t floorTime = (apr_time_sec(input) -1) * APR_USEC_PER_SEC; stat = apr_time_exp_lt(result, floorTime); result->tm_usec = (int) (input - floorTime); } else { stat = apr_time_exp_lt( result, input ); } return stat; }
int lua_apr_time_explode(lua_State *L) { apr_time_exp_t components; apr_status_t status; apr_time_t time; char *field; int i; time = time_check(L, 1); if (!lua_toboolean(L, 2)) /* Explode the time according to the local timezone by default. */ status = apr_time_exp_lt(&components, time); else /* Or explode the time according to (an offset from) GMT instead. */ status = apr_time_exp_tz(&components, time, lua_isboolean(L, 2) ? 0 : (apr_int32_t) luaL_checkinteger(L, 2)); if (status != APR_SUCCESS) return push_error_status(L, status); /* Copy numeric fields of exploded time to Lua table. */ lua_createtable(L, 0, count(fields) + 1); for (i = 0; i < count(fields); i++) { field = (char*)&components + fields[i].byte_offset; lua_pushinteger(L, *(apr_int32_t*)field + fields[i].value_offset); lua_setfield(L, -2, fields[i].name); } /* Copy boolean `isdst' field. */ lua_pushboolean(L, components.tm_isdst); lua_setfield(L, -2, "isdst"); return 1; }
/*++ LogFormatV Adds an entry to the log file. Arguments: level - Log severity level. format - Pointer to a buffer containing a printf-style format string. argList - Argument list to insert into 'format'. Return Values: None. Remarks: This function could be called before the logging subsystem is initialized. --*/ void LogFormatV( apr_uint32_t level, const char *format, va_list argList ) { apr_time_exp_t now; char *message; ASSERT(format != NULL); if (level <= maxLevel && handle != NULL) { // Write local time apr_time_exp_lt(&now, apr_time_now()); apr_file_printf(handle, "%04d-%02d-%02d %02d:%02d:%02d - ", now.tm_year+1900, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec); // Format and write log message message = apr_pvsprintf(msgPool, format, argList); if (message == NULL) { message = "Unable to format message." APR_EOL_STR; } apr_file_puts(message, handle); apr_file_flush(handle); // Clear memory allocated when formatting the message apr_pool_clear(msgPool); } }
static void test_exp_lt(CuTest *tc) { apr_status_t rv; apr_time_exp_t xt; time_t posix_secs = (time_t)apr_time_sec(now); struct tm *posix_exp = localtime(&posix_secs); rv = apr_time_exp_lt(&xt, now); if (rv == APR_ENOTIMPL) { CuNotImpl(tc, "apr_time_exp_lt"); } CuAssertTrue(tc, rv == APR_SUCCESS); #define CHK_FIELD(f) \ CuAssert(tc, "Mismatch in " #f, posix_exp->f == xt.f) CHK_FIELD(tm_sec); CHK_FIELD(tm_min); CHK_FIELD(tm_hour); CHK_FIELD(tm_mday); CHK_FIELD(tm_mon); CHK_FIELD(tm_year); CHK_FIELD(tm_wday); CHK_FIELD(tm_yday); CHK_FIELD(tm_isdst); #undef CHK_FIELD }
int logging_rotateLogFile(mm_logger* log) { mm_logger* ltmp; apr_finfo_t finfo; apr_time_t tnow; apr_time_exp_t texp; apr_status_t st; apr_size_t tbuflen,tbufmax=64; char tbuf[64],*newPath; st=apr_stat(&finfo,log->filepath,APR_FINFO_SIZE,log->p); if(finfo.size > log->maxLogFileSizeMB*1024*1024) { apr_file_printf(log->file,"Monitor File Size [%dB], Max Value [%dB].\r\n",finfo.size,log->maxLogFileSizeMB*1024*1024); logging_closeLogger(log); log->file=NULL; tnow=apr_time_now(); memset(tbuf,'\0',64); apr_time_exp_lt(&texp,tnow); apr_strftime(tbuf,&tbuflen,tbufmax,"%F-%H_%M_%S",&texp); newPath=apr_psprintf(log->p,"%s.%s.%d",log->filepath,tbuf,texp.tm_usec); apr_file_rename(log->filepath,newPath,log->p); ltmp=logging_getLogger(log->p,log->filepath,log->maxLogFileSizeMB); log->file=ltmp->file; return TRUE; } return FALSE; }
void aos_log_format_default(int level, const char *file, int line, const char *function, const char *fmt, ...) { int len; apr_time_t t; int s; apr_time_exp_t tm; va_list args; char buffer[4096]; t = apr_time_now(); if ((s = apr_time_exp_lt(&tm, t)) != APR_SUCCESS) { return; } len = snprintf(buffer, 4090, "[%04d-%02d-%02d %02d:%02d:%02d.%03d] %" APR_INT64_T_FMT " %s:%d ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec/1000, (int64_t)apr_os_thread_current(), file, line); va_start(args, fmt); len += vsnprintf(buffer + len, 4090 - len, fmt, args); va_end(args); while (buffer[len -1] == '\n') len--; buffer[len++] = '\n'; buffer[len] = '\0'; aos_log_print(buffer, len); }
int lc_rotateLogFile() { apr_status_t status=0; int cur_pid; cur_pid=getpid(); if(refreshLogger.status!=APR_SUCCESS||cur_pid!=refreshLogger.pid) { //printf("\nLogfile has not been opened.\n"); return FALSE; } lc_closeLogFile(); apr_time_t tnow; apr_time_exp_t texp; apr_size_t tbuflen,tbufmax=64; char tbuf[64],*renamedPath; tnow=apr_time_now(); memset(tbuf,'\0',64); apr_time_exp_lt(&texp,tnow); apr_strftime(tbuf,&tbuflen,tbufmax,"%F-%H_%M_%S",&texp); renamedPath=apr_psprintf(refreshLogger.logger.p,"%s.%s.%d",refreshLogger.logger.filepath,tbuf,texp.tm_usec); status = apr_file_rename(refreshLogger.logger.filepath,renamedPath,refreshLogger.logger.p); // open a new file status = lc_openLogFile(refreshLogger.logger.p, refreshLogger.logger.filepath); return status; }
/* Logging functions. Use with one of the [COMP]_VERBOSE defines so that the compiler knows to optimize this code out when no logging is needed. */ static void log_time() { apr_time_exp_t tm; apr_time_exp_lt(&tm, apr_time_now()); fprintf(stderr, "[%d-%02d-%02dT%02d:%02d:%02d.%06d%+03d] ", 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff/3600); }
/* Quantize the supplied time to the log rotation interval applying offsets as * specified in the config. */ static apr_time_t ap_get_quantized_time(rotated_log *rl, apr_time_t tm) { apr_time_t localadj = 0; if (rl->st.localt) { apr_time_exp_t lt; apr_time_exp_lt(<, tm); localadj = (apr_time_t) lt.tm_gmtoff * APR_USEC_PER_SEC; } return ((tm + rl->st.offset + localadj) / rl->st.interval) * rl->st.interval; }
static apt_bool_t apt_do_log(apt_log_priority_e priority, const char *format, va_list arg_ptr) { char log_entry[MAX_LOG_ENTRY_SIZE]; apr_size_t offset = 0; apr_time_exp_t result; apr_time_t now = apr_time_now(); apr_time_exp_lt(&result,now); if(apt_logger.header & APT_LOG_HEADER_DATE) { offset += apr_snprintf(log_entry+offset,MAX_LOG_ENTRY_SIZE-offset,"%4d-%02d-%02d ", result.tm_year+1900, result.tm_mon+1, result.tm_mday); } if(apt_logger.header & APT_LOG_HEADER_TIME) { offset += apr_snprintf(log_entry+offset,MAX_LOG_ENTRY_SIZE-offset,"%02d:%02d:%02d:%06d ", result.tm_hour, result.tm_min, result.tm_sec, result.tm_usec); } if(apt_logger.header & APT_LOG_HEADER_PRIORITY) { memcpy(log_entry+offset,priority_snames[priority],MAX_PRIORITY_NAME_LENGTH); offset += MAX_PRIORITY_NAME_LENGTH; } offset += apr_vsnprintf(log_entry+offset,MAX_LOG_ENTRY_SIZE-offset,format,arg_ptr); log_entry[offset++] = '\n'; log_entry[offset] = '\0'; if((apt_logger.mode & APT_LOG_OUTPUT_CONSOLE) == APT_LOG_OUTPUT_CONSOLE) { printf(log_entry); } if((apt_logger.mode & APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE && apt_logger.file) { apr_thread_mutex_lock(apt_logger.mutex); apt_logger.cur_size += offset; if(apt_logger.cur_size > apt_logger.max_size) { /* roll over */ fseek(apt_logger.file,0,SEEK_SET); apt_logger.cur_size = offset; } /* write to log file */ fwrite(log_entry,1,offset,apt_logger.file); fflush(apt_logger.file); apr_thread_mutex_unlock(apt_logger.mutex); } return TRUE; }
/* * Get the unix time with timezone corrections * given in the config struct. */ static int get_now(rotate_config_t *config) { apr_time_t tNow = apr_time_now(); int utc_offset = config->utc_offset; if (config->use_localtime) { /* Check for our UTC offset before using it, since it might * change if there's a switch between standard and daylight * savings time. */ apr_time_exp_t lt; apr_time_exp_lt(<, tNow); utc_offset = lt.tm_gmtoff; } return (int)apr_time_sec(tNow) + utc_offset; }
static const LogString getTimeZoneName() { const int MAX_TZ_LENGTH = 255; char tzName[MAX_TZ_LENGTH]; apr_size_t tzLength; apr_time_exp_t tm; apr_time_exp_lt(&tm, 0); apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%Z", &tm); if (tzLength == 0) { apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%z", &tm); } tzName[tzLength] = 0; LogString retval; log4cxx::helpers::Transcoder::decode(tzName, retval); return retval; }
static void test_exp_get_lt(CuTest *tc) { apr_status_t rv; apr_time_exp_t xt; apr_time_t imp; apr_int64_t hr_off_64; rv = apr_time_exp_lt(&xt, now); CuAssertTrue(tc, rv == APR_SUCCESS); rv = apr_time_exp_get(&imp, &xt); if (rv == APR_ENOTIMPL) { CuNotImpl(tc, "apr_time_exp_get"); } CuAssertTrue(tc, rv == APR_SUCCESS); hr_off_64 = (apr_int64_t) xt.tm_gmtoff * APR_USEC_PER_SEC; CuAssertTrue(tc, now + hr_off_64 == imp); }
static char * add_auth_token(apr_pool_t *pool, saxctxt *ctx, apr_uri_t *u) { apr_uri_t u2 = *u; const char *unparsed_uri, *auth_token, *ip; char *timestamp, *forwarded_list, *last; apr_status_t rv; apr_time_exp_t xt; apr_size_t sz; apr_table_t *params; unparsed_uri = apr_uri_unparse(pool, &u2, APR_URI_UNP_OMITQUERY); rv = apr_time_exp_lt(&xt, apr_time_now() + apr_time_from_sec(ctx->cfg->auth_exptime)); timestamp = apr_palloc(pool, TIME_STR_SIZE + 1); rv = apr_strftime(timestamp, &sz, TIME_STR_SIZE, "%FT%T%z", &xt); if (u2.query) u2.query = apr_pstrcat(pool, u2.query, "&vox_timestamp=", timestamp, NULL); else u2.query = apr_pstrcat(pool, "vox_timestamp=", timestamp, NULL); /* Convert the query string to a table */ params = apr_table_make(pool, 1); qs_to_table(u2.query, params, pool); /* Generate the auth token */ forwarded_list = (char *)apr_table_get(ctx->f->r->headers_in, "X-Forwarded-For"); /* If X-Forwarded-For header exists, use first IP in it */ if (forwarded_list && (forwarded_list = apr_pstrdup(pool, forwarded_list)) && (ip = apr_strtok(forwarded_list, ", \t", &last))) auth_token = make_auth_token(ctx->f->r, ip, unparsed_uri, params, ctx->cfg->auth_key); else /* Otherwise, use the normal remote_ip */ auth_token = make_auth_token(ctx->f->r, ctx->f->r->connection->remote_ip, unparsed_uri, params, ctx->cfg->auth_key); if (auth_token) { u2.query = apr_pstrcat(pool, u2.query, "&vox_sig=", auth_token, NULL); ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ctx->f->r->server, "add_auth_token: new query string is %s", u2.query); } return u2.query; }
static apt_bool_t apt_do_log(const char *file, int line, apt_log_priority_e priority, const char *format, va_list arg_ptr) { char log_entry[MAX_LOG_ENTRY_SIZE]; apr_size_t max_size = MAX_LOG_ENTRY_SIZE - 2; apr_size_t offset = 0; apr_time_exp_t result; apr_time_t now = apr_time_now(); apr_time_exp_lt(&result,now); if(apt_logger->header & APT_LOG_HEADER_DATE) { offset += apr_snprintf(log_entry+offset,max_size-offset,"%4d-%02d-%02d ", result.tm_year+1900, result.tm_mon+1, result.tm_mday); } if(apt_logger->header & APT_LOG_HEADER_TIME) { offset += apr_snprintf(log_entry+offset,max_size-offset,"%02d:%02d:%02d:%06d ", result.tm_hour, result.tm_min, result.tm_sec, result.tm_usec); } if(apt_logger->header & APT_LOG_HEADER_MARK) { offset += apr_snprintf(log_entry+offset,max_size-offset,"%s:%03d ",file,line); } if(apt_logger->header & APT_LOG_HEADER_THREAD) { offset += apr_snprintf(log_entry+offset,max_size-offset,"%05lu ",apt_thread_id_get()); } if(apt_logger->header & APT_LOG_HEADER_PRIORITY) { memcpy(log_entry+offset,priority_snames[priority],MAX_PRIORITY_NAME_LENGTH); offset += MAX_PRIORITY_NAME_LENGTH; } offset += apr_vsnprintf(log_entry+offset,max_size-offset,format,arg_ptr); log_entry[offset++] = '\n'; log_entry[offset] = '\0'; if((apt_logger->mode & APT_LOG_OUTPUT_CONSOLE) == APT_LOG_OUTPUT_CONSOLE) { fwrite(log_entry,offset,1,stdout); } if((apt_logger->mode & APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE && apt_logger->file_data) { apt_log_file_dump(apt_logger->file_data,log_entry,offset); } return TRUE; }
///////////////////////////////////////////////////////////////////////////////// // // Function: // // Purpose: // // Parameters: // // Return value: // // Author: Komatsu Yuji(Zheng Chuyu) // ///////////////////////////////////////////////////////////////////////////////// char *jhk_timestamp(void) { // YYYY-mm-dd HH:MM:SS.sss static char str[24]; apr_time_t now; apr_time_exp_t xt; now = apr_time_now(); apr_time_exp_lt(&xt, now); sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d.%03d", xt.tm_year + 1900, xt.tm_mon + 1, xt.tm_mday, xt.tm_hour, xt.tm_min, xt.tm_sec, xt.tm_usec / 1000); return str; }
APR_DECLARE(apr_status_t) apr_ctime(char *date_str, apr_time_t t) { apr_time_exp_t xt; const char *s; int real_year; /* example: "Wed Jun 30 21:49:08 1993" */ /* 123456789012345678901234 */ apr_time_exp_lt(&xt, t); s = &apr_day_snames[xt.tm_wday][0]; *date_str++ = *s++; *date_str++ = *s++; *date_str++ = *s++; *date_str++ = ' '; s = &apr_month_snames[xt.tm_mon][0]; *date_str++ = *s++; *date_str++ = *s++; *date_str++ = *s++; *date_str++ = ' '; *date_str++ = xt.tm_mday / 10 + '0'; *date_str++ = xt.tm_mday % 10 + '0'; *date_str++ = ' '; *date_str++ = xt.tm_hour / 10 + '0'; *date_str++ = xt.tm_hour % 10 + '0'; *date_str++ = ':'; *date_str++ = xt.tm_min / 10 + '0'; *date_str++ = xt.tm_min % 10 + '0'; *date_str++ = ':'; *date_str++ = xt.tm_sec / 10 + '0'; *date_str++ = xt.tm_sec % 10 + '0'; *date_str++ = ' '; real_year = 1900 + xt.tm_year; *date_str++ = real_year / 1000 + '0'; *date_str++ = real_year % 1000 / 100 + '0'; *date_str++ = real_year % 100 / 10 + '0'; *date_str++ = real_year % 10 + '0'; *date_str++ = 0; return APR_SUCCESS; }
int slayer_server_log_request(slayer_server_log_manager_t *manager, apr_pool_t *mpool, apr_socket_t *conn, const char *request_line, int response_code, int nbytes_sent, apr_int64_t time_toservice) { //generate data char dstring[1024]; apr_int64_t current_time = apr_time_now(); apr_size_t result_size; apr_time_exp_t ltime; apr_time_exp_lt(<ime,current_time); apr_strftime (dstring, &result_size, sizeof(dstring), "%d/%b/%Y:%H:%M:%S %z", <ime ); apr_sockaddr_t *client_addr; char *client_ip; apr_socket_addr_get(&client_addr,0,conn); apr_sockaddr_ip_get(&client_ip,client_addr); if (manager->fhandle) { char *message = apr_pstrcat(mpool,client_ip," - - ","[",dstring,"] \"",request_line,"\" ", apr_itoa(mpool,response_code)," ",apr_itoa(mpool,nbytes_sent), " ",apr_ltoa(mpool,time_toservice), "\n",NULL); slayer_server_log_message(manager,message); } slayer_server_log_add_entry(manager,mpool,client_ip,current_time,request_line,response_code,nbytes_sent,time_toservice); return 0; }
/* This implements the svn_client_list_func_t API, printing a single directory entry in text format. */ static svn_error_t * print_dirent(void *baton, const char *path, const svn_dirent_t *dirent, const svn_lock_t *lock, const char *abs_path, apr_pool_t *pool) { struct print_baton *pb = baton; const char *entryname; if (pb->ctx->cancel_func) SVN_ERR(pb->ctx->cancel_func(pb->ctx->cancel_baton)); if (strcmp(path, "") == 0) { if (dirent->kind == svn_node_file) entryname = svn_dirent_basename(abs_path, pool); else if (pb->verbose) entryname = "."; else /* Don't bother to list if no useful information will be shown. */ return SVN_NO_ERROR; } else entryname = path; if (pb->verbose) { apr_time_t now = apr_time_now(); apr_time_exp_t exp_time; apr_status_t apr_err; apr_size_t size; char timestr[20]; const char *sizestr, *utf8_timestr; /* svn_time_to_human_cstring gives us something *way* too long to use for this, so we have to roll our own. We include the year if the entry's time is not within half a year. */ apr_time_exp_lt(&exp_time, dirent->time); if (apr_time_sec(now - dirent->time) < (365 * 86400 / 2) && apr_time_sec(dirent->time - now) < (365 * 86400 / 2)) { apr_err = apr_strftime(timestr, &size, sizeof(timestr), _("%b %d %H:%M"), &exp_time); } else { apr_err = apr_strftime(timestr, &size, sizeof(timestr), _("%b %d %Y"), &exp_time); } /* if that failed, just zero out the string and print nothing */ if (apr_err) timestr[0] = '\0'; /* we need it in UTF-8. */ SVN_ERR(svn_utf_cstring_to_utf8(&utf8_timestr, timestr, pool)); sizestr = apr_psprintf(pool, "%" SVN_FILESIZE_T_FMT, dirent->size); return svn_cmdline_printf (pool, "%7ld %-8.8s %c %10s %12s %s%s\n", dirent->created_rev, dirent->last_author ? dirent->last_author : " ? ", lock ? 'O' : ' ', (dirent->kind == svn_node_file) ? sizestr : "", utf8_timestr, entryname, (dirent->kind == svn_node_dir) ? "/" : ""); } else { return svn_cmdline_printf(pool, "%s%s\n", entryname, (dirent->kind == svn_node_dir) ? "/" : ""); } }
static svn_error_t * test_parse_date(const char **msg, svn_boolean_t msg_only, svn_test_opts_t *opts, apr_pool_t *pool) { apr_time_t now, result; apr_time_exp_t nowexp, expt; svn_boolean_t matched; struct date_test *dt; const char **ft; *msg = "test svn_parse_date"; if (msg_only) return SVN_NO_ERROR; now = apr_time_now(); if (apr_time_exp_lt(&nowexp, now) != APR_SUCCESS) return svn_error_create(SVN_ERR_TEST_FAILED, NULL, "Can't expand time"); for (dt = localtz_tests; dt->str; dt++) { SVN_ERR(svn_parse_date(&matched, &result, dt->str, now, pool)); if (!matched) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "Match failed for '%s'", dt->str); if (apr_time_exp_lt(&expt, result) != APR_SUCCESS) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "Expand failed for '%s'", dt->str); SVN_ERR(compare_results(dt, &expt)); } for (dt = gmt_tests; dt->str; dt++) { SVN_ERR(svn_parse_date(&matched, &result, dt->str, now, pool)); if (!matched) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "Match failed for '%s'", dt->str); if (apr_time_exp_gmt(&expt, result) != APR_SUCCESS) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "Expand failed for '%s'", dt->str); SVN_ERR(compare_results(dt, &expt)); } for (dt = daytime_tests; dt->str; dt++) { SVN_ERR(svn_parse_date(&matched, &result, dt->str, now, pool)); if (!matched) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "Match failed for '%s'", dt->str); if (apr_time_exp_lt(&expt, result) != APR_SUCCESS) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "Expand failed for '%s'", dt->str); dt->year = nowexp.tm_year + 1900; dt->mon = nowexp.tm_mon + 1; dt->mday = nowexp.tm_mday; SVN_ERR(compare_results(dt, &expt)); } for (ft = failure_tests; *ft; ft++) { SVN_ERR(svn_parse_date(&matched, &result, *ft, now, pool)); if (matched) return svn_error_createf (SVN_ERR_TEST_FAILED, NULL, "Match succeeded for '%s'", *ft); } return SVN_NO_ERROR; }
static apr_status_t cached_explode(apr_time_exp_t *xt, apr_time_t t, struct exploded_time_cache_element *cache, int use_gmt) { apr_int64_t seconds = apr_time_sec(t); struct exploded_time_cache_element *cache_element = &(cache[seconds & TIME_CACHE_MASK]); struct exploded_time_cache_element cache_element_snapshot; /* The cache is implemented as a ring buffer. Each second, * it uses a different element in the buffer. The timestamp * in the element indicates whether the element contains the * exploded time for the current second (vs the time * 'now - AP_TIME_RECENT_THRESHOLD' seconds ago). If the * cached value is for the current time, we use it. Otherwise, * we compute the apr_time_exp_t and store it in this * cache element. Note that the timestamp in the cache * element is updated only after the exploded time. Thus * if two threads hit this cache element simultaneously * at the start of a new second, they'll both explode the * time and store it. I.e., the writers will collide, but * they'll be writing the same value. */ if (cache_element->t >= seconds) { /* There is an intentional race condition in this design: * in a multithreaded app, one thread might be reading * from this cache_element to resolve a timestamp from * TIME_CACHE_SIZE seconds ago at the same time that * another thread is copying the exploded form of the * current time into the same cache_element. (I.e., the * first thread might hit this element of the ring buffer * just as the element is being recycled.) This can * also happen at the start of a new second, if a * reader accesses the cache_element after a writer * has updated cache_element.t but before the writer * has finished updating the whole cache_element. * * Rather than trying to prevent this race condition * with locks, we allow it to happen and then detect * and correct it. The detection works like this: * Step 1: Take a "snapshot" of the cache element by * copying it into a temporary buffer. * Step 2: Check whether the snapshot contains consistent * data: the timestamps at the start and end of * the cache_element should both match the 'seconds' * value that we computed from the input time. * If these three don't match, then the snapshot * shows the cache_element in the middle of an * update, and its contents are invalid. * Step 3: If the snapshot is valid, use it. Otherwise, * just give up on the cache and explode the * input time. */ memcpy(&cache_element_snapshot, cache_element, sizeof(struct exploded_time_cache_element)); if ((seconds != cache_element_snapshot.t) || (seconds != cache_element_snapshot.t_validate)) { /* Invalid snapshot */ if (use_gmt) { return apr_time_exp_gmt(xt, t); } else { return apr_time_exp_lt(xt, t); } } else { /* Valid snapshot */ memcpy(xt, &(cache_element_snapshot.xt), sizeof(apr_time_exp_t)); } } else { apr_status_t r; if (use_gmt) { r = apr_time_exp_gmt(xt, t); } else { r = apr_time_exp_lt(xt, t); } if (!APR_STATUS_IS_SUCCESS(r)) { return r; } cache_element->t = seconds; memcpy(&(cache_element->xt), xt, sizeof(apr_time_exp_t)); cache_element->t_validate = seconds; } xt->tm_usec = (int)apr_time_usec(t); return APR_SUCCESS; }
SWITCH_DECLARE(switch_status_t) switch_time_exp_lt(switch_time_exp_t *result, switch_time_t input) { return apr_time_exp_lt((apr_time_exp_t *) result, input); }
const char * svn_time_to_human_cstring(apr_time_t when, apr_pool_t *pool) { apr_time_exp_t exploded_time; apr_size_t len, retlen; apr_status_t ret; char *datestr, *curptr, human_datestr[SVN_TIME__MAX_LENGTH]; /* Get the time into parts */ ret = apr_time_exp_lt(&exploded_time, when); if (ret) return NULL; /* Make room for datestring */ datestr = apr_palloc(pool, SVN_TIME__MAX_LENGTH); /* Put in machine parseable part */ len = apr_snprintf(datestr, SVN_TIME__MAX_LENGTH, HUMAN_TIMESTAMP_FORMAT, exploded_time.tm_year + 1900, exploded_time.tm_mon + 1, exploded_time.tm_mday, exploded_time.tm_hour, exploded_time.tm_min, exploded_time.tm_sec, exploded_time.tm_gmtoff / (60 * 60), (abs(exploded_time.tm_gmtoff) / 60) % 60); /* If we overfilled the buffer, just return what we got. */ if (len >= SVN_TIME__MAX_LENGTH) return datestr; /* Calculate offset to the end of the machine parseable part. */ curptr = datestr + len; /* Put in human explanatory part */ ret = apr_strftime(human_datestr, &retlen, SVN_TIME__MAX_LENGTH - len, human_timestamp_format_suffix, &exploded_time); /* If there was an error, ensure that the string is zero-terminated. */ if (ret || retlen == 0) *curptr = '\0'; else { const char *utf8_string; svn_error_t *err; err = svn_utf_cstring_to_utf8(&utf8_string, human_datestr, pool); if (err) { *curptr = '\0'; svn_error_clear(err); } else apr_cpystrn(curptr, utf8_string, SVN_TIME__MAX_LENGTH - len); } return datestr; }
/* Send the authentication to the log table */ int pg_log_auth_user(request_rec * r, pg_auth_config_rec * sec, char *user, char *sent_pw) { char sql[MAX_STRING_LEN]; char *s; int n; char fields[MAX_STRING_LEN]; char values[MAX_STRING_LEN]; char *safe_user; char *safe_pw; char *safe_req; char ts[MAX_STRING_LEN]; /* time in string format */ apr_time_exp_t t; /* time of request start */ apr_size_t retsize; safe_user = apr_palloc(r->pool, 1 + 2 * strlen(user)); safe_pw = apr_palloc(r->pool, 1 + 2 * strlen(sent_pw)); safe_req = apr_palloc(r->pool, 1 + 2 * strlen(r->the_request)); /* we do not want to process internal redirect */ if (!ap_is_initial_req(r)) return DECLINED; if ((!sec->auth_pg_log_table) || (!sec->auth_pg_log_uname_field) || (!sec->auth_pg_log_date_field)) { // At least table name, username and date field are specified // send error message and exit return DECLINED; } /* AUD: MAX_STRING_LEN probably isn't always correct */ pg_check_string(safe_user, user, strlen(user)); pg_check_string(safe_pw, sent_pw, strlen(sent_pw)); pg_check_string(safe_req, r->the_request, strlen(r->the_request)); if (sec->auth_pg_lowercaseuid) { /* and force it to lowercase */ n = 0; while (safe_user[n] && n < (MAX_STRING_LEN - 1)) { if (isupper(safe_user[n])) { safe_user[n] = tolower(safe_user[n]); } n++; } } if (sec->auth_pg_uppercaseuid) { /* and force it to uppercase */ n = 0; while (safe_user[n] && n < (MAX_STRING_LEN - 1)) { if (islower(safe_user[n])) { safe_user[n] = toupper(safe_user[n]); } n++; } } /* time field format */ apr_time_exp_lt(&t, r->request_time); apr_strftime(ts, &retsize, 100, "%Y-%m-%d %H:%M:%S", &t); /* SQL Statement, required fields: Username, Date */ apr_snprintf(fields, MAX_STRING_LEN, "%s,%s", sec->auth_pg_log_uname_field, sec->auth_pg_log_date_field); apr_snprintf(values, MAX_STRING_LEN, "'%s','%s'", safe_user, ts); /* Optional parameters */ if (sec->auth_pg_log_addrs_field) { /* IP Address field */ apr_snprintf(sql, MAX_STRING_LEN, ", %s", sec->auth_pg_log_addrs_field); strncat(fields, sql, MAX_STRING_LEN - strlen(fields) - 1); apr_snprintf(sql, MAX_STRING_LEN, ", '%s'", r->connection->remote_ip); strncat(values, sql, MAX_STRING_LEN - strlen(values) - 1); } if (sec->auth_pg_log_pwd_field) { /* Password field , clear WARNING */ apr_snprintf(sql, MAX_STRING_LEN, ", %s", sec->auth_pg_log_pwd_field); strncat(fields, sql, MAX_STRING_LEN - strlen(fields) - 1); apr_snprintf(sql, MAX_STRING_LEN, ", '%s'", safe_pw); strncat(values, sql, MAX_STRING_LEN - strlen(values) - 1); } if (sec->auth_pg_log_uri_field) { /* request string */ apr_snprintf(sql, MAX_STRING_LEN, ", %s", sec->auth_pg_log_uri_field); strncat(fields, sql, MAX_STRING_LEN - strlen(fields) - 1); apr_snprintf(sql, MAX_STRING_LEN, ", '%s'", safe_req); strncat(values, sql, MAX_STRING_LEN - strlen(values) - 1); } apr_snprintf(sql, MAX_STRING_LEN, "insert into %s (%s) values(%s) ; ", sec->auth_pg_log_table, fields, values); s = do_pg_query(r, sql, sec); return (0); }
/* This function must remain safe to use for a non-SSL connection. */ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, char *var) { SSLModConfigRec *mc = myModConfig(s); const char *result; BOOL resdup; apr_time_exp_t tm; result = NULL; resdup = TRUE; /* * When no pool is given try to find one */ if (p == NULL) { if (r != NULL) p = r->pool; else if (c != NULL) p = c->pool; else p = mc->pPool; } /* * Request dependent stuff */ if (r != NULL) { switch (var[0]) { case 'H': case 'h': if (strcEQ(var, "HTTP_USER_AGENT")) result = apr_table_get(r->headers_in, "User-Agent"); else if (strcEQ(var, "HTTP_REFERER")) result = apr_table_get(r->headers_in, "Referer"); else if (strcEQ(var, "HTTP_COOKIE")) result = apr_table_get(r->headers_in, "Cookie"); else if (strcEQ(var, "HTTP_FORWARDED")) result = apr_table_get(r->headers_in, "Forwarded"); else if (strcEQ(var, "HTTP_HOST")) result = apr_table_get(r->headers_in, "Host"); else if (strcEQ(var, "HTTP_PROXY_CONNECTION")) result = apr_table_get(r->headers_in, "Proxy-Connection"); else if (strcEQ(var, "HTTP_ACCEPT")) result = apr_table_get(r->headers_in, "Accept"); else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5)) /* all other headers from which we are still not know about */ result = apr_table_get(r->headers_in, var+5); break; case 'R': case 'r': if (strcEQ(var, "REQUEST_METHOD")) result = r->method; else if (strcEQ(var, "REQUEST_SCHEME")) result = ap_http_scheme(r); else if (strcEQ(var, "REQUEST_URI")) result = r->uri; else if (strcEQ(var, "REQUEST_FILENAME")) result = r->filename; else if (strcEQ(var, "REMOTE_ADDR")) result = r->useragent_ip; else if (strcEQ(var, "REMOTE_HOST")) result = ap_get_useragent_host(r, REMOTE_NAME, NULL); else if (strcEQ(var, "REMOTE_IDENT")) result = ap_get_remote_logname(r); else if (strcEQ(var, "REMOTE_USER")) result = r->user; break; case 'S': case 's': if (strcEQn(var, "SSL", 3)) break; /* shortcut common case */ if (strcEQ(var, "SERVER_ADMIN")) result = r->server->server_admin; else if (strcEQ(var, "SERVER_NAME")) result = ap_get_server_name_for_url(r); else if (strcEQ(var, "SERVER_PORT")) result = apr_psprintf(p, "%u", ap_get_server_port(r)); else if (strcEQ(var, "SERVER_PROTOCOL")) result = r->protocol; else if (strcEQ(var, "SCRIPT_FILENAME")) result = r->filename; break; default: if (strcEQ(var, "PATH_INFO")) result = r->path_info; else if (strcEQ(var, "QUERY_STRING")) result = r->args; else if (strcEQ(var, "IS_SUBREQ")) result = (r->main != NULL ? "true" : "false"); else if (strcEQ(var, "DOCUMENT_ROOT")) result = ap_document_root(r); else if (strcEQ(var, "AUTH_TYPE")) result = r->ap_auth_type; else if (strcEQ(var, "THE_REQUEST")) result = r->the_request; else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) { result = apr_table_get(r->notes, var+4); if (result == NULL) result = apr_table_get(r->subprocess_env, var+4); } break; } } /* * Connection stuff */ if (result == NULL && c != NULL) { SSLConnRec *sslconn = ssl_get_effective_config(c); if (strlen(var) > 4 && strcEQn(var, "SSL_", 4) && sslconn && sslconn->ssl) result = ssl_var_lookup_ssl(p, sslconn, r, var+4); else if (strcEQ(var, "HTTPS")) { if (sslconn && sslconn->ssl) result = "on"; else result = "off"; } } /* * Totally independent stuff */ if (result == NULL) { if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12)) result = ssl_var_lookup_ssl_version(p, var+12); else if (strcEQ(var, "SERVER_SOFTWARE")) result = ap_get_server_banner(); else if (strcEQ(var, "API_VERSION")) { result = apr_itoa(p, MODULE_MAGIC_NUMBER_MAJOR); resdup = FALSE; } else if (strcEQ(var, "TIME_YEAR")) { apr_time_exp_lt(&tm, apr_time_now()); result = apr_psprintf(p, "%02d%02d", (tm.tm_year / 100) + 19, tm.tm_year % 100); resdup = FALSE; } #define MKTIMESTR(format, tmfield) \ apr_time_exp_lt(&tm, apr_time_now()); \ result = apr_psprintf(p, format, tm.tmfield); \ resdup = FALSE; else if (strcEQ(var, "TIME_MON")) { MKTIMESTR("%02d", tm_mon+1) } else if (strcEQ(var, "TIME_DAY")) { MKTIMESTR("%02d", tm_mday) } else if (strcEQ(var, "TIME_HOUR")) { MKTIMESTR("%02d", tm_hour) } else if (strcEQ(var, "TIME_MIN")) { MKTIMESTR("%02d", tm_min) } else if (strcEQ(var, "TIME_SEC")) { MKTIMESTR("%02d", tm_sec) } else if (strcEQ(var, "TIME_WDAY")) { MKTIMESTR("%d", tm_wday) } else if (strcEQ(var, "TIME")) { apr_time_exp_lt(&tm, apr_time_now()); result = apr_psprintf(p, "%02d%02d%02d%02d%02d%02d%02d", (tm.tm_year / 100) + 19, (tm.tm_year % 100), tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); resdup = FALSE; } /* all other env-variables from the parent Apache process */ else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) { result = getenv(var+4); } } if (result != NULL && resdup) result = apr_pstrdup(p, result); if (result == NULL) result = ""; return (char *)result; }
/* Deprecated */ APR_DECLARE(apr_status_t) apr_explode_localtime(apr_time_exp_t *result, apr_time_t input) { return apr_time_exp_lt(result, input); }