⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_dontdothat.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * mod_dontdothat.c: an Apache filter that allows you to return arbitrary *                   errors for various types of Subversion requests. * * ==================================================================== * Copyright (c) 2006 CollabNet.  All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution.  The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals.  For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <httpd.h>#include <http_config.h>#include <http_request.h>#include <http_log.h>#include <util_filter.h>#include <ap_config.h>#include <apr_strings.h>#include <expat.h>#include "mod_dav_svn.h"#include "svn_string.h"#include "svn_config.h"module AP_MODULE_DECLARE_DATA dontdothat_module;typedef struct {  const char *config_file;  const char *base_path;} dontdothat_config_rec;static void *create_dontdothat_dir_config(apr_pool_t *pool, char *dir){  dontdothat_config_rec *cfg = apr_pcalloc(pool, sizeof(*cfg));  cfg->base_path = dir;  return cfg;}static const command_rec dontdothat_cmds[] ={  AP_INIT_TAKE1("DontDoThatConfigFile", ap_set_file_slot,                (void *) APR_OFFSETOF(dontdothat_config_rec, config_file),                OR_ALL,                "Text file containing actions to take for specific requests"),  { NULL }};typedef enum {  STATE_BEGINNING,  STATE_IN_UPDATE,  STATE_IN_SRC_PATH,  STATE_IN_DST_PATH,  STATE_IN_RECURSIVE} parse_state_t;typedef struct {  /* Set to TRUE when we determine that the request is safe and should be   * allowed to continue. */  svn_boolean_t let_it_go;  /* Set to TRUE when we determine that the request is unsafe and should be   * stopped in its tracks. */  svn_boolean_t no_soup_for_you;  XML_Parser xmlp;  /* The current location in the REPORT body. */  parse_state_t state;  /* A buffer to hold CDATA we encounter. */  svn_stringbuf_t *buffer;  dontdothat_config_rec *cfg;  /* An array of wildcards that are special cased to be allowed. */  apr_array_header_t *allow_recursive_ops;  /* An array of wildcards where recursive operations are not allowed. */  apr_array_header_t *no_recursive_ops;  /* TRUE if a path has failed a test already. */  svn_boolean_t path_failed;  /* An error for when we're using this as a baton while parsing config   * files. */  svn_error_t *err;  /* The current request. */  request_rec *r;} dontdothat_filter_ctx;/* Return TRUE if wildcard WC matches path P, FALSE otherwise. */static svn_boolean_tmatches(const char *wc, const char *p){  for (;;)    {      switch (*wc)        {          case '*':            if (wc[1] != '/' && wc[1] != '\0')              abort(); /* This was checked for during parsing of the config. */            /* It's a wild card, so eat up until the next / in p. */            while (*p && p[1] != '/')              ++p;            /* If we ran out of p and we're out of wc then it matched. */            if (! *p)              {                if (wc[1] == '\0')                  return TRUE;                else                  return FALSE;              }            break;          case '\0':            if (*p != '\0')              /* This means we hit the end of wc without running out of p. */              return FALSE;            else              /* Or they were exactly the same length, so it's not lower. */              return TRUE;          default:            if (*wc != *p)              return FALSE; /* If we don't match, then move on to the next                             * case. */            else              break;        }      ++wc;      ++p;      if (! *p && *wc)        return FALSE;    }}static svn_boolean_tis_this_legal(dontdothat_filter_ctx *ctx, const char *uri){  const char *relative_path;  const char *cleaned_uri;  const char *repos_name;  int trailing_slash;  dav_error *derr;  /* Ok, so we need to skip past the scheme, host, etc. */  uri = ap_strstr_c(uri, "://");  if (uri)    uri = ap_strchr_c(uri + 3, '/');  if (uri)    {      const char *repos_path;      derr = dav_svn_split_uri(ctx->r,                               uri,                               ctx->cfg->base_path,                               &cleaned_uri,                               &trailing_slash,                               &repos_name,                               &relative_path,                               &repos_path);      if (! derr)        {          int idx;          if (! repos_path)            repos_path = "";          repos_path = apr_psprintf(ctx->r->pool, "/%s", repos_path);          /* First check the special cases that are always legal... */          for (idx = 0; idx < ctx->allow_recursive_ops->nelts; ++idx)            {              const char *wc = APR_ARRAY_IDX(ctx->allow_recursive_ops,                                             idx,                                             const char *);              if (matches(wc, repos_path))                {                  ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->r,                                "mod_dontdothat: rule %s allows %s",                                wc, repos_path);                  return TRUE;                }            }          /* Then look for stuff we explicitly don't allow. */          for (idx = 0; idx < ctx->no_recursive_ops->nelts; ++idx)            {              const char *wc = APR_ARRAY_IDX(ctx->no_recursive_ops,                                             idx,                                             const char *);              if (matches(wc, repos_path))                {                  ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->r,                                "mod_dontdothat: rule %s forbids %s",                                wc, repos_path);                  return FALSE;                }            }        }    }  return TRUE;}static apr_status_tdontdothat_filter(ap_filter_t *f,                  apr_bucket_brigade *bb,                  ap_input_mode_t mode,                  apr_read_type_e block,                  apr_off_t readbytes){  dontdothat_filter_ctx *ctx = f->ctx;  apr_status_t rv;  apr_bucket *e;  if (mode != AP_MODE_READBYTES)    return ap_get_brigade(f->next, bb, mode, block, readbytes);  rv = ap_get_brigade(f->next, bb, mode, block, readbytes);  if (rv)    return rv;  for (e = APR_BRIGADE_FIRST(bb);       e != APR_BRIGADE_SENTINEL(bb);       e = APR_BUCKET_NEXT(e))    {      svn_boolean_t last = APR_BUCKET_IS_EOS(e);      const char *str;      apr_size_t len;      if (last)        {          str = "";          len = 0;        }      else        {          rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);          if (rv)            return rv;        }      if (! XML_Parse(ctx->xmlp, str, len, last))        {          /* let_it_go so we clean up our parser, no_soup_for_you so that we           * bail out before bothering to parse this stuff a second time. */          ctx->let_it_go = TRUE;          ctx->no_soup_for_you = TRUE;        }      /* If we found something that isn't allowed, set the correct status       * and return an error so it'll bail out before it gets anywhere it       * can do real damage. */      if (ctx->no_soup_for_you)        {          /* XXX maybe set up the SVN-ACTION env var so that it'll show up           *     in the Subversion operational logs? */          ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r,                        "mod_dontdothat: client broke the rules, "                        "returning error");          f->r->status = 403;          f->r->status_line = "403 Forbidden, No Soup For You!";          return APR_EGENERAL;        }      else if (ctx->let_it_go || last)        {          ap_remove_input_filter(f);          ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r,                        "mod_dontdothat: letting request go through");          return rv;        }    }  return rv;}static voidcdata(void *baton, const char *data, int len){  dontdothat_filter_ctx *ctx = baton;  if (ctx->no_soup_for_you || ctx->let_it_go)    return;  switch (ctx->state)    {      case STATE_IN_SRC_PATH:        /* FALLTHROUGH */      case STATE_IN_DST_PATH:        /* FALLTHROUGH */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -