📄 util.c
字号:
/* * copy at most n leading directories of s into d * d should be at least as large as s plus 1 extra byte * assumes n > 0 * the return value is the ever useful pointer to the trailing \0 of d * * MODIFIED FOR HAVE_DRIVE_LETTERS and NETWARE environments, * so that if n == 0, "/" is returned in d with n == 1 * and s == "e:/test.html", "e:/" is returned in d * *** See also directory_walk in modules/http/http_request.c * examples: * /a/b, 0 ==> / (true for all platforms) * /a/b, 1 ==> / * /a/b, 2 ==> /a/ * /a/b, 3 ==> /a/b/ * /a/b, 4 ==> /a/b/ * * c:/a/b 0 ==> / * c:/a/b 1 ==> c:/ * c:/a/b 2 ==> c:/a/ * c:/a/b 3 ==> c:/a/b * c:/a/b 4 ==> c:/a/b */AP_DECLARE(char *) ap_make_dirstr_prefix(char *d, const char *s, int n){ if (n < 1) { *d = '/'; *++d = '\0'; return (d); } for (;;) { if (*s == '\0' || (*s == '/' && (--n) == 0)) { *d = '/'; break; } *d++ = *s++; } *++d = 0; return (d);}/* * return the parent directory name including trailing / of the file s */AP_DECLARE(char *) ap_make_dirstr_parent(apr_pool_t *p, const char *s){ const char *last_slash = ap_strrchr_c(s, '/'); char *d; int l; if (last_slash == NULL) { return apr_pstrdup(p, ""); } l = (last_slash - s) + 1; d = apr_palloc(p, l + 1); memcpy(d, s, l); d[l] = 0; return (d);}AP_DECLARE(int) ap_count_dirs(const char *path){ register int x, n; for (x = 0, n = 0; path[x]; x++) if (path[x] == '/') n++; return n;}AP_DECLARE(char *) ap_getword_nc(apr_pool_t *atrans, char **line, char stop){ return ap_getword(atrans, (const char **) line, stop);}AP_DECLARE(char *) ap_getword(apr_pool_t *atrans, const char **line, char stop){ const char *pos = *line; int len; char *res; while ((*pos != stop) && *pos) { ++pos; } len = pos - *line; res = (char *)apr_palloc(atrans, len + 1); memcpy(res, *line, len); res[len] = 0; if (stop) { while (*pos == stop) { ++pos; } } *line = pos; return res;}AP_DECLARE(char *) ap_getword_white_nc(apr_pool_t *atrans, char **line){ return ap_getword_white(atrans, (const char **) line);}AP_DECLARE(char *) ap_getword_white(apr_pool_t *atrans, const char **line){ const char *pos = *line; int len; char *res; while (!apr_isspace(*pos) && *pos) { ++pos; } len = pos - *line; res = (char *)apr_palloc(atrans, len + 1); memcpy(res, *line, len); res[len] = 0; while (apr_isspace(*pos)) { ++pos; } *line = pos; return res;}AP_DECLARE(char *) ap_getword_nulls_nc(apr_pool_t *atrans, char **line, char stop){ return ap_getword_nulls(atrans, (const char **) line, stop);}AP_DECLARE(char *) ap_getword_nulls(apr_pool_t *atrans, const char **line, char stop){ const char *pos = ap_strchr_c(*line, stop); char *res; if (!pos) { res = apr_pstrdup(atrans, *line); *line += strlen(*line); return res; } res = apr_pstrndup(atrans, *line, pos - *line); ++pos; *line = pos; return res;}/* Get a word, (new) config-file style --- quoted strings and backslashes * all honored */static char *substring_conf(apr_pool_t *p, const char *start, int len, char quote){ char *result = apr_palloc(p, len + 2); char *resp = result; int i; for (i = 0; i < len; ++i) { if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) *resp++ = start[++i]; else *resp++ = start[i]; } *resp++ = '\0';#if RESOLVE_ENV_PER_TOKEN return (char *)ap_resolve_env(p,result);#else return result;#endif}AP_DECLARE(char *) ap_getword_conf_nc(apr_pool_t *p, char **line){ return ap_getword_conf(p, (const char **) line);}AP_DECLARE(char *) ap_getword_conf(apr_pool_t *p, const char **line){ const char *str = *line, *strend; char *res; char quote; while (*str && apr_isspace(*str)) ++str; if (!*str) { *line = str; return ""; } if ((quote = *str) == '"' || quote == '\'') { strend = str + 1; while (*strend && *strend != quote) { if (*strend == '\\' && strend[1] && strend[1] == quote) strend += 2; else ++strend; } res = substring_conf(p, str + 1, strend - str - 1, quote); if (*strend == quote) ++strend; } else { strend = str; while (*strend && !apr_isspace(*strend)) ++strend; res = substring_conf(p, str, strend - str, 0); } while (*strend && apr_isspace(*strend)) ++strend; *line = strend; return res;}/* Check a string for any ${ENV} environment variable * construct and replace each them by the value of * that environment variable, if it exists. If the * environment value does not exist, leave the ${ENV} * construct alone; it means something else. */AP_DECLARE(const char *) ap_resolve_env(apr_pool_t *p, const char * word){# define SMALL_EXPANSION 5 struct sll { struct sll *next; const char *string; apr_size_t len; } *result, *current, sresult[SMALL_EXPANSION]; char *res_buf, *cp; const char *s, *e, *ep; unsigned spc; apr_size_t outlen; s = ap_strchr_c(word, '$'); if (!s) { return word; } /* well, actually something to do */ ep = word + strlen(word); spc = 0; result = current = &(sresult[spc++]); current->next = NULL; current->string = word; current->len = s - word; outlen = current->len; do { /* prepare next entry */ if (current->len) { current->next = (spc < SMALL_EXPANSION) ? &(sresult[spc++]) : (struct sll *)apr_palloc(p, sizeof(*current->next)); current = current->next; current->next = NULL; current->len = 0; } if (*s == '$') { if (s[1] == '{' && (e = ap_strchr_c(s, '}'))) { word = getenv(apr_pstrndup(p, s+2, e-s-2)); if (word) { current->string = word; current->len = strlen(word); outlen += current->len; } else { current->string = s; current->len = e - s + 1; outlen += current->len; } s = e + 1; } else { current->string = s++; current->len = 1; ++outlen; } } else { word = s; s = ap_strchr_c(s, '$'); current->string = word; current->len = s ? s - word : ep - word; outlen += current->len; } } while (s && *s); /* assemble result */ res_buf = cp = apr_palloc(p, outlen + 1); do { if (result->len) { memcpy(cp, result->string, result->len); cp += result->len; } result = result->next; } while (result); res_buf[outlen] = '\0'; return res_buf;}AP_DECLARE(int) ap_cfg_closefile(ap_configfile_t *cfp){#ifdef DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "Done with config file %s", cfp->name);#endif return (cfp->close == NULL) ? 0 : cfp->close(cfp->param);}static apr_status_t cfg_close(void *param){ apr_file_t *cfp = (apr_file_t *) param; return (apr_file_close(cfp));}static int cfg_getch(void *param){ char ch; apr_file_t *cfp = (apr_file_t *) param; if (apr_file_getc(&ch, cfp) == APR_SUCCESS) return ch; return (int)EOF;}static void *cfg_getstr(void *buf, size_t bufsiz, void *param){ apr_file_t *cfp = (apr_file_t *) param; apr_status_t rv; rv = apr_file_gets(buf, bufsiz, cfp); if (rv == APR_SUCCESS || (APR_STATUS_IS_EOF(rv) && strcmp(buf, ""))) return buf; return NULL;}/* Open a ap_configfile_t as FILE, return open ap_configfile_t struct pointer */AP_DECLARE(apr_status_t) ap_pcfg_openfile(ap_configfile_t **ret_cfg, apr_pool_t *p, const char *name){ ap_configfile_t *new_cfg; apr_file_t *file = NULL; apr_finfo_t finfo; apr_status_t status;#ifdef DEBUG char buf[120];#endif if (name == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Internal error: pcfg_openfile() called with NULL filename"); return APR_EBADF; } status = apr_file_open(&file, name, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, p);#ifdef DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "Opening config file %s (%s)", name, (status != APR_SUCCESS) ? apr_strerror(status, buf, sizeof(buf)) : "successful");#endif if (status != APR_SUCCESS) return status; status = apr_file_info_get(&finfo, APR_FINFO_TYPE, file); if (status != APR_SUCCESS) return status; if (finfo.filetype != APR_REG &&#if defined(WIN32) || defined(OS2) || defined(NETWARE) strcasecmp(apr_filename_of_pathname(name), "nul") != 0) {#else strcmp(name, "/dev/null") != 0) {#endif /* WIN32 || OS2 */ ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Access to file %s denied by server: not a regular file", name); apr_file_close(file); return APR_EBADF; }#ifdef WIN32 /* Some twisted character [no pun intended] at MS decided that a * zero width joiner as the lead wide character would be ideal for * describing Unicode text files. This was further convoluted to * another MSism that the same character mapped into utf-8, EF BB BF * would signify utf-8 text files. * * Since MS configuration files are all protecting utf-8 encoded * Unicode path, file and resource names, we already have the correct * WinNT encoding. But at least eat the stupid three bytes up front. */ { unsigned char buf[4]; apr_size_t len = 3; status = apr_file_read(file, buf, &len); if ((status != APR_SUCCESS) || (len < 3) || memcmp(buf, "\xEF\xBB\xBF", 3) != 0) { apr_off_t zero = 0; apr_file_seek(file, APR_SET, &zero); } }#endif new_cfg = apr_palloc(p, sizeof(*new_cfg)); new_cfg->param = file; new_cfg->name = apr_pstrdup(p, name); new_cfg->getch = (int (*)(void *)) cfg_getch; new_cfg->getstr = (void *(*)(void *, size_t, void *)) cfg_getstr; new_cfg->close = (int (*)(void *)) cfg_close; new_cfg->line_number = 0; *ret_cfg = new_cfg; return APR_SUCCESS;}/* Allocate a ap_configfile_t handle with user defined functions and params */AP_DECLARE(ap_configfile_t *) ap_pcfg_open_custom(apr_pool_t *p, const char *descr, void *param, int(*getch)(void *param), void *(*getstr) (void *buf, size_t bufsiz, void *param), int(*close_func)(void *param)){ ap_configfile_t *new_cfg = apr_palloc(p, sizeof(*new_cfg));#ifdef DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "Opening config handler %s", descr);#endif new_cfg->param = param; new_cfg->name = descr; new_cfg->getch = getch; new_cfg->getstr = getstr; new_cfg->close = close_func; new_cfg->line_number = 0; return new_cfg;} /* Read one character from a configfile_t */AP_DECLARE(int) ap_cfg_getc(ap_configfile_t *cfp){ register int ch = cfp->getch(cfp->param); if (ch == LF) ++cfp->line_number; return ch;} /* Read one line from open ap_configfile_t, strip LF, increase line number *//* If custom handler does not define a getstr() function, read char by char */AP_DECLARE(int) ap_cfg_getline(char *buf, size_t bufsize, ap_configfile_t *cfp){ /* If a "get string" function is defined, use it */ if (cfp->getstr != NULL) { char *src, *dst; char *cp; char *cbuf = buf; size_t cbufsize = bufsize; while (1) { ++cfp->line_number; if (cfp->getstr(cbuf, cbufsize, cfp->param) == NULL) return 1; /* * check for line continuation, * i.e. match [^\\]\\[\r]\n only */ cp = cbuf; while (cp < cbuf+cbufsize && *cp != '\0') cp++; if (cp > cbuf && cp[-1] == LF) { cp--; if (cp > cbuf && cp[-1] == CR) cp--; if (cp > cbuf && cp[-1] == '\\') { cp--; if (!(cp > cbuf && cp[-1] == '\\')) { /* * line continuation requested - * then remove backslash and continue */ cbufsize -= (cp-cbuf); cbuf = cp; continue; } else { /* * no real continuation because escaped - * then just remove escape character */ for ( ; cp < cbuf+cbufsize && *cp != '\0'; cp++) cp[0] = cp[1]; } } } break; } /* * Leading and trailing white space is eliminated completely */ src = buf; while (apr_isspace(*src)) ++src; /* blast trailing whitespace */ dst = &src[strlen(src)]; while (--dst >= src && apr_isspace(*dst)) *dst = '\0'; /* Zap leading whitespace by shifting */ if (src != buf) for (dst = buf; (*dst++ = *src++) != '\0'; ) ;#ifdef DEBUG_CFG_LINES ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "Read config: %s", buf);#endif return 0; } else { /* No "get string" function defined; read character by character */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -