apache/apache.patch.davquo

Mon, 28 Jan 2013 17:37:18 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 28 Jan 2013 17:37:18 +0100
changeset 758
a2c6460cfb16
permissions
-rw-r--r--

Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.

     1 Index: modules/dav/fs/mod_dav_fs.c
     2 diff -Nau modules/dav/fs/mod_dav_fs.c.orig modules/dav/fs/mod_dav_fs.c
     3 --- modules/dav/fs/mod_dav_fs.c.orig	2006-07-12 05:38:44.000000000 +0200
     4 +++ modules/dav/fs/mod_dav_fs.c	2012-09-17 14:16:06.937987679 +0200
     5 @@ -15,6 +15,7 @@
     6   */
     8  #include "httpd.h"
     9 +#include "http_log.h"
    10  #include "http_config.h"
    11  #include "apr_strings.h"
    13 @@ -24,9 +25,19 @@
    14  /* per-server configuration */
    15  typedef struct {
    16      const char *lockdb_path;
    17 +    const char *diskusagedb_path;
    19  } dav_fs_server_conf;
    21 +/* per-dir configuration */
    22 +typedef struct {
    23 +    apr_size_t quota;
    24 +    const char *area_path;
    25 +    int hiddenfiles;
    26 +    ap_regex_t *mask;
    27 +
    28 +} dav_fs_dir_conf;
    29 +
    30  extern module AP_MODULE_DECLARE_DATA dav_fs_module;
    32  const char *dav_get_lockdb_path(const request_rec *r)
    33 @@ -37,9 +48,20 @@
    34      return conf->lockdb_path;
    35  }
    37 +const char *dav_get_diskusagedb_path(const request_rec *r)
    38 +{
    39 +    dav_fs_server_conf *conf;
    40 +
    41 +    conf = ap_get_module_config(r->server->module_config, &dav_fs_module);
    42 +    return conf->diskusagedb_path;
    43 +}
    44 +
    45  static void *dav_fs_create_server_config(apr_pool_t *p, server_rec *s)
    46  {
    47 -    return apr_pcalloc(p, sizeof(dav_fs_server_conf));
    48 +    dav_fs_server_conf *conf;
    49 +    conf = apr_pcalloc(p, sizeof(dav_fs_server_conf));
    50 +    conf->diskusagedb_path = NULL;
    51 +    return conf;
    52  }
    54  static void *dav_fs_merge_server_config(apr_pool_t *p,
    55 @@ -53,6 +75,35 @@
    57      newconf->lockdb_path =
    58          child->lockdb_path ? child->lockdb_path : parent->lockdb_path;
    59 +    newconf->diskusagedb_path =
    60 +        child->diskusagedb_path ? child->diskusagedb_path : parent->diskusagedb_path;
    61 +
    62 +    return newconf;
    63 +}
    64 +
    65 +static void *dav_fs_create_dir_config(apr_pool_t *p, char *dir)
    66 +{
    67 +    dav_fs_dir_conf *conf=apr_pcalloc(p, sizeof(dav_fs_dir_conf));
    68 +    conf->area_path = NULL;
    69 +    conf->mask = NULL;
    70 +    conf->quota = 0;
    71 +    conf->hiddenfiles = -1;
    72 +    return conf;
    73 +}
    74 +
    75 +static void *dav_fs_merge_dir_config(apr_pool_t *p,
    76 +                                        void *base, void *overrides)
    77 +{
    78 +    dav_fs_dir_conf *parent = base;
    79 +    dav_fs_dir_conf *child = overrides;
    80 +    dav_fs_dir_conf *newconf;
    81 +
    82 +    newconf = apr_pcalloc(p, sizeof(*newconf));
    83 +
    84 +    newconf->quota = child->quota ? child->quota : parent->quota;
    85 +    newconf->area_path = child->area_path ? child->area_path : parent->area_path;
    86 +    newconf->hiddenfiles = child->hiddenfiles!=-1 ? child->hiddenfiles : parent->hiddenfiles;
    87 +    newconf->mask = child->mask ? child->mask : parent->mask;
    89      return newconf;
    90  }
    91 @@ -76,12 +127,83 @@
    92      return NULL;
    93  }
    95 +/*
    96 + * Command handler for the DAVLockDB directive, which is TAKE1
    97 + */
    98 +static const char *dav_fs_cmd_diskusagedb(cmd_parms *cmd, void *config,
    99 +                                        const char *arg1)
   100 +{
   101 +    dav_fs_server_conf *conf;
   102 +    conf = ap_get_module_config(cmd->server->module_config,
   103 +                                &dav_fs_module);
   104 +    conf->diskusagedb_path = ap_server_root_relative(cmd->pool, arg1);
   105 +
   106 +    if (!conf->diskusagedb_path) {
   107 +        return apr_pstrcat(cmd->pool, "Invalid DAVDiskUsageDB path ",
   108 +                           arg1, NULL);
   109 +    }
   110 +
   111 +    return NULL;
   112 +}
   113 +
   114 +/*
   115 + * Command handler for the DAVFSQuota directive, which is TAKE1
   116 + */
   117 +
   118 +static const char *dav_fs_cmd_davareasize( cmd_parms *cmd , void *config , const char *arg1 ) {
   119 +
   120 +    dav_fs_dir_conf *conf = ( dav_fs_dir_conf * )config;
   121 +
   122 +    conf->quota = (apr_size_t)atoi( arg1 );
   123 +    if ( conf->quota < 0 )
   124 +        return "DAVFSQuota requires a nonnegative integer.";
   125 +
   126 +    conf->area_path = cmd->path;
   127 +    return NULL;
   128 +
   129 +}
   130 +
   131 +static const char *dav_fs_cmd_hidefiles( cmd_parms *cmd , void *config , const char *type , const char *arg1 ) {
   132 +
   133 +    dav_fs_dir_conf *conf = ( dav_fs_dir_conf * )config;
   134 +
   135 +//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"arg1 %s, type %s",arg1, type);
   136 +
   137 +    if (!strcasecmp(type, "None"))
   138 +        conf->hiddenfiles = DAV_FS_HIDE_NONE;
   139 +    else if (!strcasecmp(type, "Hidden"))
   140 +        conf->hiddenfiles = DAV_FS_HIDE_HIDDEN;
   141 +    else if (!strcasecmp(type, "Deny"))
   142 +        conf->hiddenfiles = DAV_FS_HIDE_DENY;
   143 +    else if (!strcasecmp(type, "Htaccess"))
   144 +        conf->hiddenfiles = DAV_FS_HIDE_HTACCESS;
   145 +    else if (!strcasecmp(type, "Mask")) {
   146 +        conf->hiddenfiles = DAV_FS_HIDE_MASK;
   147 +	conf->mask = ap_pregcomp(cmd->pool, arg1, AP_REG_EXTENDED|AP_REG_ICASE);
   148 +        if (!conf->mask) {
   149 +            return apr_psprintf(cmd->pool, "Regex '%s' in DAVFSHideFiles Mask could not be compiled", arg1);
   150 +        }
   151 +    } else {
   152 +        return "DAVFSHideFiles must be one of: "
   153 +            "None | Hidden | Deny | Htaccess | Mask <regexp>";
   154 +    }
   155 +    return NULL;
   156 +}
   157 +
   158  static const command_rec dav_fs_cmds[] =
   159  {
   160      /* per server */
   161      AP_INIT_TAKE1("DAVLockDB", dav_fs_cmd_davlockdb, NULL, RSRC_CONF,
   162                    "specify a lock database"),
   163 -
   164 +    AP_INIT_TAKE1("DAVDiskUsageDB", dav_fs_cmd_diskusagedb, NULL, RSRC_CONF,
   165 +                  "specify a disk usage database"),
   166 +    /* per directory/location */
   167 +    AP_INIT_TAKE1("DAVFSQuota", dav_fs_cmd_davareasize, NULL,
   168 +                  OR_LIMIT|ACCESS_CONF,
   169 +                  "max size of user storage area, per KByte"),
   170 +    AP_INIT_TAKE12("DAVFSHideFiles", dav_fs_cmd_hidefiles, NULL,
   171 +                  OR_LIMIT|ACCESS_CONF,
   172 +                  "how files need for hide in collection: None | Hidden | Deny | Htaccess | Mask <regexp>"),
   173      { NULL }
   174  };
   176 @@ -99,10 +221,38 @@
   177  module AP_MODULE_DECLARE_DATA dav_fs_module =
   178  {
   179      STANDARD20_MODULE_STUFF,
   180 -    NULL,                        /* dir config creater */
   181 -    NULL,                        /* dir merger --- default is to override */
   182 +    dav_fs_create_dir_config,    /* dir config creater */
   183 +    dav_fs_merge_dir_config,     /* dir merger --- default is to override */
   184      dav_fs_create_server_config, /* server config */
   185      dav_fs_merge_server_config,  /* merge server config */
   186      dav_fs_cmds,                 /* command table */
   187      register_hooks,              /* register hooks */
   188  };
   189 +
   190 +const apr_size_t dav_fs_get_quota( request_rec *r ) {
   191 +
   192 +    dav_fs_dir_conf *conf = ap_get_module_config( r->per_dir_config , &dav_fs_module );
   193 +    return  conf->quota;
   194 +
   195 +}
   196 +
   197 +const char *dav_fs_get_dir( request_rec *r ) {
   198 +
   199 +    dav_fs_dir_conf *conf = ap_get_module_config( r->per_dir_config , &dav_fs_module );
   200 +    return  conf->area_path;
   201 +
   202 +}
   203 +
   204 +const int dav_fs_get_hidefiles( request_rec *r ) {
   205 +
   206 +    dav_fs_dir_conf *conf = ap_get_module_config( r->per_dir_config , &dav_fs_module );
   207 +    return  conf->hiddenfiles;
   208 +
   209 +}
   210 +
   211 +const ap_regex_t *dav_fs_get_mask( request_rec *r ) {
   212 +
   213 +    dav_fs_dir_conf *conf = ap_get_module_config( r->per_dir_config , &dav_fs_module );
   214 +    return  conf->mask;
   215 +
   216 +}
   217 Index: modules/dav/fs/quota.h
   218 diff -Nau modules/dav/fs/quota.h.orig modules/dav/fs/quota.h
   219 --- modules/dav/fs/quota.h.orig	1970-01-01 01:00:00.000000000 +0100
   220 +++ modules/dav/fs/quota.h	2012-09-17 14:16:06.938238230 +0200
   221 @@ -0,0 +1,13 @@
   222 +/**
   223 +    disk quota check modules for WebDAV service
   224 +                        author: satake@goodcrew.ne.jp, changed by bjaka.max@gmail.com
   225 +*/
   226 +
   227 +/** set your storage cluster size */
   228 +#ifndef     DAV_CLUSTER_SIZE
   229 +    #define     DAV_CLUSTER_SIZE    4096
   230 +#endif
   231 +
   232 +static apr_size_t dav_qchk_du(const char *dirname, apr_pool_t *pool);
   233 +static apr_size_t dav_cached_du(char *dirname, const request_rec *r);
   234 +static apr_status_t dav_change_cached_du(const char *dirname, const request_rec *r, int add_size, apr_size_t delta);
   235 Index: modules/dav/fs/repos.c
   236 diff -Nau modules/dav/fs/repos.c.orig modules/dav/fs/repos.c
   237 --- modules/dav/fs/repos.c.orig	2011-09-08 17:59:38.000000000 +0200
   238 +++ modules/dav/fs/repos.c	2012-09-17 14:18:07.509160501 +0200
   239 @@ -27,6 +27,8 @@
   240  #include <stdio.h>              /* for sprintf() */
   241  #endif
   243 +#include "util_filter.h"
   244 +#include "apr_sdbm.h"
   245  #include "httpd.h"
   246  #include "http_log.h"
   247  #include "http_protocol.h"      /* for ap_set_* (in dav_fs_set_headers) */
   248 @@ -34,6 +36,7 @@
   250  #include "mod_dav.h"
   251  #include "repos.h"
   252 +#include "quota.h"
   255  /* to assist in debugging mod_dav's GET handling */
   256 @@ -46,6 +49,10 @@
   257      apr_pool_t *pool;        /* memory storage pool associated with request */
   258      const char *pathname;   /* full pathname to resource */
   259      apr_finfo_t finfo;       /* filesystem info */
   260 +    request_rec *r;         /* request of this resource*/
   261 +    apr_size_t quota;           /* config data for quota check */
   262 +    const char *area_path;
   263 +    int hiddenfiles;
   264  };
   266  /* private context for doing a filesystem walk */
   267 @@ -137,7 +144,12 @@
   268  /*
   269  ** The single property that we define (in the DAV_FS_URI_MYPROPS namespace)
   270  */
   271 -#define DAV_PROPID_FS_executable        1
   272 +#define DAV_PROPID_FS_executable		1
   273 +/*
   274 +**Quota property in DAV:namespace
   275 +*/
   276 +#define DAV_PROPID_quota_available_bytes	2
   277 +#define DAV_PROPID_quota_used_bytes		3
   279  static const dav_liveprop_spec dav_fs_props[] =
   280  {
   281 @@ -166,8 +178,20 @@
   282          DAV_PROPID_getlastmodified,
   283          0
   284      },
   285 -
   286 +    {
   287 +        DAV_FS_URI_DAV,
   288 +        "quota-available-bytes",
   289 +        DAV_PROPID_quota_available_bytes,
   290 +        0
   291 +    },
   292 +    {
   293 +        DAV_FS_URI_DAV,
   294 +        "quota-used-bytes",
   295 +        DAV_PROPID_quota_used_bytes,
   296 +        0
   297 +    },
   298      /* our custom properties */
   299 +
   300      {
   301          DAV_FS_URI_MYPROPS,
   302          "executable",
   303 @@ -191,6 +215,9 @@
   304      apr_pool_t *p;
   305      apr_file_t *f;
   306      const char *pathname;       /* we may need to remove it at close time */
   307 +    apr_size_t quota;           /* config data for quota check */
   308 +    const char *area_path;
   309 +    request_rec *r;         /* request of this resource*/
   310  };
   312  /* returns an appropriate HTTP status code given an APR status code for a
   313 @@ -641,6 +668,8 @@
   314      dav_resource *resource;
   315      char *s;
   316      char *filename;
   317 +    apr_size_t nowsize, putsize;
   318 +    const char *conlen;
   319      apr_size_t len;
   321      /* ### optimize this into a single allocation! */
   322 @@ -652,6 +681,37 @@
   323      /* ### this should go away */
   324      ctx->pool = r->pool;
   326 +    ctx->r = r;
   327 +    ctx->quota = dav_fs_get_quota(r);
   328 +    ctx->area_path = dav_fs_get_dir(r);
   329 +
   330 +    ctx->hiddenfiles = dav_fs_get_hidefiles(r);
   331 +
   332 +//    ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"Pathname is %s, quota is %d",ctx->area_path,ctx->quota);
   333 +    /** Check quota limit*/
   334 +    if (ctx->quota && r->method_number==M_PUT) {
   335 +
   336 +	/** get now user used size */
   337 +	nowsize = dav_cached_du(ctx->area_path, r);
   338 +
   339 +	/** get put size */
   340 +	conlen = NULL;
   341 +	putsize = 0;
   342 +	if ( r->headers_in!=NULL ) {
   343 +		conlen = apr_table_get( r->headers_in , "content-length" );
   344 +	}
   345 +	if ( conlen!=NULL ) {
   346 +		putsize = ((atoi(conlen)+DAV_CLUSTER_SIZE-1)/DAV_CLUSTER_SIZE)*(DAV_CLUSTER_SIZE/1024);
   347 +	}
   348 +
   349 +	/** check size */
   350 +//	ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"Pathname is %s, directory size is %d, quota is %d",ctx->area_path, nowsize+putsize, ctx->quota);
   351 +	if ( nowsize+putsize>=ctx->quota ) {
   352 +		return dav_new_error(r->pool, HTTP_INSUFFICIENT_STORAGE, 0,
   353 +			apr_psprintf(r->pool,"WebDAV-Quota: Directory `%s' size %dKB+%dKB(%s) is over %dKB!",ctx->area_path, nowsize,putsize,conlen, ctx->quota));
   354 +	}
   355 +    }
   356 +
   357      /* Preserve case on OSes which fold canonical filenames */
   358  #if 0
   359      /* ### not available in Apache 2.0 yet */
   360 @@ -865,6 +925,12 @@
   362      ds->p = p;
   363      ds->pathname = resource->info->pathname;
   364 +
   365 +    ds->quota=resource->info->quota;
   366 +    ds->area_path=resource->info->area_path;
   367 +
   368 +    ds->r = resource->info->r;
   369 +
   370      rv = apr_file_open(&ds->f, ds->pathname, flags, APR_OS_DEFAULT, ds->p);
   371      if (rv != APR_SUCCESS) {
   372          return dav_new_error(p, MAP_IO2HTTP(rv), 0,
   373 @@ -889,6 +955,23 @@
   374                                   "back) the resource "
   375                                   "when it was being closed.");
   376          }
   377 +    } else {
   378 +
   379 +	if(stream->area_path && stream->r->method_number==M_PUT) {
   380 +	    const char *conlen = NULL;
   381 +	    apr_size_t putsize = 0;
   382 +	    /** get put size */
   383 +
   384 +	    if ( stream->r->headers_in!=NULL ) {
   385 +		conlen = apr_table_get( stream->r->headers_in , "content-length" );
   386 +	    }
   387 +	    if ( conlen!=NULL ) {
   388 +		putsize = ((atoi(conlen)+DAV_CLUSTER_SIZE-1)/DAV_CLUSTER_SIZE)*(DAV_CLUSTER_SIZE/1024);
   389 +	    }
   390 +
   391 +	    dav_change_cached_du(stream->area_path, stream->r, 1, putsize);
   392 +	}
   393 +
   394      }
   396      return NULL;
   397 @@ -926,8 +1009,145 @@
   398      }
   399      return NULL;
   400  }
   401 +/**
   402 +    get (dirname) total size ( per 512byte )
   403 +    @param  dirname directory name
   404 +    @return block size
   405 +*/
   406 +static apr_size_t get_dir_size(const char *dirname, apr_pool_t *pool) {
   407 +
   408 +    DIR *dir;
   409 +    struct dirent *ent;
   410 +    struct stat status;
   411 +    char *buffer;
   412 +    apr_size_t size = 0;
   413 +
   414 +    dir = opendir(dirname);
   415 +    if ( dir==NULL ) {
   416 +        return  0;
   417 +    }
   418 +
   419 +    while ( (ent = readdir(dir))!=NULL ) {
   420 +        if ( (!strcmp(ent->d_name, ".")) || (!strcmp(ent->d_name, "..")) ) {
   421 +            continue;
   422 +        }
   423 +
   424 +        apr_filepath_merge(&buffer, dirname, ent->d_name, 0, pool);
   425 +
   426 +        if ( !lstat(buffer, &status) ) {
   427 +            size += status.st_blocks;
   428 +            if ( status.st_mode & S_IFDIR ) {
   429 +                size += get_dir_size(buffer, pool);
   430 +            }
   431 +        }
   432 +    }
   433 +    closedir(dir);
   434 +    return  size;
   435 +}
   437 +/**
   438 +    return  directory total disk space.
   439 +    same as 'du -sk dirname' command.
   440 +    @param  dirname     directory
   441 +    @return     total space
   442 +*/
   443 +static apr_size_t dav_qchk_du(const char *dirname, apr_pool_t *pool) {
   444 +    struct stat     status;
   446 +    if ( lstat(dirname, &status) ) {
   447 +        return  0;
   448 +    }
   449 +    return (status.st_blocks+((status.st_mode & S_IFDIR)?get_dir_size(dirname, pool):0))/2;
   450 +}
   451 +
   452 +static apr_sdbm_datum_t dav_cached_du_prepare_key(const char *dirname, apr_pool_t *pool) {
   453 +    apr_sdbm_datum_t key;
   454 +    key.dsize = strlen(dirname)+1;
   455 +    key.dptr = apr_palloc(pool, key.dsize);
   456 +    memcpy(key.dptr, dirname, key.dsize);
   457 +    if (key.dptr[key.dsize - 2] == '/')
   458 +        key.dptr[--key.dsize - 1] = '\0';
   459 +    return key;
   460 +}
   461 +
   462 +static apr_size_t dav_cached_du(char *dirname, const request_rec *r) {
   463 +    const char *pathname = dav_get_diskusagedb_path(r);
   464 +    apr_status_t status;
   465 +    apr_sdbm_t *db;
   466 +    apr_sdbm_datum_t val = { 0 };
   467 +    apr_size_t size;
   468 +    apr_sdbm_datum_t key;
   469 +    if (dirname[strlen(dirname)-1] == '/')
   470 +        dirname[strlen(dirname)-1] = '\0';
   471 +
   472 +    if(!pathname)
   473 +	return dav_qchk_du(dirname, r->pool);
   474 +
   475 +    key=dav_cached_du_prepare_key(dirname, r->pool);
   476 +
   477 +    if ((status = apr_sdbm_open(&db, pathname, APR_WRITE | APR_CREATE,
   478 +                               APR_OS_DEFAULT, r->pool))!= APR_SUCCESS) {
   479 +	ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"Error accessing to '%s' Disk Usage db file.", pathname);
   480 +	return dav_qchk_du(dirname, r->pool);
   481 +    }
   482 +
   483 +    apr_sdbm_fetch(db, &val, key);
   484 +    if(val.dptr) {
   485 +	size = atoi(val.dptr);
   486 +    } else {
   487 +	size=dav_qchk_du(dirname, r->pool);
   488 +	val.dptr = apr_psprintf(r->pool,"%" APR_OFF_T_FMT, size);
   489 +	val.dsize = strlen(val.dptr);
   490 +	apr_sdbm_store(db, key, val, APR_SDBM_REPLACE);
   491 +    }
   492 +
   493 +    apr_sdbm_close(db);
   494 +    return size;
   495 +}
   496 +
   497 +static apr_status_t dav_change_cached_du(const char *dirname, const request_rec *r, int add_size, apr_size_t delta) {
   498 +    const char *pathname = dav_get_diskusagedb_path(r);
   499 +    apr_status_t status;
   500 +    apr_sdbm_t *db;
   501 +    apr_sdbm_datum_t val = { 0 };
   502 +    apr_size_t size;
   503 +    apr_sdbm_datum_t key;
   504 +
   505 +    if(!pathname)
   506 +	return APR_SUCCESS;
   507 +
   508 +    key=dav_cached_du_prepare_key(dirname, r->pool);
   509 +
   510 +    if ((status = apr_sdbm_open(&db, pathname, APR_WRITE | APR_CREATE | APR_SHARELOCK,
   511 +                               APR_OS_DEFAULT, r->pool))!= APR_SUCCESS) {
   512 +	return status;
   513 +    }
   514 +
   515 +    apr_sdbm_fetch(db, &val, key);
   516 +
   517 +    if(val.dptr) {
   518 +	apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE);
   519 +	apr_sdbm_fetch(db, &val, key);
   520 +	size = atoi(val.dptr);
   521 +	if(add_size) {
   522 +	    size += delta;
   523 +	} else {
   524 +	    size -= delta;
   525 +	}
   526 +	val.dptr = apr_psprintf(r->pool,"%" APR_OFF_T_FMT, size);
   527 +	val.dsize = strlen(val.dptr);
   528 +	apr_sdbm_store(db, key, val, APR_SDBM_REPLACE);
   529 +	apr_sdbm_unlock(db);
   530 +   } else {
   531 +	size=dav_qchk_du(dirname, r->pool);
   532 +	val.dptr = apr_psprintf(r->pool,"%" APR_OFF_T_FMT, size);
   533 +	val.dsize = strlen(val.dptr);
   534 +	apr_sdbm_store(db, key, val, APR_SDBM_REPLACE);
   535 +    }
   536 +
   537 +    apr_sdbm_close(db);
   538 +    return APR_SUCCESS;
   539 +}
   540  #if DEBUG_GET_HANDLER
   542  /* only define set_headers() and deliver() for debug purposes */
   543 @@ -1355,6 +1575,8 @@
   544                                            dav_response **response)
   545  {
   546      dav_resource_private *info = resource->info;
   547 +    struct stat status;
   548 +    apr_size_t putsize = 0;
   550      *response = NULL;
   552 @@ -1394,6 +1616,10 @@
   553      }
   555      /* not a collection; remove the file and its properties */
   556 +    if (info->area_path && !lstat(info->pathname, &status) ) {
   557 +	putsize = status.st_blocks/2;
   558 +    	dav_change_cached_du(info->area_path, info->r, 0, putsize);
   559 +    }
   560      if (apr_file_remove(info->pathname, info->pool) != APR_SUCCESS) {
   561          /* ### put a description in here */
   562          return dav_new_error(info->pool, HTTP_FORBIDDEN, 0, NULL);
   563 @@ -1418,7 +1644,12 @@
   564      int isdir = fsctx->res1.collection;
   565      apr_finfo_t dirent;
   566      apr_dir_t *dirp;
   567 +    char *dirname;
   568 +    const ap_regex_t *mask;
   570 +    if(fsctx->info1.hiddenfiles==DAV_FS_HIDE_MASK) {
   571 +	mask=dav_fs_get_mask(fsctx->info1.r);
   572 +    }
   573      /* ensure the context is prepared properly, then call the func */
   574      err = (*params->func)(&fsctx->wres,
   575                            isdir
   576 @@ -1455,13 +1686,16 @@
   577      fsctx->res2.collection = 0;
   579      /* open and scan the directory */
   580 +    dirname=apr_pstrdup(pool, fsctx->path1.buf);
   581      if ((apr_dir_open(&dirp, fsctx->path1.buf, pool)) != APR_SUCCESS) {
   582          /* ### need a better error */
   583          return dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
   584      }
   585 -    while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) {
   586 +    while ((apr_dir_read(&dirent, APR_FINFO_DIRENT | APR_FINFO_NORM, dirp)) == APR_SUCCESS) {
   587          apr_size_t len;
   588          apr_status_t status;
   589 +	apr_finfo_t finfo;
   590 +	apr_status_t rv;
   592          len = strlen(dirent.name);
   594 @@ -1479,6 +1713,37 @@
   595              if (!strcmp(dirent.name, DAV_FS_STATE_DIR)) {
   596                  continue;
   597              }
   598 +	    //ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"Hiddenfiles %i",fsctx->info1.hiddenfiles);
   599 +	    if(fsctx->info1.hiddenfiles && fsctx->info1.hiddenfiles!=-1) {
   600 +		if(fsctx->info1.hiddenfiles==DAV_FS_HIDE_HIDDEN) {
   601 +		    if(dirent.name[0]=='.') {
   602 +			continue;
   603 +		    }
   604 +		} else if(fsctx->info1.hiddenfiles==DAV_FS_HIDE_DENY) {
   605 +		    request_rec *rr;
   606 +		    const char *fullname = apr_pstrcat(pool, dirname, dirent.name, NULL);
   607 +		    if (!(rr = ap_sub_req_lookup_file(ap_os_escape_path(pool,fullname,1), fsctx->info1.r, NULL))) {
   608 +			//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"Path %s, filename %s, fullname %s, return false", dirname, dirent.name, fullname);
   609 +			continue;
   610 +		    }
   611 +		    if (rr->status >= 400) {
   612 +			//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"Path %s, filename %s, fullname(escaped) %s(%s), status %i", dirname, dirent.name, fullname, ap_os_escape_path(pool,fullname,1), rr->status);
   613 +			ap_destroy_sub_req(rr);
   614 +			continue;
   615 +		    }
   616 +		    //ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"dirname %s, subrequest filename %s",dirname, rr->filename);
   617 +		    ap_destroy_sub_req(rr);
   618 +		} else if(fsctx->info1.hiddenfiles==DAV_FS_HIDE_HTACCESS) {
   619 +		    if(!strcmp(dirent.name, ".htaccess")) {
   620 +			continue;
   621 +		    }
   622 +		} else if(fsctx->info1.hiddenfiles==DAV_FS_HIDE_MASK) {
   623 +		    if(!ap_regexec(mask, dirent.name, 0, NULL, 0)) {
   624 +			//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"hide %s",dirent.name);
   625 +			continue;
   626 +		    }
   627 +		}
   628 +	    }
   629          }
   630          /* skip the state dir unless a HIDDEN is performed */
   631          if (!(params->walk_type & DAV_WALKTYPE_HIDDEN)
   632 @@ -1489,14 +1754,8 @@
   633          /* append this file onto the path buffer (copy null term) */
   634          dav_buffer_place_mem(pool, &fsctx->path1, dirent.name, len + 1, 0);
   636 -        status = apr_stat(&fsctx->info1.finfo, fsctx->path1.buf,
   637 -                          DAV_FINFO_MASK, pool);
   638 -        if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
   639 -            /* woah! where'd it go? */
   640 -            /* ### should have a better error here */
   641 -            err = dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
   642 -            break;
   643 -        }
   644 +        //set the finfo for further process
   645 +        fsctx->info1.finfo=dirent;
   647          /* copy the file to the URI, too. NOTE: we will pad an extra byte
   648             for the trailing slash later. */
   649 @@ -1512,10 +1771,11 @@
   650          fsctx->info2.pathname = fsctx->path2.buf;
   652          /* set up the URI for the current resource */
   653 +        //ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"the_request: %s,hostname: %s,status_line: %s,method: %s,range: %s,content_type: %s,unparsed_uri: %s,uri: %s,filename: %s,canonical_filename: %s,path_info: %s,args: %s,uri: %s",fsctx->info1.r->the_request ,fsctx->info1.r->hostname ,fsctx->info1.r->status_line,fsctx->info1.r->method,fsctx->info1.r->range,fsctx->info1.r->content_type,fsctx->info1.r->unparsed_uri,fsctx->info1.r->uri,fsctx->info1.r->filename,fsctx->info1.r->canonical_filename,fsctx->info1.r->path_info,fsctx->info1.r->args,fsctx->uri_buf.buf);
   654          fsctx->res1.uri = fsctx->uri_buf.buf;
   656          /* ### for now, only process regular files (e.g. skip symlinks) */
   657 -        if (fsctx->info1.finfo.filetype == APR_REG) {
   658 +        if (dirent.filetype == APR_REG) {
   659              /* call the function for the specified dir + file */
   660              if ((err = (*params->func)(&fsctx->wres,
   661                                         DAV_CALLTYPE_MEMBER)) != NULL) {
   662 @@ -1523,7 +1783,7 @@
   663                  break;
   664              }
   665          }
   666 -        else if (fsctx->info1.finfo.filetype == APR_DIR) {
   667 +        else if (dirent.filetype == APR_DIR) {
   668              apr_size_t save_path_len = fsctx->path1.cur_len;
   669              apr_size_t save_uri_len = fsctx->uri_buf.cur_len;
   670              apr_size_t save_path2_len = fsctx->path2.cur_len;
   671 @@ -1690,6 +1950,7 @@
   672      dav_fs_walker_context fsctx = { 0 };
   673      dav_error *err;
   674      dav_fs_copymove_walk_ctx cm_ctx = { 0 };
   675 +    const char *uri,*request=params->root->info->r->the_request;
   677  #if DAV_DEBUG
   678      if ((params->walk_type & DAV_WALKTYPE_LOCKNULL) != 0
   679 @@ -1743,7 +2004,11 @@
   680      }
   682      /* prep the URI buffer */
   683 -    dav_buffer_init(params->pool, &fsctx.uri_buf, params->root->uri);
   684 +
   685 +    uri = ap_getword(params->pool, &request, ' '); //get method
   686 +    uri = ap_getword(params->pool, &request, ' '); //get uri
   687 +    ap_unescape_url(uri);
   688 +    dav_buffer_init(params->pool, &fsctx.uri_buf, uri);
   690      /* if we have a directory, then ensure the URI has a trailing "/" */
   691      if (fsctx.res1.collection
   692 @@ -1844,8 +2109,11 @@
   693      ** client cannot store dead values -- we deny that thru the is_writable
   694      ** hook function.
   695      */
   696 -    if (!resource->exists)
   697 +    if (!resource->exists) {
   698 +//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"resource not exist");
   699 +
   700          return DAV_PROP_INSERT_NOTDEF;
   701 +}
   703      switch (propid) {
   704      case DAV_PROPID_creationdate:
   705 @@ -1896,15 +2164,29 @@
   706              value = "F";
   707          break;
   709 +    case DAV_PROPID_quota_available_bytes:
   710 +	/* Property defined only for collection with quota */
   711 +        if (!resource->info->quota || !resource->collection)
   712 +            return DAV_PROP_INSERT_NOTDEF;
   713 +        value = apr_psprintf(p, "%d", (resource->info->quota-dav_cached_du(resource->info->area_path, resource->info->r))*1024);
   714 +	break;
   715 +
   716 +    case DAV_PROPID_quota_used_bytes:
   717 +	/* Property defined only for collection with quota */
   718 +        if (!resource->info->quota || !resource->collection)
   719 +            return DAV_PROP_INSERT_NOTDEF;
   720 +	value = apr_psprintf(p, "%d", dav_cached_du(resource->info->area_path, resource->info->r)*1024);
   721 +	break;
   722 +
   723      default:
   724          /* ### what the heck was this property? */
   725          return DAV_PROP_INSERT_NOTDEF;
   726      }
   728      /* assert: value != NULL */
   729 -
   730      /* get the information and global NS index for the property */
   731      global_ns = dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);
   732 +//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"ns=%d name=%s value=%s",global_ns, info->name, value);
   734      /* assert: info != NULL && info->name != NULL */
   736 @@ -2138,7 +2420,7 @@
   737          */
   738          return;
   739      }
   740 -
   741 +//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"Try show all props");
   742      (void) dav_fs_insert_prop(resource, DAV_PROPID_creationdate,
   743                                what, phdr);
   744      (void) dav_fs_insert_prop(resource, DAV_PROPID_getcontentlength,
   745 @@ -2148,6 +2430,11 @@
   746      (void) dav_fs_insert_prop(resource, DAV_PROPID_getetag,
   747                                what, phdr);
   749 +    (void) dav_fs_insert_prop(resource, DAV_PROPID_quota_available_bytes,
   750 +                              what, phdr);
   751 +    (void) dav_fs_insert_prop(resource, DAV_PROPID_quota_used_bytes,
   752 +                              what, phdr);
   753 +
   754  #ifdef DAV_FS_HAS_EXECUTABLE
   755      /* Only insert this property if it is defined for this platform. */
   756      (void) dav_fs_insert_prop(resource, DAV_PROPID_FS_executable,
   757 Index: modules/dav/fs/repos.h
   758 diff -Nau modules/dav/fs/repos.h.orig modules/dav/fs/repos.h
   759 --- modules/dav/fs/repos.h.orig	2006-07-12 05:38:44.000000000 +0200
   760 +++ modules/dav/fs/repos.h	2012-09-17 14:16:06.941582156 +0200
   761 @@ -30,6 +30,12 @@
   762  #define DAV_FS_STATE_FILE_FOR_DIR       ".state_for_dir"
   763  #define DAV_FS_LOCK_NULL_FILE           ".locknull"
   765 +#define DAV_FS_HIDE_NONE		0
   766 +#define DAV_FS_HIDE_HIDDEN		1
   767 +#define DAV_FS_HIDE_DENY		2
   768 +#define DAV_FS_HIDE_HTACCESS		3
   769 +#define DAV_FS_HIDE_MASK		4
   770 +
   772  /* ensure that our state subdirectory is present */
   773  void dav_fs_ensure_state_dir(apr_pool_t *p, const char *dirname);
   774 @@ -67,6 +73,8 @@
   775  /* where is the lock database located? */
   776  const char *dav_get_lockdb_path(const request_rec *r);
   778 +const char *dav_get_diskusagedb_path(const request_rec *r);
   779 +
   780  const dav_hooks_locks *dav_fs_get_lock_hooks(request_rec *r);
   781  const dav_hooks_propdb *dav_fs_get_propdb_hooks(request_rec *r);
   783 @@ -79,6 +87,11 @@
   785  void dav_fs_register(apr_pool_t *p);
   787 +const apr_size_t dav_fs_get_quota( request_rec *r );
   788 +const char *dav_fs_get_dir( request_rec *r );
   789 +const int dav_fs_get_hidefiles( request_rec *r );
   790 +const ap_regex_t *dav_fs_get_mask( request_rec *r );
   791 +
   792  #endif /* _DAV_FS_REPOS_H_ */
   793  /** @} */
   795 Index: modules/dav/main/mod_dav.c
   796 diff -Nau modules/dav/main/mod_dav.c.orig modules/dav/main/mod_dav.c
   797 --- modules/dav/main/mod_dav.c.orig	2011-02-09 09:43:17.000000000 +0100
   798 +++ modules/dav/main/mod_dav.c	2012-09-17 14:16:06.944219747 +0200
   799 @@ -884,7 +884,14 @@
   801      return DECLINED;
   802  }
   803 -
   804 +struct dav_stream {
   805 +    apr_pool_t *p;
   806 +    apr_file_t *f;
   807 +    const char *pathname;       /* we may need to remove it at close time */
   808 +    apr_size_t quota;           /* config data for quota check */
   809 +    const char *area_path;
   810 +    request_rec *r;         /* request of this resource*/
   811 +};
   812  /* handle the PUT method */
   813  static int dav_method_put(request_rec *r)
   814  {
   815 @@ -958,7 +965,6 @@
   816      else {
   817          mode = DAV_MODE_WRITE_TRUNC;
   818      }
   819 -
   820      /* make sure the resource can be modified (if versioning repository) */
   821      if ((err = dav_auto_checkout(r, resource,
   822                                   0 /* not parent_only */,
   823 @@ -1043,6 +1049,7 @@
   824              /* no error during the write, but we hit one at close. use it. */
   825              err = err2;
   826          }
   827 +
   828      }
   830      /*
   831 @@ -2583,7 +2590,6 @@
   832      dav_lockdb *lockdb;
   833      int replace_dest;
   834      int resnew_state;
   835 -
   836      /* Ask repository module to resolve the resource */
   837      err = dav_get_resource(r, !is_move /* label_allowed */,
   838                             0 /* use_checked_in */, &resource);
   839 @@ -2635,6 +2641,7 @@
   841          return dav_error_response(r, lookup.err.status, lookup.err.desc);
   842      }
   843 +
   844      if (lookup.rnew->status != HTTP_OK) {
   845          const char *auth = apr_table_get(lookup.rnew->err_headers_out,
   846                                          "WWW-Authenticate");
   847 @@ -2700,6 +2707,7 @@
   848      if ((depth = dav_get_depth(r, DAV_INFINITY)) < 0) {
   849          /* dav_get_depth() supplies additional information for the
   850           * default message. */
   851 +
   852          return HTTP_BAD_REQUEST;
   853      }
   854      if (depth == 1) {
   855 @@ -2817,7 +2825,6 @@
   856          /* ### pass lockdb! */
   857          (void)dav_unlock(r, resource, NULL);
   858      }
   859 -
   860      /* if this is a move, then the source parent collection will be modified */
   861      if (is_move) {
   862          if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
   863 @@ -2835,7 +2842,6 @@
   864       * can be notified as to how it changed.
   865       */
   866      resnew_state = dav_get_resource_state(lookup.rnew, resnew);
   867 -
   868      /* In a MOVE operation, the destination is replaced by the source.
   869       * In a COPY operation, if the destination exists, is under version
   870       * control, and is the same resource type as the source,
   871 @@ -4573,7 +4579,7 @@
   872       * be more destructive than the user intended. */
   873      if (r->parsed_uri.fragment != NULL) {
   874          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
   875 -                     "buggy client used un-escaped hash in Request-URI");
   876 +                     "buggy client used un-escaped hash in Request-URI uri is '%s'",r->uri);
   877          return dav_error_response(r, HTTP_BAD_REQUEST,
   878                                    "The request was invalid: the URI included "
   879                                    "an un-escaped hash character");
   880 Index: modules/dav/main/util.c
   881 diff -Nau modules/dav/main/util.c.orig modules/dav/main/util.c
   882 --- modules/dav/main/util.c.orig	2010-07-21 20:25:49.000000000 +0200
   883 +++ modules/dav/main/util.c	2012-09-17 14:16:06.945216500 +0200
   884 @@ -168,6 +168,8 @@
   885      apr_port_t port;
   886      apr_uri_t comp;
   887      char *new_file;
   888 +    const char *new_filename;
   889 +    char *redirect;
   890      const char *domain;
   892      /* first thing to do is parse the URI into various components */
   893 @@ -278,7 +280,13 @@
   894       * to apply appropriate restrictions (e.g. readonly).
   895       */
   896      result.rnew = ap_sub_req_method_uri(r->method, new_file, r, NULL);
   897 -
   898 +    //detect redirect
   899 +    new_filename=apr_pstrdup(r->pool, result.rnew->filename);
   900 +    redirect=ap_getword(r->pool, &new_filename, ':');
   901 +    //ap_unescape_url(new_filename);
   902 +    if(!strcasecmp(redirect, "redirect")) {//subrequest for resolve redirect
   903 +    	result.rnew = ap_sub_req_method_uri(r->method, new_filename, r, NULL);
   904 +    }
   905      return result;
   906  }
   908 @@ -1420,11 +1428,11 @@
   910      retVal = ap_meets_conditions(r);
   912 -    /* If-None-Match '*' fix. If-None-Match '*' request should succeed 
   913 +    /* If-None-Match '*' fix. If-None-Match '*' request should succeed
   914       * if the resource does not exist. */
   915      if (retVal == HTTP_PRECONDITION_FAILED) {
   916          /* Note. If if_none_match != NULL, if_none_match is the culprit.
   917 -         * Since, in presence of If-None-Match, 
   918 +         * Since, in presence of If-None-Match,
   919           * other If-* headers are undefined. */
   920          if ((if_none_match =
   921              apr_table_get(r->headers_in, "If-None-Match")) != NULL) {
   922 Index: modules/mappers/mod_rewrite.c
   923 diff -Nau modules/mappers/mod_rewrite.c.orig modules/mappers/mod_rewrite.c
   924 --- modules/mappers/mod_rewrite.c.orig	2012-01-24 20:39:31.000000000 +0100
   925 +++ modules/mappers/mod_rewrite.c	2012-09-17 14:16:06.947134500 +0200
   926 @@ -2286,7 +2286,7 @@
   927                      current->len = span;
   928                      current->string = bri->source + bri->regmatch[n].rm_so;
   929                  }
   930 -                
   931 +
   932                  outlen += span;
   933              }
   935 @@ -3250,7 +3250,7 @@
   936      case 'B':
   937          if (!*key || !strcasecmp(key, "ackrefescaping")) {
   938              cfg->flags |= RULEFLAG_ESCAPEBACKREF;
   939 -        } 
   940 +        }
   941          else {
   942              ++error;
   943          }
   944 @@ -4026,6 +4026,7 @@
   945          if (r->main != NULL &&
   946              (p->flags & RULEFLAG_IGNOREONSUBREQ ||
   947               p->flags & RULEFLAG_FORCEREDIRECT    )) {
   948 +ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"Ignore this rule on subrequests");
   949              continue;
   950          }

mercurial