Mon, 28 Jan 2013 17:37:18 +0100
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 }