
#patch -p2 < [this file]
see http://www.geocities.co.jp/Hollywood/4471/webdav/webdav.html
        satake@goodcrew.ne.jp

special thanks:  Marco
--- work/httpd-2.0.50/modules/dav/main/mod_dav.c	2004-06-07 19:41:01.000000000 +0900
+++ work/httpd-2.0.50-new/modules/dav/main/mod_dav.c	2004-08-18 19:14:43.000000000 +0900
@@ -57,6 +57,7 @@
 #include "util_script.h"
 
 #include "mod_dav.h"
+#include "quotachk.h"	// add by satake@goodcrew.ne.jp
 
 
 /* ### what is the best way to set this? */
@@ -78,6 +79,8 @@
     const char *dir;
     int locktimeout;
     int allow_depthinfinity;
+    int area_size;		// add by satake@goodcrew.ne.jp
+    const char *area_path;	// add by satake@goodcrew.ne.jp
 
 } dav_dir_conf;
 
@@ -162,6 +165,8 @@
         conf->dir = d;
     }
 
+    conf->area_path = NULL;	// add by satake@goodcrew.ne.jp
+
     return conf;
 }
 
@@ -194,6 +199,9 @@
     newconf->dir = DAV_INHERIT_VALUE(parent, child, dir);
     newconf->allow_depthinfinity = DAV_INHERIT_VALUE(parent, child,
                                                      allow_depthinfinity);
+    /* add by satake@goodcrew.ne.jp */
+    newconf->area_size = DAV_INHERIT_VALUE( parent , child , area_size );
+    newconf->area_path = DAV_INHERIT_VALUE( parent , child , area_path );
 
     return newconf;
 }
@@ -211,6 +219,22 @@
     return conf->provider;
 }
 
+/** add by satake@goodcrew.ne.jp */
+const int   dav_get_area_size( request_rec *r ) {
+
+    dav_dir_conf *conf = ap_get_module_config( r->per_dir_config , &dav_module );
+    return  conf->area_size;
+
+}
+
+/** add by satake@goodcrew.ne.jp */
+const char *dav_get_dir( request_rec *r ) {
+
+    dav_dir_conf *conf = ap_get_module_config( r->per_dir_config , &dav_module );
+    return  conf->area_path;
+
+}
+
 const dav_hooks_locks *dav_get_lock_hooks(request_rec *r)
 {
     return dav_get_provider(r)->locks;
@@ -301,6 +325,23 @@
 }
 
 /*
+ * Command handler for DAVSATMaxAreaSize directive, which is TAKE1
+ *			add by satake@goodcrew.ne.jp
+ */
+static const char *dav_cmd_davareasize( cmd_parms *cmd , void *config , const char *arg1 ) {
+
+    dav_dir_conf *conf = ( dav_dir_conf * )config;
+
+    conf->area_size = atoi( arg1 );
+    if ( conf->area_size < 0 )
+        return "DAVSATMaxAreaSize requires a non-negative integer.";
+
+    conf->area_path = cmd->path;
+    return NULL;
+
+}
+
+/*
 ** dav_error_response()
 **
 ** Send a nice response back to the user. In most cases, Apache doesn't
@@ -905,6 +946,15 @@
         return dav_handle_err(r, err, multi_response);
     }
 
+/**
+    check for disk space is enough
+            add by satake@goodcrew.ne.jp
+*/
+    if ( dav_qchk_checksize( r )==DAV_QCHK_NG )
+        return dav_error_response(r, HTTP_INSUFFICIENT_STORAGE,
+                                     "There is not enough storage to write to "
+                                     "this resource.");
+
     /* make sure the resource can be modified (if versioning repository) */
     if ((err = dav_auto_checkout(r, resource,
                                  0 /* not parent_only */,
@@ -2462,6 +2512,15 @@
         return dav_handle_err(r, err, NULL);
     }
 
+/**
+    check for disk space is enough
+            add by satake@goodcrew.ne.jp
+*/
+    if ( dav_qchk_checksize( r )==DAV_QCHK_NG )
+        return dav_error_response(r, HTTP_INSUFFICIENT_STORAGE,
+                                     "There is not enough storage to write to "
+                                     "this resource.");
+
     /* try to create the collection */
     resource->collection = 1;
     err = (*resource->hooks->create_collection)(resource);
@@ -2747,6 +2806,15 @@
         return result;
     }
 
+/**
+    check for disk space is enough
+            add by satake@goodcrew.ne.jp
+*/
+    if ( dav_qchk_checksize( r )==DAV_QCHK_NG )
+        return dav_error_response(r, HTTP_INSUFFICIENT_STORAGE,
+                                     "There is not enough storage to write to "
+                                     "this resource.");
+
     if ((err = dav_open_lockdb(r, 0, &lockdb)) != NULL) {
         /* ### add a higher-level description? */
         return dav_handle_err(r, err, NULL);
@@ -4779,6 +4847,12 @@
                   ACCESS_CONF|RSRC_CONF,
                   "specify minimum allowed timeout"),
 
+    /* per directory/location */
+    /*		add by satake@goodcrew.ne.jp */
+    AP_INIT_TAKE1("DAVSATMaxAreaSize", dav_cmd_davareasize, NULL,
+                  ACCESS_CONF,
+                  "max size of user storage area, per KByte"),
+
     /* per directory/location, or per server */
     AP_INIT_FLAG("DAVDepthInfinity", dav_cmd_davdepthinfinity, NULL,
                  ACCESS_CONF|RSRC_CONF,
--- work/httpd-2.0.50/modules/dav/main/quotachk.h	1970-01-01 09:00:00.000000000 +0900
+++ work/httpd-2.0.50-new/modules/dav/main/quotachk.h	2004-08-18 19:14:43.000000000 +0900
@@ -0,0 +1,15 @@
+/**
+    disk quota check modules for WebDAV service
+                        author: satake@goodcrew.ne.jp
+*/
+#define     DAV_QCHK_OK     0
+#define     DAV_QCHK_NG     -1
+
+/** set your storage cluster size */
+#ifndef     DAV_CLUSTER_SIZE
+    #define     DAV_CLUSTER_SIZE    4096
+#endif
+
+int         dav_qchk_checksize( request_rec * );
+const int   dav_get_area_size( request_rec * );
+const char *dav_get_dir( request_rec * );
--- work/httpd-2.0.50/modules/dav/main/quotachk.c	1970-01-01 09:00:00.000000000 +0900
+++ work/httpd-2.0.50-new/modules/dav/main/quotachk.c	2004-08-18 19:14:43.000000000 +0900
@@ -0,0 +1,179 @@
+/**
+    disk quota check modules for WebDAV service
+                        author: satake@goodcrew.ne.jp
+*/
+#include "apr_lib.h"            /* for apr_is* */
+#include "apr_tables.h"         /* for apr_is* */
+#include "apr_file_info.h"
+#include "apr_strings.h"
+#include "httpd.h"
+#include "http_log.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include "mod_dav.h"
+#include "quotachk.h"
+
+/**
+    get (dirname) total size ( per 512byte )
+    @param  dirname directory name
+    @return block size
+*/
+static  int     get_dir_size( const char *dirname , apr_pool_t *pool )
+{
+
+    DIR             *dir;
+    struct dirent   *ent;
+    struct stat     status;
+    char            *buffer;
+    int             size = 0;
+
+    dir = opendir( dirname );
+    if ( dir==NULL ) {
+
+        return  0;
+
+    }
+
+    while ( ( ent = readdir( dir ) )!=NULL ) {
+
+        if ( ( !strcmp( ent->d_name , "." ) ) || ( !strcmp( ent->d_name , ".." ) ) ) {
+
+            continue;
+
+        }
+
+        apr_filepath_merge( &buffer , dirname , ent->d_name , 0 , pool );
+
+        if ( !lstat( buffer , &status ) ) {
+
+            size += status.st_blocks;
+            if ( status.st_mode & S_IFDIR ) {
+
+                size += get_dir_size( buffer , pool );
+
+            }
+
+        }
+
+    }
+    closedir( dir );
+
+    return  size;
+
+}
+
+/**
+    return  directory total disk space.
+    same as 'du -sk dirname' command.
+    @param  dirname     directory
+    @return     total space
+*/
+static  int     dav_qchk_du( const char *dirname , apr_pool_t *pool )
+{
+
+    struct stat     status;
+
+    if ( lstat( dirname , &status ) ) {
+
+        return  0;
+
+    }
+    return  ( status.st_blocks + ( ( status.st_mode & S_IFDIR ) ? get_dir_size( dirname , pool ) : 0 ) ) / 2;
+
+}
+
+/**
+    check size
+    return  0: OK , else: NG
+*/
+int     dav_qchk_checksize( request_rec *request )
+{
+
+    int                 maxsize;
+    int                 nowsize;
+    int                 putsize;
+    int                 retnum;
+    const char          *conlen;
+    const char          *dirname;
+    dav_lookup_result   res;
+
+    /** set default return */
+    retnum = DAV_QCHK_OK;
+
+    /** get max area size */
+    if ( ! ( maxsize = dav_get_area_size( request ) ) ) {
+
+        return  retnum;
+
+    }
+
+    /** get <Directory> directive's parameter */
+    if ( ( dirname = dav_get_dir( request ) )==NULL ) {
+
+        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "WebDAV-Quota: Directory not detect" );
+        return  retnum;
+
+    }
+
+    /** if <Location> directive without DAVSATAreaPath, then no function */
+    if ( strstr( request->filename , dirname )!=request->filename ) {
+
+        /** try uri->filename convert */
+        res = dav_lookup_uri( dirname , request , 0 );
+        if ( ( res.err.status )||( res.rnew==NULL ) ) {
+
+            if ( res.err.desc!=NULL )
+                ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
+                    apr_psprintf( request->pool , "WebDAV-Quota: [%d]: %s\n" , res.err.status, res.err.desc )
+                    );
+            return  retnum;
+
+        }
+
+        dirname = res.rnew->filename;
+        if ( ( dirname==NULL )||( strstr( request->filename , dirname )!=request->filename ) ) {
+
+            ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
+                            "WebDAV-Quota: Quota directory not match request file path."
+                            );
+            return  retnum;
+
+        }
+
+    }
+
+    /** get now user used size */
+    nowsize = dav_qchk_du( dirname , request->pool );
+
+    /** get put size */
+    conlen = NULL;
+    putsize = 0;
+    if ( request->headers_in != NULL ) {
+
+        conlen = apr_table_get( request->headers_in , "content-length" );
+
+    }
+    if ( conlen!=NULL ) {
+
+        putsize = ( ( atoi( conlen ) + DAV_CLUSTER_SIZE - 1 ) / DAV_CLUSTER_SIZE ) * ( DAV_CLUSTER_SIZE / 1024 );
+
+    }
+
+    /** check size */
+    retnum = ( nowsize + putsize >= maxsize ) ? DAV_QCHK_NG : DAV_QCHK_OK;
+    if ( retnum==DAV_QCHK_NG ) {
+
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
+                        apr_psprintf(
+                            request->pool ,
+                            "WebDAV-Quota: Directory `%s' size `%dKB' is over `%dKB'!" ,
+                            dirname , nowsize + putsize , maxsize
+                            )
+                        );
+
+    }
+    return  retnum;
+
+}
--- work/httpd-2.0.50/modules/dav/main/config5.m4	2001-08-01 04:21:51.000000000 +0900
+++ work/httpd-2.0.50-new/modules/dav/main/config5.m4	2004-08-18 19:15:08.000000000 +0900
@@ -2,7 +2,7 @@
 
 APACHE_MODPATH_INIT(dav/main)
 
-dav_objects="mod_dav.lo props.lo util.lo util_lock.lo liveprop.lo providers.lo std_liveprop.lo"
+dav_objects="mod_dav.lo props.lo util.lo util_lock.lo liveprop.lo providers.lo std_liveprop.lo quotachk.lo"
 
 if test "$enable_http" = "no"; then
   dav_enable=no
--- work/httpd-2.0.50/configure	2004-06-29 09:11:29.000000000 +0900
+++ work/httpd-2.0.50-new/configure	2004-08-18 19:14:43.000000000 +0900
@@ -13351,7 +13351,7 @@
   > $modpath_current/modules.mk
 
 
-dav_objects="mod_dav.lo props.lo util.lo util_lock.lo liveprop.lo providers.lo std_liveprop.lo"
+dav_objects="mod_dav.lo props.lo util.lo util_lock.lo liveprop.lo providers.lo std_liveprop.lo quotachk.lo"
 
 if test "$enable_http" = "no"; then
   dav_enable=no

