// Called by parent process. static std::string read_pipe(apr_file_t* in, bool timeout_ok = false) { char buf[256]; unsigned char bytes_to_read; apr_size_t bytes_read; apr_status_t status = apr_file_read_full(in, &bytes_to_read, 1, &bytes_read); if (status != APR_SUCCESS) { if (APR_STATUS_IS_TIMEUP(status) && timeout_ok) { return "TIMEOUT"; } llwarns << "apr_file_read_full: " << apr_strerror(status, buf, sizeof(buf)) << llendl; assert(APR_STATUS_IS_EOF(status)); return "END OF FILE"; } assert(bytes_read == 1); status = apr_file_read_full(in, buf, bytes_to_read, &bytes_read); if (status != APR_SUCCESS) { llwarns << "apr_file_read_full: " << apr_strerror(status, buf, sizeof(buf)) << llendl; assert(status == APR_SUCCESS); // Fail } assert(bytes_read == bytes_to_read); std::string received(buf, bytes_read); llinfos << "Received: \"" << received << "\" (bytes read: " << bytes_read << ")" << llendl; return received; }
static void create_segments(geo_db *geo) { int i, j; unsigned char delim[3]; unsigned char buf[GEO_SEGMENT_RECORD_LENGTH]; apr_size_t nbytes; apr_off_t offset; geo->ctry_offset = 0; geo->dbtype = GEOIP_COUNTRY_EDITION; offset = -3l; apr_file_seek(geo->db, APR_END, &offset); for (i = 0; i < GEO_STRUCT_INFO_MAX_SIZE; i++) { apr_file_read_full(geo->db, &delim, 3, &nbytes); if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) { apr_file_read_full(geo->db, &geo->dbtype, 1, &nbytes); if (geo->dbtype >= 106) { geo->dbtype -= 105; } if (geo->dbtype == GEOIP_REGION_EDITION_REV0) { geo->ctry_offset = GEO_STATE_BEGIN_REV0; } else if (geo->dbtype == GEOIP_REGION_EDITION_REV1) { geo->ctry_offset = GEO_STATE_BEGIN_REV1; } else if (geo->dbtype == GEOIP_CITY_EDITION_REV0 || geo->dbtype == GEOIP_CITY_EDITION_REV1 || geo->dbtype == GEOIP_ORG_EDITION || geo->dbtype == GEOIP_ISP_EDITION || geo->dbtype == GEOIP_ASNUM_EDITION) { geo->ctry_offset = 0; apr_file_read_full(geo->db, &buf, GEO_SEGMENT_RECORD_LENGTH, &nbytes); for (j = 0; j < GEO_SEGMENT_RECORD_LENGTH; j++) { geo->ctry_offset += (buf[j] << (j * 8)); } } break; } else { offset = -4l; apr_file_seek(geo->db, APR_CUR, &offset); } } if (geo->dbtype == GEOIP_COUNTRY_EDITION || geo->dbtype == GEOIP_PROXY_EDITION || geo->dbtype == GEOIP_NETSPEED_EDITION) { geo->ctry_offset = GEO_COUNTRY_BEGIN; } }
static void test_fail_read_flush(CuTest *tc) { apr_file_t *f; const char *fname = "data/testflush.dat"; apr_status_t rv; char buf[2]; apr_file_remove(fname, p); apr_assert_success(tc, "open test file", apr_file_open(&f, fname, APR_CREATE|APR_READ|APR_BUFFERED, APR_UREAD|APR_UWRITE, p)); /* this write should be buffered. */ apr_assert_success(tc, "buffered write should succeed", apr_file_puts("hello", f)); /* Now, trying a read should fail since the write must be flushed, * and should fail with something other than EOF since the file is * opened read-only. */ rv = apr_file_read_full(f, buf, 2, NULL); CuAssert(tc, "read should flush buffered write and fail", rv != APR_SUCCESS && rv != APR_EOF); /* Likewise for gets */ rv = apr_file_gets(buf, 2, f); CuAssert(tc, "gets should flush buffered write and fail", rv != APR_SUCCESS && rv != APR_EOF); apr_file_close(f); apr_file_remove(fname, p); }
apr_status_t procmgr_fetch_cmd(fcgid_command * command, server_rec * main_server) { apr_status_t rv; /* Sanity check */ if (!g_pm_read_pipe) return APR_EPIPE; /* Wait for next command */ #if APR_MAJOR_VERSION < 2 rv = apr_wait_for_io_or_timeout(g_pm_read_pipe, NULL, FOR_READ); #else rv = apr_file_pipe_wait(g_pm_read_pipe, APR_WAIT_READ); #endif /* Log any unexpect result */ if (rv != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(rv)) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, main_server, "mod_fcgid: error while waiting for message from pipe"); return rv; } /* Timeout */ if (rv != APR_SUCCESS) return rv; return apr_file_read_full(g_pm_read_pipe, command, sizeof(*command), NULL); }
/* These two functions get and put state information into the data * file for an ap_cache_el, this state information will be read * and written transparent to clients of this module */ static int file_cache_recall_mydata(apr_file_t *fd, cache_info *info, disk_cache_object_t *dobj, request_rec *r) { apr_status_t rv; char *urlbuff; disk_cache_info_t disk_info; apr_size_t len; /* read the data from the cache file */ len = sizeof(disk_cache_info_t); rv = apr_file_read_full(fd, &disk_info, len, &len); if (rv != APR_SUCCESS) { return rv; } /* Store it away so we can get it later. */ dobj->disk_info = disk_info; info->status = disk_info.status; info->date = disk_info.date; info->expire = disk_info.expire; info->request_time = disk_info.request_time; info->response_time = disk_info.response_time; /* Note that we could optimize this by conditionally doing the palloc * depending upon the size. */ urlbuff = apr_palloc(r->pool, disk_info.name_len + 1); len = disk_info.name_len; rv = apr_file_read_full(fd, urlbuff, len, &len); if (rv != APR_SUCCESS) { return rv; } urlbuff[disk_info.name_len] = '\0'; /* check that we have the same URL */ /* Would strncmp be correct? */ if (strcmp(urlbuff, dobj->name) != 0) { return APR_EGENERAL; } return APR_SUCCESS; }
int get_password(struct passwd_ctx *ctx) { char buf[MAX_STRING_LEN + 1]; if (ctx->passwd_src == PW_STDIN) { apr_file_t *file_stdin; apr_size_t nread; if (apr_file_open_stdin(&file_stdin, ctx->pool) != APR_SUCCESS) { ctx->errstr = "Unable to read from stdin."; return ERR_GENERAL; } if (apr_file_read_full(file_stdin, buf, sizeof(buf) - 1, &nread) != APR_EOF || nread == sizeof(buf) - 1) { goto err_too_long; } buf[nread] = '\0'; if (nread >= 1 && buf[nread-1] == '\n') { buf[nread-1] = '\0'; if (nread >= 2 && buf[nread-2] == '\r') buf[nread-2] = '\0'; } apr_file_close(file_stdin); ctx->passwd = apr_pstrdup(ctx->pool, buf); } else if (ctx->passwd_src == PW_PROMPT_VERIFY) { apr_size_t bufsize = sizeof(buf); if (apr_password_get("Enter password: "******"New password: "******"Re-type new password: "******"password verification error"; memset(ctx->passwd, '\0', strlen(ctx->passwd)); memset(buf, '\0', sizeof(buf)); return ERR_PWMISMATCH; } } memset(buf, '\0', sizeof(buf)); return 0; err_too_long: ctx->errstr = apr_psprintf(ctx->pool, "password too long (>%" APR_SIZE_T_FMT ")", ctx->out_len - 1); return ERR_OVERFLOW; }
static void test_xthread(abts_case *tc, void *data) { apr_file_t *f; const char *fname = "data/testxthread.dat"; apr_status_t rv; apr_int32_t flags = APR_FOPEN_CREATE|APR_FOPEN_READ|APR_FOPEN_WRITE|APR_FOPEN_APPEND|APR_FOPEN_XTHREAD; char buf[128] = { 0 }; /* Test for bug 38438, opening file with append + xthread and seeking to the end of the file resulted in writes going to the beginning not the end. */ apr_file_remove(fname, p); APR_ASSERT_SUCCESS(tc, "open test file", apr_file_open(&f, fname, flags, APR_UREAD|APR_UWRITE, p)); APR_ASSERT_SUCCESS(tc, "write should succeed", apr_file_puts("hello", f)); apr_file_close(f); APR_ASSERT_SUCCESS(tc, "open test file", apr_file_open(&f, fname, flags, APR_UREAD|APR_UWRITE, p)); /* Seek to the end. */ { apr_off_t offset = 0; rv = apr_file_seek(f, APR_END, &offset); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); } APR_ASSERT_SUCCESS(tc, "more writes should succeed", apr_file_puts("world", f)); /* Back to the beginning. */ { apr_off_t offset = 0; rv = apr_file_seek(f, APR_SET, &offset); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); } apr_file_read_full(f, buf, sizeof(buf), NULL); ABTS_STR_EQUAL(tc, "helloworld", buf); apr_file_close(f); }
/* Compare two open files. The file positions may change. */ static svn_error_t * compare_files(apr_file_t *f1, apr_file_t *f2, int dump_files) { static char file_buffer_1[10240]; static char file_buffer_2[10240]; char *c1, *c2; apr_off_t pos = 0; apr_size_t len1, len2; rewind_file(f1); rewind_file(f2); if (dump_files) dump_file_contents(f2); do { apr_file_read_full(f1, file_buffer_1, sizeof file_buffer_1, &len1); apr_file_read_full(f2, file_buffer_2, sizeof file_buffer_2, &len2); for (c1 = file_buffer_1, c2 = file_buffer_2; c1 < file_buffer_1 + len1 && c2 < file_buffer_2 + len2; ++c1, ++c2, ++pos) { if (*c1 != *c2) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "mismatch at position %"APR_OFF_T_FMT, pos); } if (len1 != len2) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "unequal file sizes at position" " %"APR_OFF_T_FMT, pos); } while (len1 == sizeof file_buffer_1); return SVN_NO_ERROR; }
static void dump_file_contents(apr_file_t *fp) { static char file_buffer[10240]; apr_size_t length = sizeof file_buffer; fputs("--------\n", stdout); do { apr_file_read_full(fp, file_buffer, sizeof file_buffer, &length); fwrite(file_buffer, 1, length, stdout); } while (length == sizeof file_buffer); putc('\n', stdout); rewind_file(fp); }
static void test_xthread(CuTest *tc) { apr_file_t *f; const char *fname = "data/testxthread.dat"; apr_status_t rv; apr_int32_t flags = APR_CREATE|APR_READ|APR_WRITE|APR_APPEND|APR_XTHREAD; char buf[128] = { 0 }; /* Test for bug 38438, opening file with append + xthread and seeking to the end of the file resulted in writes going to the beginning not the end. */ apr_file_remove(fname, p); rv = apr_file_open(&f, fname, flags, APR_UREAD|APR_UWRITE, p); CuAssert(tc, "open test file", rv == APR_SUCCESS); rv = apr_file_puts("hello", f); CuAssert(tc, "write should succeed", rv == APR_SUCCESS); apr_file_close(f); rv = apr_file_open(&f, fname, flags, APR_UREAD|APR_UWRITE, p); CuAssert(tc, "open test file", rv == APR_SUCCESS); /* Seek to the end. */ { apr_off_t offset = 0; rv = apr_file_seek(f, APR_END, &offset); } rv = apr_file_puts("world", f); CuAssert(tc, "more writes should succeed", rv == APR_SUCCESS); /* Back to the beginning. */ { apr_off_t offset = 0; rv = apr_file_seek(f, APR_SET, &offset); } apr_file_read_full(f, buf, sizeof(buf), NULL); CuAssertStrEquals(tc, "helloworld", buf); apr_file_close(f); }
static apr_status_t FileRead( void *opaque, apr_byte_t *buffer, apr_size_t bytesToRead, apr_size_t *bytesRead ) { apr_file_t *file = opaque; ASSERT(opaque != NULL); ASSERT(buffer != NULL); return apr_file_read_full(file, buffer, bytesToRead, bytesRead); }
AP_DECLARE(apr_status_t) ap_read_pid(apr_pool_t *p, const char *filename, pid_t *mypid) { const apr_size_t BUFFER_SIZE = sizeof(long) * 3 + 2; /* see apr_ltoa */ apr_file_t *pid_file = NULL; apr_status_t rv; const char *fname; char *buf, *endptr; apr_size_t bytes_read; if (!filename) { return APR_EGENERAL; } fname = ap_server_root_relative(p, filename); if (!fname) { ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, APR_EBADPATH, NULL, "Invalid PID file path %s, ignoring.", filename); return APR_EGENERAL; } rv = apr_file_open(&pid_file, fname, APR_READ, APR_OS_DEFAULT, p); if (rv != APR_SUCCESS) { return rv; } buf = apr_palloc(p, BUFFER_SIZE); rv = apr_file_read_full(pid_file, buf, BUFFER_SIZE - 1, &bytes_read); if (rv != APR_SUCCESS && rv != APR_EOF) { return rv; } /* If we fill the buffer, we're probably reading a corrupt pid file. * To be nice, let's also ensure the first char is a digit. */ if (bytes_read == 0 || bytes_read == BUFFER_SIZE - 1 || !apr_isdigit(*buf)) { return APR_EGENERAL; } buf[bytes_read] = '\0'; *mypid = strtol(buf, &endptr, 10); apr_file_close(pid_file); return APR_SUCCESS; }
char * avro_util_file_read_full (apr_pool_t * pool, const char *fname, apr_size_t * len) { apr_status_t status; apr_finfo_t finfo; apr_file_t *file; char *rval; apr_size_t bytes_read; /* open the file */ status = apr_file_open (&file, fname, APR_READ, 0, pool); if (status != APR_SUCCESS) { return NULL; } /* get the file length */ status = apr_file_info_get (&finfo, APR_FINFO_SIZE, file); if (status != APR_SUCCESS) { return NULL; } /* alloc space for the data */ rval = apr_palloc (pool, finfo.size + 1); if (!rval) { return NULL; } /* read in the data */ status = apr_file_read_full (file, rval, finfo.size, &bytes_read); if (status != APR_SUCCESS) { return NULL; } rval[finfo.size] = '\0'; if (len) { *len = bytes_read; } return rval; }
static void test_fail_read_flush(abts_case *tc, void *data) { apr_file_t *f; const char *fname = "data/testflush.dat"; apr_status_t rv; char buf[2]; apr_file_remove(fname, p); APR_ASSERT_SUCCESS(tc, "open test file", apr_file_open(&f, fname, APR_CREATE|APR_READ|APR_BUFFERED, APR_UREAD|APR_UWRITE, p)); /* this write should be buffered. */ APR_ASSERT_SUCCESS(tc, "buffered write should succeed", apr_file_puts("hello", f)); /* Now, trying a read should fail since the write must be flushed, * and should fail with something other than EOF since the file is * opened read-only. */ rv = apr_file_read_full(f, buf, 2, NULL); ABTS_ASSERT(tc, "read should flush buffered write and fail", rv != APR_SUCCESS && rv != APR_EOF); /* Likewise for gets */ rv = apr_file_gets(buf, 2, f); ABTS_ASSERT(tc, "gets should flush buffered write and fail", rv != APR_SUCCESS && rv != APR_EOF); /* Likewise for seek. */ { apr_off_t offset = 0; rv = apr_file_seek(f, APR_SET, &offset); } ABTS_ASSERT(tc, "seek should flush buffered write and fail", rv != APR_SUCCESS && rv != APR_EOF); apr_file_close(f); }
/* Test that the contents of file FNAME are equal to data EXPECT of * length EXPECTLEN. */ static void file_contents_equal(abts_case *tc, const char *fname, const void *expect, apr_size_t expectlen) { void *actual = apr_palloc(p, expectlen); apr_file_t *f; APR_ASSERT_SUCCESS(tc, "open file", apr_file_open(&f, fname, APR_READ|APR_BUFFERED, 0, p)); APR_ASSERT_SUCCESS(tc, "read from file", apr_file_read_full(f, actual, expectlen, NULL)); ABTS_ASSERT(tc, "matched expected file contents", memcmp(expect, actual, expectlen) == 0); APR_ASSERT_SUCCESS(tc, "close file", apr_file_close(f)); }
static void pipe_consumer(toolbox_t *box) { char ch; apr_status_t rv; apr_size_t nbytes; abts_case *tc = box->tc; apr_file_t *out = box->data; apr_uint32_t consumed = 0; do { rv = apr_thread_mutex_lock(box->mutex); ABTS_SUCCESS(rv); while (!pipe_count && !exiting) { rv = apr_thread_cond_wait(box->cond, box->mutex); ABTS_SUCCESS(rv); } if (!pipe_count && exiting) { rv = apr_thread_mutex_unlock(box->mutex); ABTS_SUCCESS(rv); break; } pipe_count--; consumed++; rv = apr_thread_mutex_unlock(box->mutex); ABTS_SUCCESS(rv); rv = apr_file_read_full(out, &ch, 1, &nbytes); ABTS_SUCCESS(rv); ABTS_SIZE_EQUAL(tc, 1, nbytes); ABTS_TRUE(tc, ch == '.'); } while (1); /* naive fairness test - it would be good to introduce or solidify * a solid test to ensure one thread is not starved. * ABTS_INT_EQUAL(tc, 1, !!consumed); */ }
static apr_file_t * copy_tempfile(apr_file_t *fp, apr_pool_t *pool) { static char file_buffer[10240]; apr_file_t *newfp; apr_size_t length1, length2; newfp = open_tempfile("copy_XXXXXX", pool); rewind_file(fp); do { apr_file_read_full(fp, file_buffer, sizeof file_buffer, &length1); apr_file_write_full(newfp, file_buffer, length1, &length2); assert(length1 == length2); } while (length1 == sizeof file_buffer); rewind_file(fp); rewind_file(newfp); return newfp; }
int sha1_file(const std::string& filename, std::string& checksum, bool binary) { apr_initialize(); apr_pool_t* pool; apr_pool_create(&pool, NULL); apr_file_t* in; apr_int32_t flags = (binary ? APR_READ | APR_BINARY : APR_READ); apr_file_open(&in, filename.c_str(), flags, APR_OS_DEFAULT, pool); char buffer[512]; memset(buffer, 0, sizeof(buffer)); apr_size_t bytes_read = 0; apr_file_read_full(in, buffer, 512, &bytes_read); apr_file_close(in); unsigned char digest[APR_SHA1_DIGESTSIZE + 1]; memset(digest, 0, APR_SHA1_DIGESTSIZE + 1); apr_sha1_ctx_t context; apr_sha1_init(&context); if(binary) apr_sha1_update_binary(&context, (const unsigned char*)buffer, bytes_read); else apr_sha1_update(&context, buffer, bytes_read); apr_sha1_final(digest, &context); std::ostringstream oss; for(int i = 0; i < APR_SHA1_DIGESTSIZE; i++) { unsigned short letter = digest[i]; oss << std::hex << std::setw(2) << std::setfill('0') << letter; } checksum = oss.str(); apr_pool_destroy(pool); apr_terminate(); return 0; }
/* Test that the contents of file FNAME are equal to data EXPECT of * length EXPECTLEN. */ static void file_contents_equal(CuTest *tc, const char *fname, const void *expect, apr_size_t expectlen) { void *actual = apr_palloc(p, expectlen); apr_file_t *f; apr_status_t rv; int rc; rv = apr_file_open(&f, fname, APR_READ|APR_BUFFERED, 0, p); CuAssertIntEquals(tc, APR_SUCCESS, rv); rv = apr_file_read_full(f, actual, expectlen, NULL); CuAssertIntEquals(tc, APR_SUCCESS, rv); rc = memcmp(expect, actual, expectlen); CuAssertIntEquals(tc, 0, rc); rv = apr_file_close(f); CuAssertIntEquals(tc, APR_SUCCESS, rv); }
static int open_entity(cache_handle_t *h, request_rec *r, const char *key) { apr_uint32_t format; apr_size_t len; const char *nkey; apr_status_t rc; static int error_logged = 0; disk_cache_conf *conf = ap_get_module_config(r->server->module_config, &disk_cache_module); apr_finfo_t finfo; cache_object_t *obj; cache_info *info; disk_cache_object_t *dobj; int flags; h->cache_obj = NULL; /* Look up entity keyed to 'url' */ if (conf->cache_root == NULL) { if (!error_logged) { error_logged = 1; ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "disk_cache: Cannot cache files to disk without a CacheRoot specified."); } return DECLINED; } /* Create and init the cache object */ h->cache_obj = obj = apr_pcalloc(r->pool, sizeof(cache_object_t)); obj->vobj = dobj = apr_pcalloc(r->pool, sizeof(disk_cache_object_t)); info = &(obj->info); /* Open the headers file */ dobj->prefix = NULL; /* Save the cache root */ dobj->root = apr_pstrndup(r->pool, conf->cache_root, conf->cache_root_len); dobj->root_len = conf->cache_root_len; dobj->hdrsfile = header_file(r->pool, conf, dobj, key); flags = APR_READ|APR_BINARY|APR_BUFFERED; rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool); if (rc != APR_SUCCESS) { return DECLINED; } /* read the format from the cache file */ len = sizeof(format); apr_file_read_full(dobj->hfd, &format, len, &len); if (format == VARY_FORMAT_VERSION) { apr_array_header_t* varray; apr_time_t expire; len = sizeof(expire); apr_file_read_full(dobj->hfd, &expire, len, &len); varray = apr_array_make(r->pool, 5, sizeof(char*)); rc = read_array(r, varray, dobj->hfd); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server, "disk_cache: Cannot parse vary header file: %s", dobj->hdrsfile); return DECLINED; } apr_file_close(dobj->hfd); nkey = regen_key(r->pool, r->headers_in, varray, key); dobj->hashfile = NULL; dobj->prefix = dobj->hdrsfile; dobj->hdrsfile = header_file(r->pool, conf, dobj, nkey); flags = APR_READ|APR_BINARY|APR_BUFFERED; rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool); if (rc != APR_SUCCESS) { return DECLINED; } } else if (format != DISK_FORMAT_VERSION) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "cache_disk: File '%s' has a version mismatch. File had version: %d.", dobj->hdrsfile, format); return DECLINED; } else { apr_off_t offset = 0; /* This wasn't a Vary Format file, so we must seek to the * start of the file again, so that later reads work. */ apr_file_seek(dobj->hfd, APR_SET, &offset); nkey = key; } obj->key = nkey; dobj->key = nkey; dobj->name = key; dobj->datafile = data_file(r->pool, conf, dobj, nkey); dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); /* Open the data file */ flags = APR_READ|APR_BINARY; #ifdef APR_SENDFILE_ENABLED flags |= APR_SENDFILE_ENABLED; #endif rc = apr_file_open(&dobj->fd, dobj->datafile, flags, 0, r->pool); if (rc != APR_SUCCESS) { /* XXX: Log message */ return DECLINED; } rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, dobj->fd); if (rc == APR_SUCCESS) { dobj->file_size = finfo.size; } /* Read the bytes to setup the cache_info fields */ rc = file_cache_recall_mydata(dobj->hfd, info, dobj, r); if (rc != APR_SUCCESS) { /* XXX log message */ return DECLINED; } /* Initialize the cache_handle callback functions */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Recalled cached URL info header %s", dobj->name); return OK; }
/** * Sets the policy file to use from the configuration. * * @param parms the command directive parameters. * @param userdata NULL, not used. * @param arg the string argument to the command directive (the file with * the cross-domain policy to serve as content). * * @return NULL on success, otherwise an error string to display. */ static const char* fsp_set_policy_file( cmd_parms* parms, void* userdata, const char* arg) { const char* rval = NULL; apr_pool_t* pool = (apr_pool_t*)parms->pool; fsp_config* cfg = ap_get_module_config( parms->server->module_config, &fsp_module); // ensure command is in the correct context rval = ap_check_cmd_context(parms, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); if(rval == NULL) { // get canonical file name char* fname = ap_server_root_relative(pool, arg); if(fname == NULL) { rval = (const char*)apr_psprintf( pool, "%s: Invalid policy file '%s'", parms->cmd->name, arg); } else { // try to open the file apr_status_t rv; apr_file_t* fd; apr_finfo_t finfo; rv = apr_file_open(&fd, fname, APR_READ, APR_OS_DEFAULT, pool); if(rv == APR_SUCCESS) { // stat file rv = apr_file_info_get(&finfo, APR_FINFO_NORM, fd); if(rv == APR_SUCCESS) { // ensure file is not empty apr_size_t length = (apr_size_t)finfo.size; if(length <= 0) { rval = (const char*)apr_psprintf( pool, "%s: policy file '%s' is empty", parms->cmd->name, fname); } // read file else { char* buf = (char*)apr_palloc(pool, length + 1); buf[length] = '\0'; rv = apr_file_read_full(fd, buf, length, NULL); if(rv == APR_SUCCESS) { // TODO: validate file // save policy string cfg->policy = buf; cfg->policy_length = length + 1; } } // close the file apr_file_close(fd); } } // handle error case if(rv != APR_SUCCESS) { char errmsg[120]; rval = (const char*)apr_psprintf( pool, "%s: Invalid policy file '%s' (%s)", parms->cmd->name, fname, apr_strerror(rv, errmsg, sizeof(errmsg))); } } } return rval; }
/* * walk the cache directory tree */ static int process_dir(char *path, apr_pool_t *pool) { apr_dir_t *dir; apr_pool_t *p; apr_hash_t *h; apr_hash_index_t *i; apr_file_t *fd; apr_status_t status; apr_finfo_t info; apr_size_t len; apr_time_t current, deviation; char *nextpath, *base, *ext, *orig_basename; APR_RING_ENTRY(_direntry) anchor; DIRENTRY *d, *t, *n; ENTRY *e; int skip, retries; disk_cache_info_t disk_info; APR_RING_INIT(&anchor, _direntry, link); apr_pool_create(&p, pool); h = apr_hash_make(p); fd = NULL; skip = 0; deviation = MAXDEVIATION * APR_USEC_PER_SEC; if (apr_dir_open(&dir, path, p) != APR_SUCCESS) { return 1; } while (apr_dir_read(&info, 0, dir) == APR_SUCCESS && !interrupted) { if (!strcmp(info.name, ".") || !strcmp(info.name, "..")) { continue; } d = apr_pcalloc(p, sizeof(DIRENTRY)); d->basename = apr_pstrcat(p, path, "/", info.name, NULL); APR_RING_INSERT_TAIL(&anchor, d, _direntry, link); } apr_dir_close(dir); if (interrupted) { return 1; } skip = baselen + 1; for (d = APR_RING_FIRST(&anchor); !interrupted && d != APR_RING_SENTINEL(&anchor, _direntry, link); d=n) { n = APR_RING_NEXT(d, link); base = strrchr(d->basename, '/'); if (!base++) { base = d->basename; } ext = strchr(base, '.'); /* there may be temporary files which may be gone before * processing, always skip these if not in realclean mode */ if (!ext && !realclean) { if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN) && strlen(base) == AP_TEMPFILE_NAMELEN) { continue; } } /* this may look strange but apr_stat() may return errno which * is system dependent and there may be transient failures, * so just blindly retry for a short while */ retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, d->basename, DIRINFO, p); } while (status != APR_SUCCESS && !interrupted && --retries); /* what may happen here is that apache did create a file which * we did detect but then does delete the file before we can * get file information, so if we don't get any file information * we will ignore the file in this case */ if (status != APR_SUCCESS) { if (!realclean && !interrupted) { continue; } return 1; } if (info.filetype == APR_DIR) { /* Make a copy of the basename, as process_dir modifies it */ orig_basename = apr_pstrdup(pool, d->basename); if (process_dir(d->basename, pool)) { return 1; } /* If asked to delete dirs, do so now. We don't care if it fails. * If it fails, it likely means there was something else there. */ if (deldirs && !dryrun) { apr_dir_remove(orig_basename, pool); } continue; } if (info.filetype != APR_REG) { continue; } if (!ext) { if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN) && strlen(base) == AP_TEMPFILE_NAMELEN) { d->basename += skip; d->type = TEMP; d->dsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); } continue; } if (!strcasecmp(ext, CACHE_HEADER_SUFFIX)) { *ext = '\0'; d->basename += skip; /* if a user manually creates a '.header' file */ if (d->basename[0] == '\0') { continue; } t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING); if (t) { d = t; } d->type |= HEADER; d->htime = info.mtime; d->hsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); continue; } if (!strcasecmp(ext, CACHE_DATA_SUFFIX)) { *ext = '\0'; d->basename += skip; /* if a user manually creates a '.data' file */ if (d->basename[0] == '\0') { continue; } t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING); if (t) { d = t; } d->type |= DATA; d->dtime = info.mtime; d->dsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); } } if (interrupted) { return 1; } path[baselen] = '\0'; for (i = apr_hash_first(p, h); i && !interrupted; i = apr_hash_next(i)) { void *hvalue; apr_uint32_t format; apr_hash_this(i, NULL, NULL, &hvalue); d = hvalue; switch(d->type) { case HEADERDATA: nextpath = apr_pstrcat(p, path, "/", d->basename, CACHE_HEADER_SUFFIX, NULL); if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY, APR_OS_DEFAULT, p) == APR_SUCCESS) { len = sizeof(format); if (apr_file_read_full(fd, &format, len, &len) == APR_SUCCESS) { if (format == DISK_FORMAT_VERSION) { apr_off_t offset = 0; apr_file_seek(fd, APR_SET, &offset); len = sizeof(disk_cache_info_t); if (apr_file_read_full(fd, &disk_info, len, &len) == APR_SUCCESS) { apr_file_close(fd); e = apr_palloc(pool, sizeof(ENTRY)); APR_RING_INSERT_TAIL(&root, e, _entry, link); e->expire = disk_info.expire; e->response_time = disk_info.response_time; e->htime = d->htime; e->dtime = d->dtime; e->hsize = d->hsize; e->dsize = d->dsize; e->basename = apr_pstrdup(pool, d->basename); break; } else { apr_file_close(fd); } } else if (format == VARY_FORMAT_VERSION) { /* This must be a URL that added Vary headers later, * so kill the orphaned .data file */ apr_file_close(fd); apr_file_remove(apr_pstrcat(p, path, "/", d->basename, CACHE_DATA_SUFFIX, NULL), p); } } else { apr_file_close(fd); } } /* we have a somehow unreadable headers file which is associated * with a data file. this may be caused by apache currently * rewriting the headers file. thus we may delete the file set * either in realclean mode or if the headers file modification * timestamp is not within a specified positive or negative offset * to the current time. */ current = apr_time_now(); if (realclean || d->htime < current - deviation || d->htime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->hsize; unsolicited += d->dsize; } break; /* single data and header files may be deleted either in realclean * mode or if their modification timestamp is not within a * specified positive or negative offset to the current time. * this handling is necessary due to possible race conditions * between apache and this process */ case HEADER: current = apr_time_now(); nextpath = apr_pstrcat(p, path, "/", d->basename, CACHE_HEADER_SUFFIX, NULL); if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY, APR_OS_DEFAULT, p) == APR_SUCCESS) { len = sizeof(format); if (apr_file_read_full(fd, &format, len, &len) == APR_SUCCESS) { if (format == VARY_FORMAT_VERSION) { apr_time_t expires; len = sizeof(expires); apr_file_read_full(fd, &expires, len, &len); apr_file_close(fd); if (expires < current) { delete_entry(path, d->basename, p); } break; } } apr_file_close(fd); } if (realclean || d->htime < current - deviation || d->htime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->hsize; } break; case DATA: current = apr_time_now(); if (realclean || d->dtime < current - deviation || d->dtime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->dsize; } break; /* temp files may only be deleted in realclean mode which * is asserted above if a tempfile is in the hash array */ case TEMP: delete_file(path, d->basename, p); unsolicited += d->dsize; break; } } if (interrupted) { return 1; } apr_pool_destroy(p); if (benice) { apr_sleep(NICE_DELAY); } if (interrupted) { return 1; } return 0; }
/** * Perform geographical lookup on target. */ int geo_lookup(modsec_rec *msr, geo_rec *georec, const char *target, char **error_msg) { apr_sockaddr_t *addr; long ipnum = 0; char *targetip = NULL; geo_db *geo = msr->txcfg->geo; char errstr[1024]; unsigned char buf[2* GEO_MAX_RECORD_LEN]; const int reclen = 3; /* Algorithm needs changed if this changes */ apr_size_t nbytes; unsigned int rec_val = 0; apr_off_t seekto = 0; apr_status_t ret; int rc; int country = 0; int level; double dtmp; int itmp; *error_msg = NULL; /* init */ georec->country_code = geo_country_code[0]; georec->country_code3 = geo_country_code3[0]; georec->country_name = geo_country_name[0]; georec->country_continent = geo_country_continent[0]; georec->region = ""; georec->city = ""; georec->postal_code = ""; georec->latitude = 0; georec->longitude = 0; georec->dma_code = 0; georec->area_code = 0; if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: Looking up \"%s\".", log_escape(msr->mp, target)); } /* NOTE: This only works with ipv4 */ if ((rc = apr_sockaddr_info_get(&addr, target, APR_INET, 0, 0, msr->mp)) != APR_SUCCESS) { *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" failed: %s", log_escape(msr->mp, target), apr_strerror(rc, errstr, 1024)); msr_log(msr, 4, "%s", *error_msg); return 0; } if ((rc = apr_sockaddr_ip_get(&targetip, addr)) != APR_SUCCESS) { *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" failed: %s", log_escape(msr->mp, target), apr_strerror(rc, errstr, 1024)); msr_log(msr, 4, "%s", *error_msg); return 0; }; /* Why is this in host byte order? */ ipnum = ntohl(addr->sa.sin.sin_addr.s_addr); if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: Using address \"%s\" (0x%08lx). %lu", targetip, ipnum, ipnum); } ret = apr_global_mutex_lock(msr->modsecurity->geo_lock); if (ret != APR_SUCCESS) { msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s", get_apr_error(msr->mp, ret)); } for (level = 31; level >= 0; level--) { /* Read the record */ seekto = 2 * reclen * rec_val; apr_file_seek(geo->db, APR_SET, &seekto); /* TODO: check rc */ rc = apr_file_read_full(geo->db, &buf, (2 * reclen), &nbytes); /* NOTE: This is hard-coded for size 3 records */ /* Left */ if ((ipnum & (1 << level)) == 0) { rec_val = (buf[3*0 + 0] << (0*8)) + (buf[3*0 + 1] << (1*8)) + (buf[3*0 + 2] << (2*8)); } /* Right */ else { rec_val = (buf[3*1 + 0] << (0*8)) + (buf[3*1 + 1] << (1*8)) + (buf[3*1 + 2] << (2*8)); } /* If we are past the country offset, then we are done */ if (rec_val >= geo->ctry_offset) { break; } } if (rec_val == geo->ctry_offset) { *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\").", log_escape(msr->mp, target)); msr_log(msr, 4, "%s", *error_msg); ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock); if (ret != APR_SUCCESS) { msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s", get_apr_error(msr->mp, ret)); } return 0; } if (geo->dbtype == GEO_COUNTRY_DATABASE) { country = rec_val; country -= geo->ctry_offset; if ((country <= 0) || (country > GEO_COUNTRY_LAST)) { *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\" (country %d).", log_escape(msr->mp, target), country); msr_log(msr, 4, "%s", *error_msg); ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock); if (ret != APR_SUCCESS) { msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s", get_apr_error(msr->mp, ret)); } return 0; } /* Country */ georec->country_code = geo_country_code[country]; georec->country_code3 = geo_country_code3[country]; georec->country_name = geo_country_name[country]; georec->country_continent = geo_country_continent[country]; } else { int field_len = 0; int rec_offset = 0; int remaining = GEO_CITY_RECORD_LEN; unsigned char cbuf[GEO_CITY_RECORD_LEN]; seekto = rec_val + (2 * reclen - 1) * geo->ctry_offset; apr_file_seek(geo->db, APR_SET, &seekto); /* TODO: check rc */ rc = apr_file_read_full(geo->db, &cbuf, sizeof(cbuf), &nbytes); country = cbuf[0]; if ((country <= 0) || (country > GEO_COUNTRY_LAST)) { *error_msg = apr_psprintf(msr->mp, "No geo data for \"%s\" (country %d).", log_escape(msr->mp, target), country); msr_log(msr, 4, "%s", *error_msg); ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock); if (ret != APR_SUCCESS) { msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s", get_apr_error(msr->mp, ret)); } return 0; } if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: rec=\"%s\"", log_escape_raw(msr->mp, cbuf, sizeof(cbuf))); } /* Country */ if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: country=\"%.*s\"", (1*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))); } georec->country_code = geo_country_code[country]; georec->country_code3 = geo_country_code3[country]; georec->country_name = geo_country_name[country]; georec->country_continent = geo_country_continent[country]; rec_offset++; remaining -= rec_offset; /* Region */ field_len = field_length((const char *)cbuf+rec_offset, remaining); if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: region=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4)); } georec->region = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining)); rec_offset += field_len + 1; remaining -= field_len + 1; /* City */ field_len = field_length((const char *)cbuf+rec_offset, remaining); if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: city=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4)); } georec->city = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining)); rec_offset += field_len + 1; remaining -= field_len + 1; /* Postal Code */ field_len = field_length((const char *)cbuf+rec_offset, remaining); if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: postal_code=\"%.*s\"", ((field_len+1)*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4)); } georec->postal_code = apr_pstrmemdup(msr->mp, (const char *)cbuf+rec_offset, (remaining)); rec_offset += field_len + 1; remaining -= field_len + 1; /* Latitude */ if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: latitude=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4)); } dtmp = cbuf[rec_offset] + (cbuf[rec_offset+1] << 8) + (cbuf[rec_offset+2] << 16); georec->latitude = dtmp/10000 - 180; rec_offset += 3; remaining -= 3; /* Longitude */ if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: longitude=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4)); } dtmp = cbuf[rec_offset] + (cbuf[rec_offset+1] << 8) + (cbuf[rec_offset+2] << 16); georec->longitude = dtmp/10000 - 180; rec_offset += 3; remaining -= 3; /* dma/area codes are in city rev1 and US only */ if (msr->txcfg->debuglog_level >= 9) { msr_log(msr, 9, "GEO: dma/area=\"%.*s\"", (3*4), log_escape_raw(msr->mp, cbuf, sizeof(cbuf))+(rec_offset*4)); } if (geo->dbtype == GEO_CITY_DATABASE_1 && georec->country_code[0] == 'U' && georec->country_code[1] == 'S') { /* DMA Code */ itmp = cbuf[rec_offset] + (cbuf[rec_offset+1] << 8) + (cbuf[rec_offset+2] << 16); georec->dma_code = itmp / 1000; georec->area_code = itmp % 1000; rec_offset += 6; remaining -= 6; } } *error_msg = apr_psprintf(msr->mp, "Geo lookup for \"%s\" succeeded.", log_escape(msr->mp, target)); ret = apr_global_mutex_unlock(msr->modsecurity->geo_lock); if (ret != APR_SUCCESS) { msr_log(msr, 1, "Geo Lookup: Failed to lock proc mutex: %s", get_apr_error(msr->mp, ret)); } return 1; }
/** \brief Load GSB database * * \param dcfg Pointer to directory configuration * \param error_msg Error message * * \retval 1 On Success * \retval 0 On Fail */ static int gsb_db_create(directory_config *dcfg, char **error_msg) { char errstr[1024]; apr_pool_t *mp = dcfg->mp; gsb_db *gsb = dcfg->gsb; apr_int32_t wanted = APR_FINFO_SIZE; apr_finfo_t finfo; apr_status_t rc; apr_size_t nbytes; char *buf = NULL, *p = NULL, *savedptr = NULL; char *op = NULL; if ((rc = apr_file_open(&gsb->db, gsb->dbfn, APR_READ, APR_OS_DEFAULT, mp)) != APR_SUCCESS) { *error_msg = apr_psprintf(mp, "Could not open gsb database \"%s\": %s", gsb->dbfn, apr_strerror(rc, errstr, 1024)); return 0; } if ((rc = apr_file_info_get(&finfo, wanted, gsb->db)) != APR_SUCCESS) { *error_msg = apr_psprintf(mp, "Could not cannot get gsb malware file information \"%s\": %s", gsb->dbfn, apr_strerror(rc, errstr, 1024)); apr_file_close(gsb->db); return 0; } buf = (char *)malloc(finfo.size+1); if (buf == NULL) { *error_msg = apr_psprintf(mp, "Could not alloc memory for gsb data"); apr_file_close(gsb->db); return 0; } rc = apr_file_read_full(gsb->db, buf, finfo.size, &nbytes); gsb->gsb_table = apr_hash_make(dcfg->mp); if (gsb->gsb_table == NULL) { *error_msg = apr_psprintf(mp, "Could not alloc memory for gsb table"); free(buf); buf = NULL; apr_file_close(gsb->db); return 0; } p = apr_strtok(buf,"\t",&savedptr); while (p != NULL) { op = strchr(p,'+'); if(op != NULL) { char *hash = ++op; if(strlen(hash) == 32) apr_hash_set(gsb->gsb_table, hash, APR_HASH_KEY_STRING, "malware"); } op = strchr(p,'-'); if(op != NULL) { char *hash = ++op; if(strlen(hash) == 32) apr_hash_set(gsb->gsb_table, hash, APR_HASH_KEY_STRING, NULL); } p = apr_strtok(NULL,"\t",&savedptr); } apr_file_close(gsb->db); free(buf); buf = NULL; return 1; }
void nx_config_cache_read() { nx_ctx_t *ctx; apr_off_t offset = 0; char *buf = NULL; apr_status_t rv; apr_size_t nbytes, bytesread, bytesleft; nx_value_t *version = NULL; apr_file_t *ccfile; nx_exception_t e; ctx = nx_ctx_get(); if ( ctx->nocache == TRUE ) { return; } log_debug("reading config cache from %s", ctx->ccfilename); rv = apr_file_open(&ccfile, ctx->ccfilename, APR_READ, APR_OS_DEFAULT, ctx->pool); if ( APR_STATUS_IS_ENOENT(rv) ) { // nothing to read return; } CHECKERR_MSG(rv, "couldn't open config cache '%s'", ctx->ccfilename); try { CHECKERR_MSG(apr_file_seek(ccfile, APR_END, &offset), "couldn't seek in cache file"); if ( offset > NX_CONFIG_CACHE_LIMIT ) { throw_msg("cache file is too large (%d bytes)", offset); } if ( offset > 0 ) { nbytes = (apr_size_t) offset; buf = malloc((size_t) offset); // seek back to start offset = 0; CHECKERR_MSG(apr_file_seek(ccfile, APR_SET, &offset), "couldn't seek in cache file"); // read cache file into memory if ( (rv = apr_file_read_full(ccfile, buf, nbytes, &bytesread)) != APR_SUCCESS ) { if ( rv != APR_EOF ) { CHECKERR_MSG(rv, "failed to read config cache file"); } } if ( nbytes != bytesread ) { throw_msg("read %d bytes, wanted %d", (int) bytesread, (int) nbytes); } bytesleft = nbytes; version = nx_value_from_membuf(buf, nbytes, &bytesread); if ( version->type != NX_VALUE_TYPE_STRING ) { throw_msg("string expected for config cache version"); } if ( strcmp(version->string->buf, NX_CONFIG_CACHE_VERSION) != 0 ) { throw_msg("config cache version mismatch, expected %s, got %s", NX_CONFIG_CACHE_VERSION, version->string->buf); } bytesleft -= bytesread; while ( bytesleft > 0 ) { _read_item(buf + (nbytes - bytesleft), bytesleft, ctx->config_cache, &bytesread); ASSERT(bytesread <= bytesleft); bytesleft -= bytesread; } } } catch(e) { apr_file_close(ccfile); apr_file_remove(ctx->ccfilename, NULL); if ( buf != NULL ) { free(buf); } if ( version != NULL ) { nx_value_free(version); } rethrow_msg(e, "failed to read config cache"); } if ( buf != NULL ) { free(buf); } if ( version != NULL ) { nx_value_free(version); } apr_file_close(ccfile); //apr_file_remove(ctx->ccfilename, NULL); }
/* 初始化unicode映射表 */ apr_status_t msc_unicode_map_init(apr_pool_t *mp) { char errstr[1024]; unicode_map *u_map; apr_int32_t wanted = APR_FINFO_SIZE; apr_finfo_t finfo; apr_status_t rc; apr_size_t nbytes; unsigned int codepage = 0; char *buf = NULL, *p = NULL, *savedptr = NULL; char *ucode = NULL, *hmap = NULL; int found = 0, processing = 0; int Code = 0, Map = 0; if(unicode_map_table != NULL) { free(unicode_map_table); unicode_map_table = NULL; } u_map = apr_pcalloc(mp, sizeof(unicode_map)); if (u_map == NULL) { return -1; } u_map->map = NULL; u_map->mapfn = ap_server_root_relative(mp, DEF_UNICODEMAPFILE_VAL); if ((rc = apr_file_open(&u_map->map, u_map->mapfn, APR_READ, APR_OS_DEFAULT, mp)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Could not open unicode map file \"%s\": %s", u_map->mapfn, apr_strerror(rc, errstr, 1024)); return -1; } if ((rc = apr_file_info_get(&finfo, wanted, u_map->map)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Could not get unicode map file information \"%s\": %s", u_map->mapfn, apr_strerror(rc, errstr, 1024)); apr_file_close(u_map->map); return -1; } buf = (char *)malloc(finfo.size + 1); if (buf == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Could not alloc memory for unicode map"); apr_file_close(u_map->map); return -1; } rc = apr_file_read_full(u_map->map, buf, finfo.size, &nbytes); if (unicode_map_table != NULL) { memset(unicode_map_table, -1, (sizeof(int)*65536)); } else { unicode_map_table = (int *)malloc(sizeof(int) * 65536); if (unicode_map_table == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Could not alloc memory for unicode map"); free(buf); buf = NULL; apr_file_close(u_map->map); return -1; } memset(unicode_map_table, -1, (sizeof(int)*65536)); } /* Setting some unicode values - http://tools.ietf.org/html/rfc3490#section-3.1 */ /* Set 0x3002 -> 0x2e */ unicode_map_table[0x3002] = 0x2e; /* Set 0xFF61 -> 0x2e */ unicode_map_table[0xff61] = 0x2e; /* Set 0xFF0E -> 0x2e */ unicode_map_table[0xff0e] = 0x2e; /* Set 0x002E -> 0x2e */ unicode_map_table[0x002e] = 0x2e; p = apr_strtok(buf, CODEPAGE_SEPARATORS, &savedptr); while (p != NULL) { codepage = atol(p); if (codepage == unicode_codepage) { found = 1; } if (found == 1 && (strchr(p,':') != NULL)) { char *mapping = strdup(p); processing = 1; if(mapping != NULL) { ucode = apr_strtok(mapping,":", &hmap); sscanf(ucode,"%x",&Code); sscanf(hmap,"%x",&Map); if(Code >= 0 || Code <= 65535) { unicode_map_table[Code] = Map; } free(mapping); mapping = NULL; } } if (processing == 1 && (strchr(p,':') == NULL)) { free(buf); buf = NULL; break; } p = apr_strtok(NULL,CODEPAGE_SEPARATORS,&savedptr); } apr_file_close(u_map->map); free(buf); buf = NULL; apr_pool_cleanup_register(mp, (const void *)unicode_map_table, msc_unicode_map_destroy, apr_pool_cleanup_null); return APR_SUCCESS; }
apr_status_t sha1_file(const std::string& filename, std::string& checksum, bool binary, apr_pool_t* parentPool) { apr_status_t ret = APR_SUCCESS; apr_pool_t* pool = NULL; ret = apr_pool_create(&pool, parentPool); if(ret == APR_SUCCESS) { apr_file_t* in = NULL; apr_int32_t flags = (binary ? APR_READ | APR_BINARY : APR_READ); ret = apr_file_open(&in, filename.c_str(), flags, APR_OS_DEFAULT, pool); if(ret == APR_SUCCESS) { unsigned char digest[APR_SHA1_DIGESTSIZE + 1]; memset(digest, 0, APR_SHA1_DIGESTSIZE + 1); apr_sha1_ctx_t context; apr_sha1_init(&context); unsigned char buffer[512]; memset(buffer, 0, sizeof(buffer)); apr_size_t bytes_read = 0; ret = apr_file_read_full(in, buffer, sizeof(buffer) - 1, &bytes_read); if(ret == APR_SUCCESS || ret == APR_EOF) { if(binary) apr_sha1_update_binary(&context, buffer, bytes_read); else apr_sha1_update(&context, (const char*)buffer, bytes_read); } while(ret == APR_SUCCESS) { ret = apr_file_read_full(in, buffer, sizeof(buffer) - 1, &bytes_read); if(ret == APR_SUCCESS || ret == APR_EOF) { if(binary) apr_sha1_update_binary(&context, buffer, bytes_read); else apr_sha1_update(&context, (const char*)buffer, bytes_read); } } apr_sha1_final(digest, &context); if(ret == APR_EOF) { std::ostringstream oss; for(int i = 0; i < APR_SHA1_DIGESTSIZE; i++) { unsigned short letter = digest[i]; oss << std::hex << std::setw(2) << std::setfill('0') << letter; } checksum = oss.str(); ret = APR_SUCCESS; } apr_file_close(in); } apr_pool_destroy(pool); } return ret; }