Description: Add mod_quotatab module
Author: Francesco Paolo Lovergine <frankie@debian.org>
Forwarded: not needed

Index: proftpd-dfsg/README.mod_quotatab
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ proftpd-dfsg/README.mod_quotatab	2011-02-08 13:33:10.000000000 +0100
@@ -0,0 +1,354 @@
+  ------------------------------------------------------------------------
+
+                         ProFTPD module mod_quotatab
+
+  ------------------------------------------------------------------------
+
+This module is contained in the mod_quotatab.c, mod_quotatab.h, and in its
+submodule source files, for ProFTPD 1.2, found here, and is not compiled by
+default. Installation instructions can be found here.
+
+This module is designed to impose quotas, both byte- and file-based, on FTP
+accounts, based on user, group, class, or for all accounts. It is based on
+the ideas contained in Eric Estabrook's mod_quota; however, this module has
+been written from scratch to implement quotas in a very different manner. A
+more detailed explanation of the usage of this module follows the directive
+explanations.
+
+The most current version of mod_quotatab's submodules supports storage of
+quota table information in various formats:
+
+   * mod_quotatab_file for file-based quota tables
+   * mod_quotatab_sql for SQL-based quota tables
+
+The most current version of mod_quotatab can be found at:
+
+  http://www.castaglia.org/proftpd/
+
+The eventual goal of this module is to make use of the Confstream API, an
+experimental API described here. This API would make support for tables in
+other formats (e.g. LDAP, CDB, DBM) much easier to implement.
+
+Author
+
+Please contact TJ Saunders <tj at castaglia.org> with any questions,
+concerns, or suggestions regarding this module.
+
+Thanks
+
+2002-01-12: Thanks to SupaFly <ntlfy at ntlworld.com> for helping debug an
+issue with a missing tally table.
+
+2002-03-30: Thanks to Kai Langheim <kl at q-nic.de> for pointing out several
+small bugs affecting users with no quota entries.
+
+Directives
+
+   * QuotaDirectoryTally
+   * QuotaDisplayUnits
+   * QuotaEngine
+   * QuotaLimitTable
+   * QuotaLog
+   * QuotaShowQuotas
+   * QuotaTallyTable
+
+SITE Commands
+
+   * SITE QUOTA
+
+  ------------------------------------------------------------------------
+
+QuotaDirectoryTally
+
+Syntax: QuotaDirectoryTally on|off
+Default: QuotaDirectoryTally off
+Context: server config, <VirtualHost>, <Global>
+Module: mod_quotatab
+Compatibility: 1.2.5rc2 and later
+
+The QuotaDirectoryTally directive configures mod_quotatab to take directory
+operations (e.g. creating a directory, removing a directory) into account
+when tallying.
+
+  ------------------------------------------------------------------------
+
+QuotaDisplayUnits
+
+Syntax: QuotaDisplayUnits "b"|"Kb"|"Mb"|"Gb"
+Default: None
+Context: server config, <VirtualHost>, <Global>
+Module: mod_quotatab
+Compatibility: 1.2.5rc2 and later
+
+This directive configures how the user's current byte quota values will be
+reported to them. Note that this directive does not affect how the quota
+values are stored in the quota table, only their presentation to the user.
+
+"b" causes quotas to be displayed in bytes; "Kb", kilobytes; "Mb",
+megabytes; and "Gb", gigabytes.
+
+Example:
+
+  # display quota information in megabytes
+  QuotaDisplayUnits Mb
+
+  ------------------------------------------------------------------------
+
+QuotaEngine
+
+Syntax: QuotaEngine on|off
+Default: None
+Context: server config, <VirtualHost>, <Global>
+Module: mod_quotatab
+Compatibility: 1.2.5rc2 and later
+
+The QuotaEngine directive enables or disables the module's runtime quota
+engine. If it is set to off this module does no runtime processing at all.
+Use this directive to disable the module instead of commenting out all
+mod_quotatab directives.
+
+  ------------------------------------------------------------------------
+
+QuotaLimitTable
+
+Syntax: QuotaLimitTable source-type:source-info
+Default: None
+Context:
+Module: mod_quotatab
+Compatibility: 1.2.5rc2 and later
+
+This directive configures the information necessary for the module to locate
+and use the table containing the quota limit, the maximum number of bytes
+and/or files defined for use by specific users, groups, classes, etc, and is
+required for mod_quotatab to function.
+
+Please consult the relevant submodule documentation for details on that
+module's syntax for this configuration directive.
+
+See also: QuotaTallyTable
+
+  ------------------------------------------------------------------------
+
+QuotaLog
+
+Syntax: QuotaLog file|"none"
+Default: None
+Context:
+Module: mod_quotatab
+Compatibility: 1.2.5rc2 and later
+
+The QuotaLog directive is used to a specify a log file for mod_quotatab
+reporting, and can be done a per-server basis. The file parameter must be
+the full path to the file to use for logging. Note that this path must not
+be to a world-writeable directory and, unless AllowLogSymlinks is explicitly
+set to on (generally a bad idea), the path must not be a symbolic link.
+
+If file is "none", no logging will be done at all; this setting can be used
+to override a QuotaLog setting inherited from a <Global> context.
+
+  ------------------------------------------------------------------------
+
+QuotaShowQuotas
+
+Syntax: QuotaShowQuotas on|off
+Default: on
+Context:
+Module: mod_quotatab
+Compatibility: 1.2.5rc2 and later
+
+The QuotaShowQuotas directive can be used to enable/disable mod_quotatab's
+response to a SITE QUOTA request. For some sites, revealing the current
+quota information may be considered an unnecessary, perhaps even
+detrimental, information leak; other sites may consider this a definite
+feature.
+
+  ------------------------------------------------------------------------
+
+QuotaTallyTable
+
+Syntax: QuotaTallyTable source-type:source-info
+Default: None
+Context:
+Module: mod_quotatab
+Compatibility: 1.2.5rc2 and later
+
+This directive configures the information necessary for the module to locate
+and use the table containing the quota tally, or the current byte/file
+counts for users, groups, classes, etc, and is required for mod_quotatab to
+function.
+
+Please consult the relevant submodule documentation for details on that
+module's syntax for this configuration directive.
+
+See also: QuotaLimitTable
+
+  ------------------------------------------------------------------------
+
+SITE QUOTA
+
+The SITE QUOTA command will display the quota, both the limit and the
+current tally, to the client. This SITE command accepts no parameters, and
+can only be used once the client has successfully logged in.
+
+Example:
+
+ftp> quote SITE QUOTA
+200-The current quota for this session are [current/limit]:
+ Name: tj
+ Quota Type: User
+ Per Session: True
+ Limit Type: Hard
+   Uploaded Kb:         unlimited
+   Downloaded Kb:       unlimited
+   Transferred Kb:      unlimited
+   Uploaded files:      1/1
+   Downloaded files:    unlimited
+   Transferred files:   unlimited
+200 Please contact root@familiar.castaglia.org if these entries are inaccurate
+ftp>
+
+Use of this SITE command can be controlled via <Limit>, e.g.:
+
+  <Limit SITE_QUOTA>
+    AllowUser tj
+    DenyAll
+  </Limit>
+
+Like many SITE commands, the FTP client will probably not recognize or
+support SITE QUOTA. Hopefully the client does have the ability to send
+arbitrary commands to the server, as the common ftp(1) client does via
+quote.
+
+The email address displayed in the SITE QUOTA output can be configured via
+the ServerAdmin directive.
+
+  ------------------------------------------------------------------------
+
+Usage
+
+To use mod_quotatab's functionality, you must first define the tables that
+together contain the quota information.
+
+There are two such quota tables: one table for providing quota information
+about the absolute byte/file limits for users, groups, and classes, and a
+separate table for maintaining the current tally, or number of bytes/files
+used, for those same users, groups, and classes. This separation of
+information allows for a configuration such as using LDAP to efficiently
+distribute the limit information, and local SQL databases for efficiently
+storing the tally. The limit table is considered a read-only table, and is
+only accessed at the start of session in order to determine what the session
+limits should be. The tally table is accessed in read-write mode, and is
+updated after the relevant FTP commands have been processed.
+
+This module was not explicitly designed for easy interaction with other
+applications, but rather for other criteria:
+
+   * efficient lookups and updates
+   * no need for ~/.quota files
+   * no need of requirement for root privileges to access quotas
+   * easy support for an abstraction layer for storing quota information in
+     other formats
+   * support for a SITE command that allows users to view their current
+     quotas
+
+This module maintains its quotas based solely on FTP commands - it does not
+enforce quotas based on files that may have been added, deleted, or moved
+via shell access or any mechanism other than through the proftpd server.
+
+When a client logs in, assuming QuotaEngine is on, mod_quotatab will check
+the limit table for the record most appropriate for that client. This check
+first examines the table for records of type user that match the client's
+login name. If no such matching records are found, it checks for records of
+type group that match any of the user's groups (both primary and
+supplemental). Failing that, it will check for records of type class that
+belong to the class (if enabled) from which the client is connecting. If
+still no matching records are found, the table will be searched for a record
+of type all; if absent, the module will assume that no quotas apply to the
+client.
+
+Once the limits for the current session have been established, mod_quotatab
+examines the tally table to see what the current numbers in the matching
+tally record are. Should the client have an applicable limit record but no
+matching tally record, the module will initialize a new record in the tally
+table.
+
+For the purposes of tracking the number of uploaded bytes/files, the tally
+will be adjusted accordingly upon use of the following FTP commands: APPE
+(bytes only), DELE, STOR, and STOU. The number of bytes used for the
+calculation will be determined from the difference in file size of the file
+in question.
+
+For the purposes of tracking the number of downloaded bytes/files, the tally
+will be adjusted accordingly upon use of the following FTP commands: RETR.
+The number of bytes used for the calculation will be determined from the
+number of bytes sent to the client.
+
+For the purposes of tracking the number of transferred bytes/files, the
+tally will be adjusted accordingly upon use of the following FTP commands:
+APPE (bytes only), DELE, RETR, STOR, and STOU. The number of bytes used for
+the calculation will be determined from the number of bytes sent to the
+client. This type of limit allows for byte/file limits to be set that
+encompass both uploads and downloads.
+
+Note that if all three types of quotas are set (upload, download, and
+transfer), any quota reached will cause denial of FTP commands. This means
+that a high upload quota will never be reached if a low transfer quota is in
+effect. This holds true for bytes and files quota. For example, if a user
+has a limited number of both bytes and files to be uploaded in their limit
+record, the first limit reached (bytes or files) is the effective limit.
+Caveat emptor.
+
+For any quota limit that is set as "unlimited", mod_quotatab will not keep
+the tally. Many site administrators might want this ability, for accounting
+purposes. However, that ability is outside of the intended design of this
+module; other logging modules are much better suited for accounting purposes
+(e.g. mod_sql's SQLLog directive).
+
+If any developers wish to make use of mod_quotatab's quota information, or
+to develop a new submodule, there is developer documentation available here.
+
+  ------------------------------------------------------------------------
+
+Installation
+
+To install mod_quotatab, follow these instructions. After unpacking the
+tarball, copy the mod_quotatab.c, mod_quotatab.h, mod_quotatab_file.c, and
+mod_quotatab_sql.c files into:
+
+  proftpd-dir/contrib/
+
+after unpacking the latest proftpd-1.2 source code. Follow the usual steps
+for using third-party modules in proftpd:
+
+  ./configure --with-modules=quotatab-modules
+  make
+  make install
+
+where quotatab-modules will depend on the types of quota tables you wish to
+support.
+
+For file-based quota tables, include the mod_quotatab_file submodule, e.g.:
+
+  mod_quotatab:mod_quotatab_file
+
+For SQL-based quota tables, include the mod_quotatab_sql submodule, e.g.:
+
+  mod_quotatab:mod_quotatab_sql
+
+And, if you wish to support file- and SQL-based quota tables:
+
+  mod_quotatab:mod_quotatab_file:mod_quotatab_sql
+
+Note that SQL tables require that a correct installation of mod_sql (and any
+of its backend modules) also be used. Consult the mod_sql documentation for
+installation instructions for that module.
+
+  ------------------------------------------------------------------------
+
+Author: $Author: frankie $
+Last Updated: $Date: 2003/11/17 15:30:12 $
+
+  ------------------------------------------------------------------------
+ Copyright 2000-2002 TJ Saunders
+All Rights Reserved
+  ------------------------------------------------------------------------
Index: proftpd-dfsg/diskuse
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ proftpd-dfsg/diskuse	2011-02-08 13:33:10.000000000 +0100
@@ -0,0 +1,232 @@
+#!/usr/bin/perl
+# -------------------------------------------------------------------------
+# Copyright (C) 2002 TJ Saunders <tj@castaglia.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+#
+#  $Id: 14.quotatab_modules.diff,v 1.4 2003/11/17 15:30:12 frankie Exp $
+#
+# -------------------------------------------------------------------------
+
+use strict;
+
+use Fcntl;
+use File::Basename qw(basename);
+use Getopt::Long;
+
+my $program = basename($0);
+my %opts = {};
+
+GetOptions(\%opts, 'G', 'K', 'M', 'dir-tally', 'group=s', 'help',
+  'user=s', 'verbose');
+
+my $verbose = 0;
+my $user_id = -1;
+my $group_id = -1;
+
+usage() if defined($opts{'help'});
+
+if (length(@ARGV) < 1) {
+  print STDOUT "$program: wrong number of parameters\n";
+  exit 0;
+}
+
+unless (defined($opts{'user'}) || defined($opts{'group'})) {
+  print STDOUT "$program: missing required --group or --user option\n";
+  exit 0;
+}
+
+if (defined($opts{'user'})) {
+  $user_id = getpwnam($opts{'user'}) or
+    die "$program: no such user: $opts{'user'}\n";
+}
+
+if (defined($opts{'group'})) {
+  $group_id = getgrnam($opts{'group'}) or
+    die "$program: no such group: $opts{'group'}\n";
+}
+
+$verbose = 1 if (defined($opts{'verbose'}));
+
+my ($total_bytes, $total_files);
+
+foreach my $dir (@ARGV) {
+  my ($bytes, $files) = get_dir_disk_use($dir);
+
+  $total_bytes += $bytes;
+  $total_files += $files;
+}
+
+my $byte_units = "bytes";
+
+if (defined($opts{'K'})) {
+  $total_bytes /= 1024;
+  $byte_units = "KB";
+
+} elsif (defined($opts{'M'})) {
+  $total_bytes /= (1024 * 1024);
+  $byte_units = "MB";
+
+} elsif (defined($opts{'G'})) {
+  $total_bytes /= (1024 * 1024 * 1024);
+  $byte_units = "GB";
+}
+
+my $file_units = "files";
+$file_units = "file" if ($total_files == 1);
+
+print STDOUT "$program: $total_bytes $byte_units in $total_files $file_units\n";
+
+# done
+exit 0;
+
+# --------------------------------------------------------------------------
+sub get_dir_disk_use {
+  my ($dir) = @_;
+
+  print STDOUT "$program: examining directory '$dir'\n" if $verbose;
+
+  my @subdirs = ();
+  my $nbytes = 0;
+  my $nfiles = 0;
+
+  unless (opendir(DIR, $dir)) {
+    print STDERR "$program: unable to open directory '$dir': $!\n";
+    return (0, 0);
+  }
+
+  my @files = readdir(DIR);
+  close(DIR);
+
+  foreach my $file (@files) {
+    my ($mode, $uid, $gid, $size) = (lstat("$dir/$file"))[2, 4, 5, 7];
+
+    # Is this entry a regular file, or a directory?
+    unless (-f "$dir/$file" || (-l "$dir/$file" && !-f "$dir/$file") || -d "$dir/$file") {
+      print STDOUT "$program: skipping '$dir/$file': not a file or directory\n" if $verbose;
+      next;
+    }
+
+    # Does this file match the given user/group ownership?
+    if ($user_id != -1 && $group_id != -1) {
+
+      if ($uid == $user_id && $gid == $group_id) {
+
+        if (defined($opts{'dir-tally'}) && $file eq ".") {
+          $nbytes += $size;
+          $nfiles++;
+ 
+        } elsif (! -d "$dir/$file") {
+          $nbytes += $size;
+          $nfiles++;
+        }
+
+      } else {
+        print STDOUT "$program: '$file' does not match UID $user_id, GID $group_id\n" if $verbose;
+      }
+
+    } elsif ($user_id != -1) {
+
+      if ($uid == $user_id) {
+
+        if (defined($opts{'dir-tally'}) && $file eq ".") {
+          $nbytes += $size;
+          $nfiles++;
+
+        } elsif (! -d "$dir/$file") {
+          $nbytes += $size;
+          $nfiles++;
+        }
+
+      } else {
+        print STDOUT "$program: '$file' does not match UID $user_id\n" if $verbose;
+      }
+
+    } elsif ($group_id != -1) {
+
+      if ($gid == $group_id) {
+
+        if (defined($opts{'dir-tally'}) && $file eq ".") {
+          $nbytes += $size;
+          $nfiles++;
+
+        } elsif (! -d "$dir/$file") {
+          $nbytes += $size;
+          $nfiles++;
+        }
+
+      } else {
+        print STDOUT "$program: '$file' does not match GID $group_id\n" if $verbose;
+      }
+    }
+
+    # Is this entry a directory?  If so, add it to the subdir list.
+    if (-d "$dir/$file") {
+
+      # Skip dot directories
+      push(@subdirs, "$dir/$file") unless ($file eq "." || $file eq "..");
+    }
+  }
+
+  # Now, recurse through the directory's subdirectories
+  foreach my $subdir (@subdirs) {
+    my ($bytecount, $filecount) = get_dir_disk_use($subdir);
+    $nbytes += $bytecount;
+    $nfiles += $filecount;
+  }
+
+  return ($nbytes, $nfiles);
+}
+
+# --------------------------------------------------------------------------
+sub usage {
+
+  print STDOUT <<END_OF_USAGE;
+
+usage: $program [options] dir1 dir2 ... dirN
+
+ $program calculates the amount of disk space used underneath the given
+ directory (or directories).  Either a --group or a --user option is required.
+ If both are used, only files whose ownership matches both the given name and
+ group will be added to the disk usage sum.
+
+ Options:
+
+  --G          Display the number of bytes in units of gigabytes.  The default
+               number is in bytes.
+
+  --K          Display the number of bytes in units of kilobytes.  The default
+               number is in bytes.
+
+  --M          Display the number of bytes in units of megabytes.  The default
+               number is in bytes.
+
+  --dir-tally  Count the size of directories toward the disk usage sum.  The
+               default is to consider regular files only.
+
+  --group      Count files owned by this group in the disk usage sum.
+
+  --help       Display this message.
+
+  --user       Count files owned by this user in the disk usage sum.
+
+  --verbose    Display diagnostic output while $program is running.
+
+END_OF_USAGE
+
+  exit 0;
+}
+
+# --------------------------------------------------------------------------
Index: proftpd-dfsg/diskuse.html
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ proftpd-dfsg/diskuse.html	2011-02-08 13:33:10.000000000 +0100
@@ -0,0 +1,103 @@
+<!-- $Id: 14.quotatab_modules.diff,v 1.4 2003/11/17 15:30:12 frankie Exp $ -->
+<!-- $Source: /cvsroot/pkg-proftpd/debian/patches/14.quotatab_modules.diff,v $ -->
+
+<html>
+<head>
+<title>diskuse: tool for ProFTPD mod_quotatab</title>
+</head>
+
+<body bgcolor=white>
+
+<hr><br>
+<center>
+<h2><b><code>diskuse</code>: tool for ProFTPD module <code>mod_quotatab</code></b></h2>
+</center>
+<hr><br>
+
+This program is distributed with the
+<a href="./mod_quotatab.html"><code>mod_quotatab</code></a> module for
+ProFTPD 1.2.  It is used to calculate the amount of disk space currently
+used by a given user and/or group.
+
+<p>
+The most current version of <code>diskuse</code> can be found at:
+<pre>
+  <a href="http://www.castaglia.org/proftpd/">http://www.castaglia.org/proftpd/</a>
+</pre>
+
+<h2>Author</h2>
+<p>
+Please contact TJ Saunders &lt;tj <i>at</i> castaglia.org&gt; with any
+questions, concerns, or suggestions regarding this program.
+
+<p>
+<hr><br>
+<h2><a name="Usage">Usage</a></h2>
+The following describes the common usage of the <code>diskuse</code> tool.
+The options supported are described in more detail
+<a href="#Options">later</a>.
+
+<p>
+Usage of this tool is fairly straightforward: choose the directory (or
+directories) to scan, and the user or group for whom you wish to calculate
+disk usage:
+<pre>
+  diskuse /home /usr /tmp --user=bob
+</pre>
+The <code>--K</code>, <code>--M</code>, and <code>--G</code> options can be
+used to display the disk usage calculated in kilobytes, megabytes, or
+gigabytes, respectively.
+
+<p>
+<hr><br>
+<h2><a name="Options">Options</a></h2>
+The following is the output from running <code>diskuse --help</code>:
+<pre>
+usage: diskuse [options] dir1 dir2 ... dirN
+
+ diskuse calculates the amount of disk space used underneath the given
+ directory (or directories).  Either a --group or a --user option is required.
+ If both are used, only files whose ownership matches both the given name and
+ group will be added to the disk usage sum.
+
+ Options:
+
+  --G          Display the number of bytes in units of gigabytes.  The default
+               number is in bytes.
+
+  --K          Display the number of bytes in units of kilobytes.  The default
+               number is in bytes.
+
+  --M          Display the number of bytes in units of megabytes.  The default
+               number is in bytes.
+
+  --dir-tally  Count the size of directories toward the disk usage sum.  The
+               default is to consider regular files only.
+
+  --group      Count files owned by this group in the disk usage sum.
+
+  --help       Display this message.
+
+  --user       Count files owned by this user in the disk usage sum.
+
+  --verbose    Display diagnostic output while diskuse is running.
+</pre>
+
+<p>
+<hr><br>
+
+Author: <i>$Author: frankie $</i><br>
+Last Updated: <i>$Date: 2003/11/17 15:30:12 $</i><br>
+
+<br><hr>
+
+<font size=2><b><i>
+&copy; Copyright 2000-2002 TJ Saunders<br>
+ All Rights Reserved<br>
+</i></b></font>
+
+<hr><br>
+
+</body>
+</html>
+
