]> git.pld-linux.org Git - packages/courier-imap.git/commitdiff
- outdated.
authorkloczek <kloczek@pld-linux.org>
Sun, 2 Mar 2003 13:55:10 +0000 (13:55 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    courier-imap-1.5.3-myownquery.patch -> 1.3
    courier-imap-1.5.3.20020921-myownquery.patch -> 1.2

courier-imap-1.5.3-myownquery.patch [deleted file]
courier-imap-1.5.3.20020921-myownquery.patch [deleted file]

diff --git a/courier-imap-1.5.3-myownquery.patch b/courier-imap-1.5.3-myownquery.patch
deleted file mode 100644 (file)
index a590da0..0000000
+++ /dev/null
@@ -1,2064 +0,0 @@
-diff -ur courier-imap-1.5.3-orig/authlib/README.authmysql.myownquery courier-imap-1.5.3/authlib/README.authmysql.myownquery
---- courier-imap-1.5.3-orig/authlib/README.authmysql.myownquery        Tue Jan  8 06:01:22 2002
-+++ courier-imap-1.5.3/authlib/README.authmysql.myownquery     Mon Oct 14 01:05:11 2002
-@@ -2,13 +2,18 @@
--          Developer Notes for courier-imap-myownquery.patch
-+                  Developer Notes and Usage Instructions
-+                                  
-+                                  of
-+                                  
-+                     courier-imap-authmysql-myownquery
-+                                  by
-+                      
-+                      Pawel Wilk <siefca@kernel.pl>
--                                                      document version: 1.03
--                                                      author: Pawel Wilk
-@@ -19,75 +24,843 @@
-+ .. table of contents..
-+PREAMBLE
-+PART I - Usage Instructions
-+      1 What's that?
-+      
-+      2 When will I need it?
-+      
-+      3 How does it work?
-+        3.1 configuration variables
-+        3.2 queries
-+        3.3 substitutions
-+        3.4 triggers
-+        3.5 empty default domain name
-+        3.6 whitespaces in queries
-+      
-+      4 Examples of usage
-+        4.1 corporate mail system
-+          4.1.1 database structure
-+          4.1.2 authdaemon configuration
-+        4.2 virtual mail domains provider
-+          4.2.1 database structure
-+          4.2.2 authdaemon configuration
-+
-+PART II - Developer Notes
-+
-+      1 Modifications overview
-+
-+      2 Definitions
-+
-+      3 New data types
-+        3.1 struct var_data
-+        3.2 typedef size_t (*parsefunc)
-+  
-+      4 New functions
-+        4.1 get_variable
-+        4.2 parse_core
-+        4.3 ParsePlugin_counter
-+        4.4 ParsePlugin_builder
-+        4.5 parse_string
-+        4.6 validate_password
-+        4.7 get_localpart
-+        4.8 get_domain
-+        4.9 get_username
-+        4.10 parse_select_clause
-+        4.11 parse_chpass_clause
-+        4.12 auth_mysql_on_trigger
-+        4.13 auth_mysql_on_pass
-+        4.14 auth_mysql_checkpassword
-+      5 Ideas and TODO
--0 What's that?
-+      6 Thanks
--1 Modifications overview
--2 Definitions
--3 New data types
--  3.1 struct var_data
--  3.2 typedef size_t (*parsefunc)
--  
--4 New functions
--  4.1 get_variable
--  4.2 parse_core
--  4.3 ParsePlugin_counter
--  4.4 ParsePlugin_builder
--  4.5 parse_string
--  4.6 validate_password
--  4.7 get_localpart
--  4.8 get_domain
--  4.9 parse_select_clause
--  4.10 parse_chpass_clause
--  
--5 Ideas and TODO
--6 Thanks
-+//////////////////////////////// PREAMBLE /////////////////////////////////////
-+
-+This is README document for "myownquery" patch for Courier's Authdaemon.
-+This document version is 1.36
-+
-+* The patch, which this document describes is developed for Courier-IMAP
-+  version 1.5.3 and the official patch revision is 2.
-+
-+* You can download the patch from the FTP server using URI:
-+
-+ftp://ftp.pld.org.pl/people/siefca/patches/courier/courier-imap-1.5.3-myownquery.patch
-+   it should also be accessible on mirroring servers, which list can be
-+   obtained under: http://www.pld.org.pl/
-+
-+* To know more about getting Courier see http://www.courier-mta.org/
-+
-+* This patch, including the documentation, is released under GNU GPL
-+  license terms. You should look at the COPYING file present in
-+  Courier sources.
-+
-+.
-+.
-+.
-+.
-+.
-+.
-+
-+//////////////////////////////// PART I - Usage ///////////////////////////////
-                   *-----------------------
--                   0 What's that?
-+                   1 What's that?
-                   *-----------------------
--Courier-imap-myownquery.patch allows administrator to set own MySQL queries
--used by authdaemon to authenticate user (including fetchig credentials) and to
--change user's password. It allows to construct SELECT or UPDATE clause in the
--configuration file (authmysqlrc) by adding two new configuration variables:
--MYSQL_SELECT_CLAUSE and MYSQL_CHPASS_CLAUSE. It may be useful in the mail
--environments where there is such a need to have different database structure
--and/or tables scheme than expected by authmysql module.
-+Courier-imap-myownquery's features allow the administrator to set his
-+own MySQL queries used by authdaemon to authenticate a user (including
-+fetchig his credentials) and to change the user's password. It allows
-+one to write a SELECT and UPDATE clause in the configuration file
-+(authmysqlrc) using the new configuration options. It may be useful in
-+mail environments where there is a need to have a different database
-+structure and/or tables scheme than expected by authmysql module.
-+
-+It also implements a small parsing engine for substitution of
-+variables which may appear in the SQL clauses, such as a username or a
-+domain.
--It also implements a small parsing engine for substitution variables which
--may appear in the clauses and are used to put informations like username
--or domain into the right place of a query.
--This patch was created using `diff -Nur` on courier-imap-1.3.12 source.
-+                  *-----------------------
-+                   2 When will I need it?
-+                  *-----------------------
-+
-+ o When you already have some MySQL database filled up with the data
-+    and there is no chance to change the whole structure to make it
-+    work with a standard authmysql table. Typical situation is when
-+    all the
-+    data required to authenticate a user is arranged in more than one
-+    table.
-+
-+ o When you have some great idea how to make the database structure
-+    more efficient due to your needs and your requirements.
-+      
-+ o When doing something 'by-myself' is in your style and you just want
-+    to create your own database, just to feel the pleasure of doing
-+    something original. :)
-+
-+
-+
-+                  *-----------------------
-+                   3 How does it work?
-+                  *-----------------------
-+
-+There are three things which the feature concerns:
-+
-+- fetching clauses from the configuration file
-+- doing substitution replacements inside of SQL clauses
-+- passing prepared query on to the mysql interface funtions
-+
-+3.1 configuration options
-+
-+You can apply your own MySQL queries using a set of the configuration
-+options.  The options you'll need to make the authmysql your slave
-+are:
-+
-+MYSQL_SERVER          (required)
-+MYSQL_USERNAME                (required)
-+MYSQL_PASSWORD                (required)
-+
-+              The server name, userid, and password used to log in.
-+
-+MYSQL_DATABASE (required)
-+
-+              The name of the MySQL database we will open.
-+
-+DEFAULT_DOMAIN (optional)
-+
-+              If DEFAULT_DOMAIN is defined, and someone tries to log
-+              in as 'user', we will look up 'user@DEFAULT_DOMAIN'
-+              instead.
-+
-+USER_DOMAIN_SEPARATORS (optional)
-+
-+              This may contain the set of characters used by parsing
-+              routines to split local part of the virtual mailbox
-+              name from the part which describes the domain name. If
-+              it's not defined the set containing @% is assumed, so
-+              the user can enter either: user@domain or user%domain
-+
-+MYSQL_SELECT_CLAUSE   (required)
-+MYSQL_CHPASS_CLAUSE   (required under some circumstances)
-+
-+              These are the major options you should use. See 3.2
-+              section for more info.
-+
-+ON_PASS_OK_CLAUSE     (optional)
-+ON_PASS_FAIL_CLAUSE   (optional)
-+ON_PASS_CHANGE_CLAUSE (optional)
-+
-+              These are used to do a MySQL query whether user has
-+              passed the authentication verification
-+              (ON_PASS_OK_CLAUSE) or there was the authentication
-+              failure (ON_PASS_FAIL_CLAUSE), or whether user has
-+              changed his password (ON_PASS_CHANGE_CLAUSE).
-+              Query results have no meaning. You can use the same
-+              substitution variables in your query as with
-+              MYSQL_SELECT_CLAUSE. See 3.4 section for more info.
-+
-+The options which have no effect, and may be safetly left blank are:
-+
-+MYSQL_USER_TABLE
-+MYSQL_CRYPT_PWFIELD
-+MYSQL_CLEAR_PWFIELD
-+MYSQL_UID_FIELD
-+MYSQL_GID_FIELD
-+MYSQL_LOGIN_FIELD
-+MYSQL_HOME_FIELD
-+MYSQL_NAME_FIELD
-+MYSQL_MAILDIR_FIELD
-+MYSQL_QUOTA_FIELD
-+MYSQL_WHERE_CLAUSE
-+
-+3.2 queries
-+
-+The feature adds two configuration options (clauses), which are parsed
-+first, and then applied as MySQL queries to MySQL interface
-+routines. These options are: MYSQL_SELECT_CLAUSE and
-+MYSQL_CHPASS_CLAUSE. After each option a number of spaces and/or tabs
-+is allowed, and then MySQL query is expected. For better look, your
-+queries can have line breaks. Each line break should be preceded by
-+the backslash sign. Look into examples chapter (4) to see how it
-+should look like. First clause is used to authenticate a user, and the
-+second to change his password.
-+
-+You should note that a query identified by MYSQL_SELECT_CLAUSE should
-+return fixed number (9) of fields and each field should match the
-+variable expected by authentication routines. These fields are:
-+
-+
-+* username - which is the currently logged user's username (or the
-+             username with domain if you want it)
-+
-+  cryptpw - which is the user's crypted password
-+*
-+  clearpw - which is the user's plaintext password
-+
-+* uid - which is a numerical UID value used as a process's UID when
-+        accessing the mailbox directory
-+
-+* gid - as above, but refers to GID
-+
-+* home - which contains full path to the user's home directory
-+
-+  maildir - which contains the directory name inside the user's home;
-+          treated as INBOX folder when accessing mailbox - if it's
-+          empty then the 'Maildir' string is used
-+
-+quota - which describes a quota size for the mailbox
-+
-+fullname - which may contain the user's fullname
-+
-+(The fields marked by the asterix sign are required and cannot have an
-+ empty results. In case of passwords, at least one of the shown fields
-+ should contain some result.)
-+
-+So, the typical query clause may start with:
-+
-+MYSQL_SELECT_CLAUSE SELECT                                      \
-+ users.username,                                              \
-+ users.cryptpw,                                                       \
-+ users.clearpw,                                               \
-+ domains.uid,                                                 \
-+ domains.gid,                                                 \
-+ users.mailbox_path)                                          \
-+ ''                                                           \ 
-+ domains.quota,                                                       \
-+ ''                                                           \
-+...
-+
-+Note that in this short example we're assuming that we have two tables
-+(users and domains) and INBOX path is always called 'Maildir' and
-+we're not using the fullname field (the query will always return an
-+empty string in its place).
-+
-+Also note that you may discard one of the password fields if you don't
-+want to use an authentication mechanism, which needs it. For example,
-+if you don't want to use MD5-CRAM you may put '' into the place of
-+clearpw (because, for example you're in paranoid mode and you don't
-+even want to keep plain passwords in the database:).
-+
-+3.3 substitutions
-+
-+Substitutions are strings, which may appear in your query, and which
-+have a special meaning. You can also call them substitution
-+variables. If substitution variable is known for a clause context then
-+it is parsed. If it isn't known the error is generated. In the default
-+compilation of authmysql module any substitution variable is declared
-+inside of two substrings - the first is a dollar sign concatenated
-+with opening parenthesis, and the second is a closing parenthesis
-+sign. First symbol identifies beginning of a substitution variable,
-+and the second closes it. The string between the beginning and the
-+closing symbol is called substitution variable's name.
-+
-+When, as I said before, the name is known to the parsing routine the
-+substitution is made and the proper value appears in place of the
-+substitution variable, while passing on the query for later
-+processing.
-+
-+Allowed substitution variables:
-+
-+context: MYSQL_SELECT_CLAUSE, ON_PASS_FAIL_CLAUSE, ON_PASS_OK_CLAUSE,
-+       ON_PASS_CHANGE_CLAUSE
-+
-+$(local_part)                 will be replaced by currently verified user's username
-+                      (without the domain part)
-+
-+$(domain)             will be replaced by currently verified user's domain
-+                      name (if present, or if not present but the
-+                      DEFAULT_DOMAIN was used) or by the empty,
-+                      zero-length
-+                      string if the domain cannot be obtained
-+
-+$(username)           will be replaced by currently verified user's username
-+                      concatenated with the given domain name using
-+                      @ symbol -- if the domiain name cannot be
-+                      obtained (even looking up DEFAULT_DOMAIN) the
-+                      separation sign will not appear and only the
-+                      given username will be presented
-+
-+context: MYSQL_CHPASS_CLAUSE
-+
-+$(local_part)           will be replaced by currently verified user's username
-+                        (without the domain part)
-+
-+$(domain)               will be replaced by currently verified user's domain
-+                        name (if present, or if not present but the
-+                        DEFAULT_DOMAIN was used) or by the empty, zero-length
-+                        string if the domain cannot be obtained
-+
-+$(username)             will be replaced by currently verified user's username
-+                        concatenated with the given domain name using
-+                        @ symbol -- if the domiain name cannot be
-+                        obtained (even by looking up DEFAULT_DOMAIN)
-+                        the separation sign will not appear and only
-+                        the given username will be presented
-+
-+$(newpass)            will be replaced by currently authenticated user's
-+                      new password to set up (plaintext password)
-+
-+$(newpass_crypt)      will be replaced by currently authenticated user's
-+                      new password to set up (MD5 form created from
-+                      entered plain form)
-+
-+3.4 triggers
-+
-+Triggers are MySQL queries, which are performed depending on
-+authentication state. Currently, there are three triggers which you
-+may use. First is called ON_PASS_OK_CLAUSE and it is performed when
-+the authentication succeedes.  The second is called
-+ON_PASS_FAIL_CLAUSE and has the reverse meaning. The third, which name
-+is ON_PASS_CHANGE_CLAUSE is performed whenever user has changed his
-+password.
-+
-+You can declare triggers in the authmysqlrc configuration file. They
-+can be used to arrange some logging facility in the database or just
-+to keep last times of the successful/failed login tries. The typical
-+trigger, which puts last login date into the users' table can look
-+like this:
-+
-+ON_PASS_OK_CLAUSE     UPDATE users SET last_login=CURRENT_TIMESTAMP \
-+                      WHERE username='$(username)';
-+
-+or, if you would like to know about last login failure for users you can try:
-+
-+ON_PASS_FAIL_CLAUSE   UPDATE users SET last_bad_login=CURRENT_TIMESTAMP \
-+                      WHERE username='$(username)';
-+
-+and/or, if you want to know last password changes you can use:
-+
-+ON_PASS_CHANGE_CLAUSE UPDATE users SET pw_change=CURRENT_TIMESTAMP \
-+                      WHERE username='$(username)';
-+
-+Note, that YOU CAN use the triggers even if you aren't using
-+MYSQL_SELECT_CLAUSE. Also note, that if the entered username
-+doesn't match any real user ON_PASS_FAIL_CLAUSE will be simply
-+discarded. To watch brute force attacs against known usernames
-+you have to use log files. ;]
-+
-+3.5 empty default domain name
-+
-+Sometimes happens, that you want to allow user to log in without
-+having a domain name entered and you expect it will be treated as an
-+empty string, neither an error, nor default domain. In that case you
-+should leave DEFAULT_DOMAIN option unset in authmysqlrc file and your
-+database should have empty (not NULL) string fields for users without
-+the domain name specified.
-+
-+3.6 whitespaces in queries
-+
-+In a few examples, here and in authmysqlrc file, I used to put many
-+whitespaces and tabs to make the examples more clear for reader.
-+However, it is recommended to not torture authdaemon's parser in
-+that way and to remove unnecessary characters. ;]
-+
-+For example, the clause:
-+
-+MYSQL_CHPASS_CLAUSE UPDATE                                       \
-+ users                                                           \
-+ SET clearpw='$(newpass)',                                       \
-+     cryptpw='$(newpass_crypt)'                                  \
-+ WHERE username='$(local_part)'                                  \
-+ AND   domain_name='$(domain)'
-+
-+can be safetly rewritten as:
-+
-+MYSQL_CHPASS_CLAUSE UPDATE users \
-+SET clearpw='$(newpass)', cryptpw='$(newpass_crypt)' \
-+WHERE username='$(local_part)' AND domain_name='$(domain)'
-+
-+
-+
-+
-+
-+
-+                  *-----------------------
-+                   4 Examples of usage
-+                  *-----------------------
-+
-+The "ownquery" feature gives you possibility to adapt an
-+authentication query to the database. So the first thing you have to
-+do is to design the database structure you need, whithout being
-+grieved at what structure authentication routines like. You have to
-+take care about four essential things:
-+
-+ o  The database
-+ 
-+ o  The users' data in the database
-+ 
-+ o  The proper directories for keeping virtual mailboxes and a system
-+    user which can read and write them
-+ 
-+ o  The proper MySQL queries in your authmysqlrc configuration file
-+
-+4.1 corporate mail system
-+
-+This example is concerned about a corporate mail system with a small
-+ammount of served virtual domains. The database scheme was derived
-+from tpop3d documentation and modified a bit.
-+
-+4.1.1 database structure
-+
-+Our goal here is to separate the data responsible for keeping mailbox
-+credentials from the data describing domains.
-+
-+Let's create some tables for our example, filled up with an example
-+data:
-+
-+table:          domains
-+
-+purpose:        associates virtual domain with domain name and informations
-+              necessary to access mailboxes withing the domain
-+
-+fields:         domain_name         - fully qualified domain name
-+                path_prefix         - absolute pathname which points to
-+                                      a directory where domain's mailboxes
-+                                      are located
-+                quota               - default quota for each mailbox
-+                uid                 - UID used to work on mailboxes
-+                gid                 - GID used to work on mailboxes
-+              
-+        +----------------+-------------+-----+-----+----------+
-+        | domain_name    | path_prefix | uid | gid | quota    |
-+        +----------------+-------------+-----+-----+----------+
-+        | exampledom.com | /var/mail/x | 555 | 555 | 10000000 |
-+      | pld.org.pl     | /var/mail/p | 556 | 556 | 20000000 |
-+      | pld.net.pl     | /var/mail/p | 556 | 556 | 20000000 |
-+      +----------------+-------------+-----+-----+----------+
-+
-+table:          users
-+
-+purpose:        associates virtual mailbox with user and domain name,
-+              and with informations necessary to access mailbox
-+
-+fields:         username           - user login name (mailbox name)
-+              domain_name          - fully qualified domain name
-+                mailbox_path         - relative pathname for mailbox
-+                                       (will be appended to the path_prefix
-+                                        from domain_auth table to specify
-+                                      user's mailbox location)
-+                cryptpw              - crypted password
-+                plainpw              - plaintext password
-+
-+        +----------+----------------+--------------+------------+--------+
-+      | username | domain_name    | mailbox_path | cryptpw   | plainpw |
-+      +----------+----------------+--------------+-----------+---------+
-+      | siefca   | pld.org.pl     | s/siefca     | $1$fs45.. | dupa.8  |
-+      | siefca   | pld.net.pl     | s/siefca     | $1$fs45.. | dupa.8  |
-+      | f00bar   | exampledom.com | foobar       | $1$g44w.. | secret  |
-+      +----------+----------------+--------------+-----------+---------+ 
-+
-+Using MySQL monitor you can create these tables entering CREATE
-+sequences.  Be sure to connect to the database using administrative
-+MySQL account (usualy: mysql -u mysql -p).
-+
-+--------------------- cut here
-+
-+# Create the database called vmail.
-+
-+CREATE database vmail;
-+
-+# Create an example MySQL user, which can read, write and delete data
-+# from vmail database. Username: vuser Password: secret_password
-+
-+GRANT SELECT,INSERT,UPDATE,DELETE ON vmail.*
-+             TO vuser@localhost
-+             IDENTIFIED BY 'secret_password';
-+
-+FLUSH PRIVILEGES;
-+
-+# Create the tables.
-+
-+use vmail;
-+
-+CREATE TABLE domains (
-+        domain_name           char(255) DEFAULT '',
-+        path_prefix           char(255) DEFAULT '' NOT NULL,
-+        uid                   int(10) unsigned DEFAULT '15000' NOT NULL,
-+        gid                   int(10) unsigned DEFAULT '15000' NOT NULL,
-+        quota                 char(255) DEFAULT '2000000' NOT NULL,
-+        KEY domain_name (domain_name(255))
-+        );
-+
-+CREATE TABLE users (
-+        username              char(128) DEFAULT '' NOT NULL,
-+        domain_name           char(255) DEFAULT '',
-+        mailbox_path          char(255) DEFAULT '' NOT NULL,
-+        cryptpw               char(128) DEFAULT '' NOT NULL,
-+        clearpw               char(128) DEFAULT '' NOT NULL,
-+        KEY username (username(128))
-+        );
-+
-+# Create an example virtual domain entry
-+# name  : exampledom.com
-+# uid   : 555
-+# gid   : 555
-+# path  : /var/mail/x
-+# quota : 10 Megs per mailbox
-+
-+INSERT INTO domains VALUES ('exampledom.com', '/var/mail/x', 555, 555,
-+                            '10000000');
-+
-+# Create an example virtual user entry
-+# username      : siefca
-+# domain name   : exampledom.com
-+# cryptpw       : $1$wIfVZ8uK$qhagYAcIoZpQM83Et7c1e/
-+# clearpw       : dupa.8
-+# mailbox path  : s/siefca
-+
-+INSERT INTO users VALUES ('siefca', 'exampledom.com', 's/siefca',
-+                        '$1$wIfVZ8uK$qhagYAcIoZpQM83Et7c1e/',
-+                        'dupa.8');
-+
-+--------------------- cut here
-+
-+Note: If you would like to have your passwords more safe, then just
-+      omit the clearpw column and put '' into the config-query in
-+      its place while doing SELECT on a database. But be ware -
-+      you'll be unable to use authentication methods which needs it,
-+      like MD5_CRAM.
-+
-+4.1.2 authdaemon configuration
-+
-+When our database is ready we can set up the configuration. :-) Go to
-+authmysqlrc file and edit it.
-+
-+At the beginning we should take care about general informations, which
-+are identifying our database:
-+
-+MYSQL_SERVER            localhost
-+MYSQL_USERNAME          vuser
-+MYSQL_PASSWORD          secret_password
-+MYSQL_DATABASE          vmail
-+
-+Then we should add a clause responsible for authenticating user and
-+fetching credentials:
-+
-+DEFAULT_DOMAIN          exampledom.com
-+
-+MYSQL_SELECT_CLAUSE SELECT                                      \
-+ users.username, users.cryptpw, users.clearpw,                  \
-+ domains.uid, domains.gid,                                      \
-+ CONCAT_WS('/',domains.path_prefix,users.mailbox_path),         \
-+ '', domains.quota, ''                                          \
-+ FROM users, domains                                            \
-+  WHERE domains.domain_name='$(domain)'                         \
-+    AND users.username='$(local_part)'                          \
-+    AND domains.domain_name=users.domain_name
-+
-+
-+Note the '' in the place of field which tells where user's INBOX
-+resides and in place of realname field. You should use '' if you want
-+to put an empty value as a query result for some field.
-+
-+We also should add some configuration for changing user's password:
-+
-+MYSQL_CHPASS_CLAUSE UPDATE                                       \
-+ users                                                           \
-+ SET clearpw='$(newpass)',                                       \
-+     cryptpw='$(newpass_crypt)'                                  \
-+ WHERE username='$(local_part)'                                  \
-+ AND   domain_name='$(domain)'
-+
-+And finally...
-+Create a system user/group and a proper directory structure. In our example:
-+
-+groupadd -g 555 xdomain
-+useradd -u 555 -g 555 xdomain
-+mkdir -p /var/mail/x/s/siefca
-+chmod -R 0770 /var/mail/x
-+maildirmake /var/mail/x/s/siefca/Maildir
-+chown -R xdomain.xdomain /var/mail/x
-+
-+Now, restart the authdaemon and see if it works. Try: telnet 0 pop3
-+
-+and type:
-+
-+USER siefca [ENTER]
-+PASS dupa.8 [ENTER]
-+
-+You should get Ok response. ;)
-+
-+4.2 virtual mail domains provider
-+
-+Let's consider more complicated database scheme, where there is a need
-+to associate a lot of information with the domain name, including
-+registrant information, owner, etc. That implies data separation
-+between domain name, user and domain additional informations (which
-+are unwanted when authentication process takes place). By proper data
-+separation I mean avoiding unwanted redundancy in the database.
-+
-+Currently applied example doesn't care about the update password
-+problem.  This is due to current abilities of MySQL and authdaemon
-+(authmysql).  MySQL doesn't support subsequent SELECTs on UPDATE
-+operation, and authmysql doesn't supports batched queries at the
-+moment.
-+
-+4.2.1 database structure
-+
-+table:                domain_names
-+
-+purpose:      associates domain_id with domain name
-+
-+fields:               domain_name             - fully qualified domain name
-+              domain_id               - domain identifier
-+
-+      +----------------+-----------+
-+      | domain_name    | domain_id |
-+      +----------------+-----------+
-+      | exampledom.com |         1 |
-+      | pld.org.pl     |         2 |
-+      | pld.net.pl     |         2 |
-+      | foobare.net.uk |         3 |
-+      +----------------+-----------+
-+
-+Note, that for pld.org.pl and pld.net.pl the domain identifiers are
-+the same.  We can create a domain aliases in such a way. :)
-+
-+table:                domain_auth
-+
-+purpose:      associates domain_id with authentication credentials
-+              which are common for all users in the virtual domain
-+
-+fields:               domain_id               - domain identifier
-+              path_prefix             - absolute pathname which points to
-+                                        a directory where domain's mailboxes
-+                                        are located
-+              quota                   - default quota for each mailbox
-+              uid                     - UID used to work on mailboxes
-+              gid                     - GID used to work on mailboxes
-+              
-+      +------------+---------------+--------+-------+-------+
-+      | domain_id  | path_prefix   | quota  | uid   | gid   |
-+      +------------+---------------+--------+-------+-------+
-+      |          1 | /var/mail/ex  | 100000 | 15000 | 15000 | 
-+      |          2 | /var/mail/pld | 555500 | 15001 | 15000 |
-+      |          3 | /home/f0/mail |   8000 | 15002 | 15000 |
-+      +------------+---------------+--------+-------+-------+
-+
-+table:                domain_info
-+
-+purpose:      associates domain_id with additional informations
-+
-+fields:               domain_id               - domain identifier
-+              registrant_id           - registrant identifier
-+              nic_handle              - NIC handle
-+              owner_id                - domain's owner identifier
-+              expires                 - domain's expiration date
-+
-+      +------------+---------------+------------+----------+---------+
-+      | domain_id  | registrant_id | nic_handle | owner_id | expires |
-+      +------------+---------------+------------+----------+---------+
-+
-+      (we don't need to say anything more about this table indeed)
-+
-+table:                users
-+
-+purpose:      associates users' identifiers with domains' identifiers
-+              and infers the credentials for various virtual mailboxes
-+
-+fields:               username                - user's login name
-+              domain_id               - domain identifier
-+              cryptpw                 - crypted password
-+              plainpw                 - plaintext password
-+              quota                   - user's mailbox quota
-+                                        (will override quota value set for
-+                                        the whole virtual domain)
-+              path                    - relative pathname for mailbox
-+                                        (will be appended to the path_prefix
-+                                        from domain_auth table to specify
-+                                        user's mailbox location)
-+
-+      +------------+-----------+----------+-----------+-------+------------+
-+      | username   | domain_id | cryptpw  | plainpw   | quota | path       |
-+      +------------+-----------+----------+-----------+-------+------------+
-+      | foobar     |         1 | $1$hlIeE | dupa.8    | NULL  | f/o/foobar |
-+      | breeder    |         2 | $1$TWsdf | ziarno128 | 77777 | brd        |
-+      +------------+-----------+----------+-----------+-------+------------+
-+
-+    (you can add a realname column here, it doesn't fit to my terminal window:)
-+
-+--------------------- cut here
-+
-+# Create the database called vmail.
-+
-+CREATE database vmail;
-+
-+# Create an example MySQL user, which can read, write and delete data
-+# from vmail database. Username: vuser Password: secret_password
-+
-+GRANT SELECT,INSERT,UPDATE,DELETE ON vmail.*
-+           TO vuser@localhost
-+           IDENTIFIED BY 'secret_password';
-+
-+FLUSH PRIVILEGES;
-+
-+# Create the tables.
-+
-+use vmail;
-+
-+CREATE TABLE domain_names (
-+      domain_id             int(10) unsigned NOT NULL,
-+      domain_name           char(255) DEFAULT '' NOT NULL,
-+      KEY domain_name (domain_name(255))
-+      );
-+
-+CREATE TABLE domain_auth (
-+      domain_id             int(10) unsigned DEFAULT 1 NOT NULL,
-+      uid                   int(10) unsigned DEFAULT '15000' NOT NULL,
-+      gid                   int(10) unsigned DEFAULT '15000' NOT NULL,
-+      path_prefix           char(255) DEFAULT '' NOT NULL,
-+      quota                 char(255) DEFAULT '20000000' NOT NULL,
-+      KEY domain_id (domain_id)
-+      );
-+
-+CREATE TABLE users (
-+        username            char(128) DEFAULT '' NOT NULL,
-+      domain_id             int(10) unsigned DEFAULT 1 NOT NULL,
-+        cryptpw               char(128) DEFAULT '' NOT NULL,
-+      plainpw               char(128) DEFAULT '' NOT NULL,
-+        name                  char(128) DEFAULT '' NOT NULL,
-+        quota                 char(255),
-+      path                  char(255) DEFAULT '' NOT NULL,
-+        KEY username (username(128))
-+      );
-+      
-+# Create an example virtual domain entry
-+# id  : 1
-+# name        : exampledom.com
-+# uid : 15000
-+# gid : 15000
-+# path        : /var/mail/example
-+# quota       : 20 Megs per mailbox
-+
-+INSERT INTO domain_names VALUES (1, 'exampledom.com');
-+INSERT INTO domain_auth VALUES (1, '15000', '15000', '/var/mail/example',
-+                              '20000000');
-+
-+# Create an example virtual user entry
-+# username    : siefca
-+# domain id   : 1 (points to exampledom.com)
-+# cryptpw     : $1$wIfVZ8uK$qhagYAcIoZpQM83Et7c1e/
-+# clearpw     : dupa.8
-+# name                : Pawel Wilk
-+# quota               : NULL (we want it to be fetched from domain_auth table)
-+# mailbox path        : s/i/siefca
-+
-+INSERT INTO users VALUES ('siefca', 1, '$1$wIfVZ8uK$qhagYAcIoZpQM83Et7c1e/',
-+                        'dupa.8', 'Pawel Wilk', NULL, 's/i/siefca');
-+
-+--------------------- cut here
-+
-+Ok, we've done what we need. Don't forget to create system user with
-+UID and GID set to 15000, and a directory containing mailboxes (in
-+this case: /var/mail/example) owned by system user I've mentioned
-+above.  There is also necessary to create Maildir folder structure for
-+our user inside the virtual domain directory - you can configure your
-+MTA agent to do such thing when first message arrive or use
-+maildirmake tool, which comes with Courier-IMAP.
-+
-+
-+4.2.2 authdaemon configuration
-+
-+DEFAULT_DOMAIN                exampledom.com
-+
-+MYSQL_SELECT_CLAUSE SELECT                                    \
-+ users.username,                                              \
-+ users.cryptpw,                                                       \
-+ users.plainpw,                                                       \
-+ domain_auth.uid,                                             \
-+ domain_auth.gid,                                             \
-+ CONCAT_WS('/',domain_auth.path_prefix,users.path),           \
-+ '',                                                          \
-+ IFNULL(users.quota, domain_auth.quota),                      \
-+ users.name                                                   \
-+ FROM users, domain_names, domain_auth                                \
-+ WHERE domain_names.domain_name='$(domain)'                   \
-+  AND users.username='$(local_part)'                          \
-+  AND domain_names.domain_id=users.domain_id                  \
-+  AND domain_names.domain_id=domain_auth.domain_id
-+
-+
-+.
-+.
-+.
-+.
-+.
-+.
-+
-+/////////////////////////// PART II - Developer Notes /////////////////////////
-+
-                   *-----------------------
-                    1 Modifications overview
-                   *-----------------------
--Modified files:       authmysqllib.c authmysqlrc
-+Modified files:       authmysqllib.c authmysql.c authmysql.h authmysqlrc
- Each modified set of instructions is marked by my e-mail address:
- siefca@pld.org.pl
--Changes in the current source code are related to:
-+Changes in the source code are related to:
--- sections where the queries are constructed
-+- sections where the queries are constructed [authmysqllib.c]
-   (including memory allocation for the buffers)
-       when MYSQL_SELECT_CLAUSE or MYSQL_CHPASS_CLAUSE is
-@@ -95,17 +868,29 @@
-       passing over current memory allocation and query construction
-       subroutines
-         
--- section where the configuration file is read
-+- section where the configuration file is read [authmysqllib.c]
-       i've had to modify read_env() function to allow line breaks
--      - now each sequence of the backslash as a first character and
-+      -- now each sequence of the backslash as a first character and
-       newline as the second is replaced by two whitespaces while
-       putting into the buffer
--- sections where the query is constructed
-+      i've also added USER_DOMAIN_SEPARATORS configuration option --
-+      it is used by get_localpart(), get_domain() and get_username()
-+      functions, which are described below
-+
-+- sections where the query is constructed [authmysqllib.c]
-       selection is made, depending on configuration variables which
--      are set or not - if own query is used 
-+      are set or not -- if own query is used 
-+
-+- sections where the user is authenticated against the authinfo [authmysql.c]
-+
-+      i've detached a part of code responsible for authentication
-+      against crypted and plain password -- now it is in stub
-+      function called auth_mysql_checkpassword() -- due to obtain
-+      more clean code in auth_mysql_login() and
-+      auth_mysql_changepw() around trigger calling functions
-@@ -123,14 +908,20 @@
- These definitions allows to change substitution marks in an easy way.
- SV_BEGIN_MARK refers to sequence of characters treated as a prefix of
--each substitution variable and SV_END_MARK refers to string which is
--a closing suffix. If the expected substitution variable is called
-+each substitution variable and SV_END_MARK refers to string which is a
-+closing suffix. If the expected substitution variable is called
- 'local_part' (without apostrophes) then '$(local_part)' is a valid
--string representation for SV_BEGIN_MARK set to "$(" and SV_END_MARK to ")".
--MAX_SUBSTITUTION_LEN defines maximal length of a substitution variable's
--identifier (name).
-+string representation for SV_BEGIN_MARK set to "$(" and SV_END_MARK to
-+")".  MAX_SUBSTITUTION_LEN defines maximal length of a substitution
-+variable's identifier (name).
-+
-+The last two definitions (SV_BEGIN_LEN and SV_END_LEN) are just for
-+code simplification.
-+
-+#define         DEF_SEPARATORS_SET      "@%"
--The last two definitions are just for code simplification.
-+The DEF_SEPARATORS_SET directive defines the set of characters, which
-+are treated as separators when splitting local part from the domain.
-@@ -152,10 +943,10 @@
-       size_t value_length;
-       } ;
--This structure holds information needed by parsing routines.
--Using var_data array you may specify a set of string substitutions
--which should be done while parsing a query. Last element in array
--should have all fields set to zero (null). 
-+This structure holds information needed by parsing routines.  Using
-+var_data array you may specify a set of string substitutions which
-+should be done while parsing a query. Last element in array should
-+have all fields set to zero (null).
- name field    - should contain substituted variable name
- value                 - should contain string which replaces it
-@@ -164,9 +955,9 @@
- explanation: size is used to increase speed of calculation proccess
--           value_length is used to cache length of a value during the
--           parsing subroutines - it helps when substitution variable
--           occures more than once within the query
-+           value_length is used to cache length of a value during
-+           the parsing subroutines - it helps when substitution
-+           variable occures more than once within the query
-  
- Example:
-@@ -177,18 +968,19 @@
- };
- In this example we've declared that $(some) in the query should be
--replaced by 'replacement' text, and replacement for $(anotha) will
--be defined in the code before passing on the array pointer to
--the paring function.
-+replaced by 'replacement' text, and replacement for $(anotha) will be
-+set later in the code, before passing on the array pointer to the
-+general parsing function.
- 3.2 typedef size_t (*parsefunc)
- typedef int (*parsefunc)(const char *, size_t, void *);
--This type definition refers to the function pointer, which is used
--to pass plugin functions into the core parsing subroutine. This definition
--is included to simplify the declaration of the parse_core() function.
-+This type definition refers to the function pointer, which is used to
-+pass plugin functions into the core parsing subroutine. This
-+definition is included to simplify the declaration of the parse_core()
-+function.
-@@ -230,6 +1022,10 @@
-       structure of var_data type, which contains variable definition
-       of a given name. It returns NULL on error or failure.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
- 4.2 parse_core
-@@ -285,6 +1081,11 @@
-       This function returns -1 if an error has occured and 0 if
-       everything went good.
-+
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-       
- 4.3 ParsePlugin_counter
-@@ -314,6 +1115,11 @@
-       This function returns the variable size or -1 if an error
-       has occured, 0 if everything went good.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+
- 4.4 ParsePlugin_builder
- NAME
-@@ -333,7 +1139,7 @@
-       type pointer and refers to the (char *) pointer variable.
-       After each call it shifts the value of pointer variable (char *)
-       incrementing it by len bytes. Be careful when using this function
--      - its changes the given pointer value. Always operate on an
-+      - it changes the given pointer value. Always operate on an
-       additional pointer type variable when passing it as the third
-       argument.
-@@ -342,6 +1148,10 @@
-       This function returns the variable size or -1 if an error
-       has occured, 0 if everything went good.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
- 4.5 parse_string
- NAME
-@@ -353,7 +1163,7 @@
- DESCRIPTION
--      This function parses the string pointed with source according to the
-+      This function parses the string pointed to by source according to the
-       replacement instructions set in var_data array, which is passed with
-       its pointer vdt. It produces changed string located in newly allocated
-       memory area.
-@@ -377,6 +1187,10 @@
-       Function returns pointer to the result buffer or NULL
-       if an error has occured.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
- WARNINGS
-       This function allocates some amount of memory using standard
-@@ -405,6 +1219,10 @@
-       It returns a pointer to the static buffer which contains
-       validated password string or NULL if an error has occured.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
- 4.7 get_localpart
-@@ -414,20 +1232,28 @@
- SYNOPSIS
--      static const char *get_localpart (const char *username);
-+      static const char *get_localpart (const char *username,
-+                                        const char *separators);
- DESCRIPTION
-       This function detaches local part of an e-mail address
-       from string pointed with username and puts it to the
-       buffer of the fixed length. All necessary cleaning is
--      made on the result string.
-+      made on the result string. String pointed with separators
-+      refers to a set of characters, which are treated as
-+      separation signs between local part and a domain.
- RETURN VALUE
-       Pointer to the static buffer containing local part or
-       NULL if there was some error.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+
- 4.8 get_domain
-@@ -438,24 +1264,67 @@
- SYNOPSIS
-       static const char *get_domain (const char *username, 
--                                     const char *defdomain);
-+                                     const char *defdomain,
-+                                     const char *separators);
- DESCRIPTION
-         This function detaches domain part of an e-mail address
-       from string pointed with username and puts it to the
-       buffer of the fixed length. All necessary cleaning is
--      made on the result string. If function cannot find domain
--      part in the string the string pointed by defdomain is
--      used instead.
-+      made on the result string. If the function cannot find a domain
-+      part in the string then the string pointed to by defdomain is
-+      used instead. If this function cannot find a domain part
-+      as well as it cannot obtain the default domain (it's empty string
-+      or the defdomain pointer is NULL) the returned result string is an
-+      empty string. The string pointed with separators refers to a set
-+      of characters, which are treated as separation signs between local
-+      part and a domain.
- RETURN VALUE
-         Pointer to the static buffer containing domain name or
-       NULL if there was some error.
-+FILES
-+
-+      authlib/authmysqllib.c
--4.9 parse_select_clause
-+
-+4.9 get_username
-+
-+NAME
-+
-+      get_username
-+
-+SYNOPSIS
-+
-+      static const char *get_username (const char *username,
-+                                       const char *domainname);
-+
-+DESCRIPTION
-+
-+      This function concatenates the localpart with a domain name
-+      using the @ symbol. If the domain is empty or NULL the result
-+      comes without binding symbol.
-+
-+RETURN VALUE
-+
-+        Pointer to the static buffer containing output string or
-+        NULL if there was some error.
-+
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+WARNINGS
-+
-+      This function does not any string cleaning, nor default domain
-+      checking. It is designed to work on results of get_localpart() and
-+      get_domain().
-+
-+
-+4.10 parse_select_clause
- NAME
-@@ -465,23 +1334,34 @@
-       static char *parse_select_clause (const char *clause,
-                                         const char *username,
--                                        const char *defdomain);
-+                                        const char *defdomain
-+                                        const char *separators_set);
- DESCRIPTION
-       This function is a simple wrapper to the parse_string()
-       function. It parses a query pointed by caluse. username
--      and defdomain strings are used to replace corresponding
--      substitution strings if present in the query: $(local_part)
--      and $(domain).
-+      and defdomain strings are used to create corresponding
-+      substitution strings if present in the query: $(local_part),
-+      $(domain), and $(username). Note, that username parameter
-+      may contain 'user@domain' form here, so the call to
-+      get_localpart() and get_domain() function will split it
-+      into two parts, then calling get_username() function will join
-+      it again using the @ symbol. This trick is wanted as long as
-+      we'd like to have possibility to split the local part from the
-+      domain by using dynamic symbols set. The separators_set is
-+      passed to get_localpart() and get_domain() invocations.
-       
--
- RETURN VALUE
-       Same as parse_string().
-+FILES
-+
-+      authlib/authmysqllib.c
--4.10 parse_chpass_clause
-+
-+4.11 parse_chpass_clause
- NAME
-@@ -492,6 +1372,7 @@
-         static char *parse_chpass_clause (const char *clause,
-                                           const char *username,
-                                           const char *defdomain,
-+                                        const char *separators_set,
-                                         const char *newpass,
-                                         const char *newpass_crypt);
-                                                                   
-@@ -502,12 +1383,115 @@
-       defdomain, newpass and newpass_crypt strings are used to
-       replace corresponding substitution strings if present in
-       the query: $(local_part), $(domain), $(newpass),
--      $(newpass_crypt).
-+      $(newpass_crypt). The separators_set is passed to
-+      get_localpart() and get_domain() functions as described in the
-+      entry for parse_select_clause().
- RETURN VALUE
-       Same as parse_string().
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+
-+4.12 auth_mysql_on_trigger
-+
-+NAME
-+
-+      auth_mysql_on_trigger
-+
-+SYNOPSIS
-+
-+      int auth_mysql_on_trigger (const char *clause_name,
-+                                 const char *username);
-+
-+DESCRIPTION
-+
-+      This function is responsible for calling out the MySQL queries
-+      depending on which authentication state was reached.
-+
-+      The clause_name should contain the name of a clause, which can
-+      be found in the configuration file, and the username is simply
-+      the string used as username (including the domain if entered).
-+
-+      This function reads DEFAULT_DOMAIN and USER_DOMAIN_SEPARATORS
-+      from the configuration file using read_env(), then it uses
-+      parse_select_clause() to parse the query obtained using
-+      read_env(clause_name), and then it calls querying subroutines
-+      to perform the action.
-+
-+RETURN VALUE
-+
-+      This function returns 0 on success and -1 on failure. The
-+      query results are simply discarded. If a trigger's clause is
-+      not defined in the configuration file the 1 is returned and
-+      function silently ends its work.
-+
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+
-+4.13 auth_mysql_on_pass
-+
-+NAME
-+
-+      auth_mysql_on_pass
-+
-+SYNOPSIS
-+
-+      static int auth_mysql_on_pass(const char *clause,
-+                                    struct authmysqluserinfo *authinfo);
-+
-+DESCRIPTION
-+
-+      This function is responsible for invoking trigger MySQL
-+      clauses whenever user is authenticated or not.
-+      This is a stub function, which calls auth_mysql_on_trigger().
-+      Firstly, it does a simple checks in authinfo structure --
-+      it looks for a valid username field. If username is not set
-+      or it's empty the fuction does nothing. This behavior follows
-+      the need, that if there wasn't any valid username then we
-+      shouldn't touch the database.
-+
-+RETURN VALUE
-+
-+      It returns 0 in case everything went fine, -1 if there was some
-+      error.
-+
-+FILES
-+
-+      authlib/authmysql.c
-+
-+
-+4.14 auth_mysql_checkpassword
-+
-+NAME
-+      auth_mysql_checkpassword
-+
-+SYNOPSIS
-+
-+      static int auth_mysql_checkpassword(struct authmysqluserinfo *authinfo,                                                                                                          const char *pass);
-+      
-+DESCRIPTION
-+
-+      This function is a wrapper, which checks user's entered
-+      password against one found in a database. Function tries to
-+      authenticate user against his crypted password and if it's
-+      impossible it tries the plain form -- by impossible we mean
-+      the authinfo->cryptpw set to NULL.
-+
-+RETURN VALUE
-+
-+      Function returns 0 if the password was correct, -1 if user
-+      applied bad password of the username wasn't found.
-+
-+FILES
-+
-+      authlib/authmysql.c
-+
-@@ -516,15 +1500,10 @@
-                    5 Ideas and TODO
-                   *------------------------
--- solve problem with fixed buffer length of local part and the domain part
--  strings after split                                         (problem?)
- - allow admin to set a group name instead of numerical group id
- - allow admin to set a username instead of numerical user id
--
--- add clauses:
--
--  - MYSQL_PRESELECT_CLAUSE (query which comes before MYSQL_SELECT_CLAUSE)
--  - MYSQL_POSTSELECT_CLAUSE (query which comes after MYSQL_SELECT_CLAUSE)
-+- put the parsing routines into separate files to make possible of sharing it
-+  by more authentication modules
-@@ -534,10 +1513,20 @@
-                    6 Thanks
-                   *------------------------
--At the beginning this patch was messy indeed. :> I would like to thank
--Sam Varshavchik for pointing me a lot how to make it more fast and solid.
--I would also thank Philip Hazel, Chris Lightfoot and Mike Bremford which
--by their software capabilities inspired me to write it.
-+At the beginning the patch was messy indeed. :> I would like to thank:
-----------------------------------------------------------------------------
-+Sam Varshavchik
-+  for pointing me a lot, how to make it more fast and solid
-+          
-+Philip Hazel, Chris Lightfoot, Mike Bremford
-+  which by their software's capabilities inspired me to write it
-+              
-+Oliver Oblasnik
-+  which remainded me to make the documentation more friendly for
-+  those who are not programmers and just want to use it
-+  
-+Jacek Surazski
-+  for reviewing this document just before it was published
-+---------------------------------------------------------------------------
-+                                Any comments and suggestions are welcome.
-diff -ur courier-imap-1.5.3-orig/authlib/authmysql.c courier-imap-1.5.3/authlib/authmysql.c
---- courier-imap-1.5.3-orig/authlib/authmysql.c        Sun Jun 24 01:42:05 2001
-+++ courier-imap-1.5.3/authlib/authmysql.c     Sun Oct 13 23:12:06 2002
-@@ -19,7 +19,47 @@
- #include      "authmysql.h"
- #include      "authstaticlist.h"
--static const char rcsid[]="$Id$";
-+static const char rcsid[]="$Id$";
-+
-+/* siefca@pld.org.pl */
-+static int auth_mysql_on_pass(const char *clause, struct authmysqluserinfo *authinfo)
-+{
-+      if (authinfo->username && *(authinfo->username)!='\0') /* do it if user was found */
-+      {
-+              if (auth_mysql_on_trigger(clause, authinfo->username))
-+              {
-+                      return (-1); /* MySQL error or something critical.. */
-+              }
-+      }
-+  
-+      return (0);
-+}
-+
-+/* siefca@pld.org.pl */
-+static int auth_mysql_checkpassword(struct authmysqluserinfo *authinfo,
-+                                  const char *pass)
-+{
-+      if (authinfo->cryptpw)
-+      {
-+              if (authcheckpassword(pass,authinfo->cryptpw))
-+              {
-+                      return (-1); /* User/Password not found. */
-+              }
-+      }
-+      else if (authinfo->clearpw)
-+      {
-+              if (strcmp(pass, authinfo->clearpw))
-+              {
-+                      return (-1);
-+              }
-+      }
-+      else
-+      {
-+              return (-1);
-+      }
-+    
-+      return (0);
-+}
- static char *auth_mysql_login(const char *service, char *authdata,
-       int issession,
-@@ -46,26 +86,23 @@
-               return (0);
-       }
--      if (authinfo->cryptpw)
-+      /* siefca@pld.org.pl */
-+      if (auth_mysql_checkpassword(authinfo,pass))
-       {
--              if (authcheckpassword(pass,authinfo->cryptpw))
--              {
-+              if (auth_mysql_on_pass("ON_PASS_FAIL_CLAUSE", authinfo))
-+                      errno=EACCES;
-+              else
-                       errno=EPERM;
--                      return (0);     /* User/Password not found. */
--              }
--      }
--      else if (authinfo->clearpw)
--      {
--              if (strcmp(pass, authinfo->clearpw))
--              {
--                      errno=EPERM;
--                      return (0);
--              }
-+          
-+              return(0);
-       }
-       else
-       {
--              errno=EPERM;
--              return (0);             /* Username not found */
-+              if (auth_mysql_on_pass("ON_PASS_OK_CLAUSE", authinfo))
-+              {
-+                      errno=EACCES;
-+                      return(0);
-+              }
-       }
-       if (callback_func == 0)
-@@ -149,26 +186,23 @@
-               return (-1);
-       }
--      if (authinfo->cryptpw)
-+      /* siefca@pld.org.pl */
-+      if (auth_mysql_checkpassword(authinfo, pass))
-       {
--              if (authcheckpassword(pass,authinfo->cryptpw))
--              {
--                      errno=EPERM;
--                      return (-1);    /* User/Password not found. */
--              }
--      }
--      else if (authinfo->clearpw)
--      {
--              if (strcmp(pass, authinfo->clearpw))
--              {
-+              if (auth_mysql_on_pass("ON_PASS_FAIL_CLAUSE", authinfo))
-+                      errno=EACCES;
-+              else
-                       errno=EPERM;
--                      return (-1);
--              }
-+
-+              return(-1);
-       }
-       else
-       {
--              errno=EPERM;
--              return (-1);
-+              if (auth_mysql_on_pass("ON_PASS_OK_CLAUSE", authinfo))
-+              {
-+                      errno=EACCES;
-+                      return(-1);
-+              }
-       }
-       if (auth_mysql_setpass(user, newpass))
-@@ -176,6 +210,14 @@
-               errno=EPERM;
-               return (-1);
-       }
-+      
-+      /* siefca@pld.org.pl */
-+      if (auth_mysql_on_pass("ON_PASS_CHANGE_CLAUSE", authinfo))
-+      {
-+          errno=EACCES;
-+          return (-1);
-+      }
-+
-       return (0);
- }
-@@ -314,7 +356,7 @@
- #endif
- char *auth_mysql(const char *service, const char *authtype, char *authdata,
--              int issession,
-+               int issession,
-       void (*callback_func)(struct authinfo *, void *), void *callback_arg)
- {
-       if (strcmp(authtype, AUTHTYPE_LOGIN) == 0)
-diff -ur courier-imap-1.5.3-orig/authlib/authmysql.h courier-imap-1.5.3/authlib/authmysql.h
---- courier-imap-1.5.3-orig/authlib/authmysql.h        Mon Aug  6 05:12:39 2001
-+++ courier-imap-1.5.3/authlib/authmysql.h     Sat Sep 28 00:01:07 2002
-@@ -21,6 +21,7 @@
-       } ;
- extern struct authmysqluserinfo *auth_mysql_getuserinfo(const char *);
-+extern int auth_mysql_on_trigger (const char *clause_name, const char *username);
- extern void auth_mysql_cleanup();
- extern int auth_mysql_setpass(const char *, const char *);
-diff -ur courier-imap-1.5.3-orig/authlib/authmysqllib.c courier-imap-1.5.3/authlib/authmysqllib.c
---- courier-imap-1.5.3-orig/authlib/authmysqllib.c     Wed May 29 19:24:03 2002
-+++ courier-imap-1.5.3/authlib/authmysqllib.c  Sun Oct 13 22:58:09 2002
-@@ -23,6 +23,8 @@
- #define               SV_END_MARK             ")"
- #define               SV_BEGIN_LEN            ((sizeof(SV_BEGIN_MARK))-1)
- #define               SV_END_LEN              ((sizeof(SV_END_MARK))-1)
-+#define               DEF_SEPARATORS_SET      "@%"
-+
- static const char rcsid[]="$Id$";
-@@ -268,7 +270,7 @@
-                        SV_BEGIN_MARK
-                        "%.*s"
-                        SV_END_MARK
--                       "\n", len, begin);
-+                       "\n", (int) len, begin);
-       
-       return NULL;
- }
-@@ -364,14 +366,14 @@
-               t_size  = t_end-t_begin+1;/* text field length              */
-               /* work on text */
--              if ( (outfn (t_begin, t_size, result)) == -1 )
-+              if ( (outfn (t_begin, t_size, result)))
-                       return -1;
-               
-               /* work on variable */
-               v_ptr = get_variable (v_begin, v_size, vdt);
-               if (!v_ptr) return -1;
-               
--              if ( (outfn (v_ptr->value, v_ptr->value_length, result)) == -1 )
-+              if ( (outfn (v_ptr->value, v_ptr->value_length, result)))
-                       return -1;
-               
-               q = e + 1;
-@@ -379,7 +381,7 @@
-       /* work on last part of text if any */
-       if (*q != '\0')
--              if ( (outfn (q, strlen(q), result)) == -1 )
-+              if ( (outfn (q, strlen(q), result)))
-                       return -1;
-       return 0;
-@@ -426,21 +428,45 @@
-               return NULL;
-       }       
-       *pass_buf = '\0';
--      
-+
-       return output_buf;
- }
- /* siefca@pld.org.pl */
--static const char *get_localpart (const char *username)
-+static const char *get_username (const char *username, const char *domainname)
-+{
-+size_t u_len;
-+char *p;
-+static char   username_buf[400];
-+
-+      if (!username || *username == '\0') return NULL;
-+      u_len=strlen(username);
-+      if (( u_len + (domainname ? strlen(domainname) : 0)
-+          ) > 397) return NULL;
-+
-+      strcpy (username_buf, username);
-+      if (domainname && *domainname != '\0')
-+        {
-+          p = username_buf + u_len;
-+          *p='@'; p++;
-+          strcpy(p, domainname);
-+        }
-+      
-+      return (username_buf);
-+}
-+
-+/* siefca@pld.org.pl */
-+static const char *get_localpart (const char *username, const char *separators)
- {
- size_t                lbuf    = 0;
- const char    *l_end, *p;
- char          *q;
- static char   localpart_buf[130];
-       
--      if (!username || *username == '\0')     return NULL;
-+      if (!username || *username == '\0' ||
-+          !separators || *separators == '\0') return NULL;
-       
--      p = strchr(username,'@');
-+      p = strpbrk (username, separators);
-       if (p)
-       {
-               if ((p-username) > 128)
-@@ -469,21 +495,27 @@
- }
- /* siefca@pld.org.pl */
--static const char *get_domain (const char *username, const char *defdomain)
-+static const char *get_domain (const char *username, const char *defdomain,
-+                             const char *separators)
- {
- static char   domain_buf[260];
- const char    *p;
- char          *q;
-       
--      if (!username || *username == '\0')     return NULL;
--      p = strchr(username,'@');
-+      if (!username || *username == '\0' ||
-+          !separators || *separators == '\0') return NULL;
-+      
-+      p = strpbrk (username, separators);
-       
-       if (!p || *(p+1) == '\0')
-       {
--              if (defdomain && *defdomain)
-+              if (defdomain && *defdomain != '\0')
-                       return defdomain;
-               else
--                      return NULL;
-+                {
-+                  *domain_buf = '\0';
-+                  return domain_buf;
-+                }
-       }
-       p++;
-@@ -531,20 +563,25 @@
- /* siefca@pld.org.pl */
- static char *parse_select_clause (const char *clause, const char *username,
--                                const char *defdomain)
-+                                const char *defdomain,
-+                                const char *separators_set)
- {
- static struct var_data vd[]={
-           {"local_part",      NULL,   sizeof("local_part"),   0},
-           {"domain",          NULL,   sizeof("domain"),       0},
-+          {"username",        NULL,   sizeof("username"),     0},
-           {NULL,              NULL,   0,                      0}};
--      if (clause == NULL || *clause == '\0' ||
--          !username || *username == '\0')
-+      if (!clause || !username || !separators_set ||
-+          *clause == '\0' || *username == '\0' ||
-+          *separators_set == '\0')
-               return NULL;
--      
--      vd[0].value     = get_localpart (username);
--      vd[1].value     = get_domain (username, defdomain);
--      if (!vd[0].value || !vd[1].value)
-+
-+      vd[0].value     = get_localpart (username, separators_set);
-+      vd[1].value     = get_domain (username, defdomain, separators_set);
-+      vd[2].value     = get_username (vd[0].value, vd[1].value);
-+
-+      if (!vd[0].value || !vd[1].value || !vd[2].value)
-               return NULL;
-       
-       return (parse_string (clause, vd));
-@@ -552,12 +589,15 @@
- /* siefca@pld.org.pl */
- static char *parse_chpass_clause (const char *clause, const char *username,
--                                const char *defdomain, const char *newpass,
-+                                const char *defdomain,
-+                                const char *separators_set,
-+                                const char *newpass,
-                                 const char *newpass_crypt)
- {
- static struct var_data vd[]={
-           {"local_part",      NULL,   sizeof("local_part"),           0},
-           {"domain",          NULL,   sizeof("domain"),               0},
-+          {"username",        NULL,   sizeof("username"),             0},
-           {"newpass",         NULL,   sizeof("newpass"),              0},
-           {"newpass_crypt",   NULL,   sizeof("newpass_crypt"),        0},
-           {NULL,              NULL,   0,                              0}};
-@@ -565,19 +605,81 @@
-       if (clause == NULL || *clause == '\0'           ||
-           !username || *username == '\0'              ||
-           !newpass || *newpass == '\0'                ||
-+          !separators_set || *separators_set == '\0'  ||
-           !newpass_crypt || *newpass_crypt == '\0')   return NULL;
--      vd[0].value     = get_localpart (username);
--      vd[1].value     = get_domain (username, defdomain);
--      vd[2].value     = validate_password (newpass);
--      vd[3].value     = validate_password (newpass_crypt);
-+      vd[0].value     = get_localpart (username, separators_set);
-+      vd[1].value     = get_domain (username, defdomain, separators_set);
-+      vd[3].value     = get_username (vd[0].value, vd[1].value);
-+      vd[4].value     = validate_password (newpass);
-+      vd[5].value     = validate_password (newpass_crypt);
-       
-       if (!vd[0].value || !vd[1].value ||
--          !vd[2].value || !vd[3].value)       return NULL;
-+          !vd[2].value || !vd[3].value ||
-+          !vd[4].value || !vd[5].value)       return NULL;
-       return (parse_string (clause, vd));
- }
-+/* siefca@pld.org.pl */
-+int auth_mysql_on_trigger (const char *clause_name, const char *username)
-+{
-+char          *querybuf       =NULL;
-+const char    *separators_set =NULL,
-+              *defdomain      =NULL,
-+              *on_clause      =NULL;
-+MYSQL_RES     *result;
-+
-+      if (!clause_name || *clause_name == '\0')
-+        return (-1);
-+      
-+      on_clause = read_env (clause_name);
-+      if (!on_clause || *on_clause == '\0')
-+        return (0); /* ok! not in use */
-+
-+      defdomain = read_env ("DEFAULT_DOMAIN");        
-+      separators_set = read_env ("USER_DOMAIN_SEPARATORS");
-+      if (!defdomain) defdomain = "";
-+      if (!separators_set || *separators_set == '\0')
-+              separators_set = DEF_SEPARATORS_SET;
-+      
-+      querybuf = parse_select_clause (on_clause,
-+                                      username,
-+                                      defdomain,
-+                                      separators_set);
-+      
-+      if (!querybuf)  return (-1);
-+
-+      if (mysql_query (mysql, querybuf))
-+      {
-+              /* <o.blasnik@nextra.de> */
-+
-+              auth_mysql_cleanup();
-+
-+              if (do_connect())
-+              {
-+                      free(querybuf);
-+                      return (-1);
-+              }
-+
-+              if (mysql_query (mysql, querybuf))
-+              {
-+                      free(querybuf);
-+                      auth_mysql_cleanup();
-+                      /* Server went down, that's OK,
-+                      ** try again next time.
-+                      */
-+                      return (-1);
-+              }
-+      }
-+      free(querybuf);
-+      result = mysql_store_result(mysql);
-+      if (result) mysql_free_result(result);
-+      
-+      return (0);
-+}
-+
-+
- struct authmysqluserinfo *auth_mysql_getuserinfo(const char *username)
- {
- const char *user_table        =NULL;
-@@ -596,6 +698,7 @@
-           *gid_field          =NULL,
-           *quota_field        =NULL,
-           *where_clause       =NULL,
-+          *separators_set     =NULL,
-           *select_clause      =NULL; /* siefca@pld.org.pl */
- static const char query[]=
-@@ -704,7 +807,15 @@
-       else
-       {
-               /* siefca@pld.org.pl */
--              querybuf=parse_select_clause (select_clause, username, defdomain);
-+              separators_set = read_env ("USER_DOMAIN_SEPARATORS");
-+
-+              if (!separators_set || *separators_set == '\0')
-+                      separators_set = DEF_SEPARATORS_SET;
-+
-+              querybuf = parse_select_clause (select_clause,
-+                                              username,
-+                                              defdomain,
-+                                              separators_set);
-               if (!querybuf) return 0;
-       }
-@@ -788,6 +899,7 @@
-                   *where_clause       =NULL,
-                   *user_table         =NULL,
-                   *login_field        =NULL,
-+                  *separators_set     =NULL,  
-                   *chpass_clause      =NULL; /* siefca@pld.org.pl */
-       if (!mysql)
-@@ -837,13 +949,18 @@
-       }
-       else
-       {
-+                separators_set = read_env ("USER_DOMAIN_SEPARATORS");
-+              
-+              if (!separators_set || *separators_set == '\0')
-+                      separators_set = DEF_SEPARATORS_SET;
-+              
-               sql_buf=parse_chpass_clause(chpass_clause,
-                                           user,
-                                           defdomain,
-+                                          separators_set,
-                                           pass,
-                                           newpass_crypt_ptr);
-       }
--      
-       if (!sql_buf)
-       {
-diff -ur courier-imap-1.5.3-orig/authlib/authmysqlrc courier-imap-1.5.3/authlib/authmysqlrc
---- courier-imap-1.5.3-orig/authlib/authmysqlrc        Thu Apr  4 06:36:29 2002
-+++ courier-imap-1.5.3/authlib/authmysqlrc     Mon Oct 14 00:02:59 2002
-@@ -1,4 +1,4 @@
--##VERSION: $Id$
-+##VERSION: $Id$
- #
- # Copyright 2000 Double Precision, Inc.  See COPYING for
- # distribution information.
-@@ -141,65 +141,99 @@
- #
- # MYSQL_WHERE_CLAUSE  server='mailhost.example.com'
--##NAME: MYSQL_SELECT_CLAUSE:0
--#
--# (EXPERIMENTAL)
--# This is optional, MYSQL_SELECT_CLAUSE can be set when you have a database,
--# which is structuraly different from proposed. The fixed string will
--# be used to do a SELECT operation on database, which should return fields
--# in order specified bellow:
-+##NAME: USER_DOMAIN_SEPARATORS:0
- #
--# username, cryptpw, uid, gid, clearpw, home, maildir, quota, fullname
-+# This is optional. Using this option you can set the set of characters
-+# which are treated as separators when splitting entered username into the
-+# local part and the domain name. If it's not set the defaults @% are used,
-+# so the user can authenticate using user@domain or user%domain form.
-+# See README.authmysql.myownquery for more information
- #
--# Enabling this option causes ignorance of any other field-related
--# options, excluding default domain.
-+# USER_DOMAIN_SEPARATORS      @%+
-+
-+##NAME: MYSQL_SELECT_CLAUSE:0
- #
--# There are two variables, which you can use. Substitution will be made
--# for them, so you can put entered username (local part) and domain name
--# in the right place of your query. These variables are:
--#             $(local_part) and $(domain)
-+# This is optional, MYSQL_SELECT_CLAUSE can be set when you have a database,
-+# which is structuraly different from proposed. You can type here your MySQL
-+# query, which will be used to fetch user's credentials, and which should
-+# return fields in order specified bellow:
-+#
-+# username, cryptpw, clearpw, uid, gid, home, maildir, quota, fullname
-+#
-+# Enabling this option causes ignorance of any other field-related options.
-+#
-+# There also are variables, which you can use. Substitution will be made
-+# for them, so you can pass currently entered username and a domain name
-+# up to the right place within your query. These variables are:
-+# $(local_part) , $(domain) , $(username)
- #
- # If a $(domain) is empty (not given by the remote user) the default domain
--# name is used in its place.
--#
--# This example is a little bit modified adaptation of vmail-sql
--# database scheme:
--#
--# MYSQL_SELECT_CLAUSE SELECT popbox.local_part,                       \
--#                     CONCAT('{MD5}', popbox.password_hash),          \
--#                     popbox.clearpw,                                 \
--#                     domain.uid,                                     \
--#                     domain.gid,                                     \
--#                     CONCAT(domain.path, '/', popbox.mbox_name),     \
--#                     '',                                             \
--#                     domain.quota,                                   \
--#                     '',                                             \
--#                     FROM popbox, domain                             \
--#                     WHERE popbox.local_part = '$(local_part)'       \
--#                     AND popbox.domain_name = '$(domain)'            \
--#                     AND popbox.domain_name = domain.domain_name
--#
-+# name is used in its place. $(username) is a local part concatenated with
-+# domain name using symbol defined in USER_DOMAIN_CONCAT or '@' if this option
-+# is not set.
-+# See README.authmysql.myownquery for more information
-+#
-+# MYSQL_SELECT_CLAUSE SELECT                                  \
-+# users.username, users.cryptpw, users.clearpw,                       \
-+# domains.uid, domains.gid,                                   \
-+# CONCAT_WS('/',domains.path_prefix,users.mailbox_path),      \
-+# '', domains.quota, ''                                               \
-+# FROM users, domains                                         \
-+#  WHERE domains.domain_name='$(domain)'                      \
-+#    AND users.username='$(local_part)'                               \
-+#    AND domains.domain_name=users.domain_name
-+
- ##NAME: MYSQL_CHPASS_CLAUSE:0
- #
--# (EXPERIMENTAL)
- # This is optional, MYSQL_CHPASS_CLAUSE can be set when you have a database,
--# which is structuraly different from proposed. The fixed string will
--# be used to do an UPDATE operation on database. In other words, it is
--# used, when changing password.
-+# which is structuraly different from proposed. You can use it to set up
-+# a MySQL query used to change user's password.
- #
- # There are four variables, which you can use. Substitution will be made
--# for them, so you can put entered username (local part) and domain name
--# in the right place of your query. There variables are:
--#     $(local_part) , $(domain) , $(newpass) , $(newpass_crypt)
-+# for them, so you can put the currently entered username and the domain name
-+# in the right place of your query. These variables are:
-+# $(local_part) , $(domain) , $(username) , $(newpass) , $(newpass_crypt)
- #
- # If a $(domain) is empty (not given by the remote user) the default domain
--# name is used in its place.
--# $(newpass) contains plain password
--# $(newpass_crypt) contains its crypted form
--#
--# MYSQL_CHPASS_CLAUSE UPDATE  popbox                                  \
--#                     SET     clearpw='$(newpass)',                   \
--#                             password_hash='$(newpass_crypt)'        \
--#                     WHERE   local_part='$(local_part)'              \
--#                     AND     domain_name='$(domain)'
--#
-+# name is used in its place. $(newpass) contains plain password and
-+# $(newpass_crypt) contains its crypted form.
-+# See README.authmysql.myownquery for more information
-+#
-+# MYSQL_CHPASS_CLAUSE UPDATE users            \
-+# SET clearpw='$(newpass)',                   \
-+#     cryptpw='$(newpass_crypt)'              \
-+# WHERE username='$(local_part)'              \
-+# AND domain_name='$(domain)'
-+
-+##NAME: ON_PASS_OK_CLAUSE:0
-+#
-+# This is optional, ON_PASS_OK_CLAUSE is a trigger -- the query
-+# is performed each time user has successfuly logged in.
-+# See README.authmysql.myownquery for more information
-+#
-+# ON_PASS_OK_CLAUSE           UPDATE users                            \
-+#                             SET last_ok=CURRENT_TIMESTAMP           \
-+#                             WHERE username='$(local_part)'          \
-+#                             AND domain_name='$(domain)'
-+
-+##NAME: ON_PASS_FAIL_CLAUSE:0
-+#
-+# This is optional, ON_PASS_FAIL_CLAUSE is a trigger -- the query
-+# is performed each time user has NOT logged in, cause of bad password.
-+# See README.authmysql.myownquery for more information
-+#
-+# ON_PASS_FAIL_CLAUSE         UPDATE users                            \
-+#                             SET last_fail=CURRENT_TIMESTAMP         \
-+#                             WHERE username='$(local_part)'          \
-+#                             AND domain_name='$(domain)'
-+
-+##NAME: ON_PASS_CHANGE_CLAUSE:0
-+#
-+# This is optional, ON_PASS_CHANGE_CLAUSE is a trigger -- the query
-+# is performed each time user has successfuly changed his password.
-+# See README.authmysql.myownquery for more information
-+#
-+# ON_PASS_CHANGE_CLAUSE               UPDATE users                            \
-+#                             SET pw_change=CURRENT_TIMESTAMP         \
-+#                             WHERE username='$(local_part)'          \
-+#                             AND domain_name='$(domain)'
diff --git a/courier-imap-1.5.3.20020921-myownquery.patch b/courier-imap-1.5.3.20020921-myownquery.patch
deleted file mode 100644 (file)
index afcd292..0000000
+++ /dev/null
@@ -1,1773 +0,0 @@
-diff -ur courier-imap-1.5.3.20020921.orig/authlib/README.authmysql.myownquery courier-imap-1.5.3.20020921/authlib/README.authmysql.myownquery
---- courier-imap-1.5.3.20020921.orig/authlib/README.authmysql.myownquery       Tue Jan  8 06:01:22 2002
-+++ courier-imap-1.5.3.20020921/authlib/README.authmysql.myownquery    Sat Sep 28 01:19:55 2002
-@@ -2,13 +2,18 @@
--          Developer Notes for courier-imap-myownquery.patch
-+                  Developer Notes and Usage Instructions
-+                                  
-+                                  of
-+                                  
-+                     courier-imap-authmysql-myownquery
-+                                      document version: 1.30
-+                                      patch for version: 1.5.3.20020921
-+                                      author: Pawel Wilk <siefca@kernel.pl>
--                                                      document version: 1.03
--                                                      author: Pawel Wilk
-@@ -21,71 +26,749 @@
-+PART I - Usage Instructions
-+      1 What's that?
-+      
-+      2 When will I need it?
-+      
-+      3 How does it work?
-+        3.1 configuration variables
-+        3.2 queries
-+        3.3 substitutions
-+        3.4 triggers
-+      
-+      4 Examples of usage
-+        4.1 corporate mail system
-+          4.1.1 database structure
-+          4.1.2 authdaemon configuration
-+        4.2 virtual mail domains provider
-+          4.2.1 database structure
-+          4.2.2 authdaemon configuration
-+
-+PART II - Developer Notes
-+
-+      1 Modifications overview
-+
-+      2 Definitions
-+
-+      3 New data types
-+        3.1 struct var_data
-+        3.2 typedef size_t (*parsefunc)
-+  
-+      4 New functions
-+        4.1 get_variable
-+        4.2 parse_core
-+        4.3 ParsePlugin_counter
-+        4.4 ParsePlugin_builder
-+        4.5 parse_string
-+        4.6 validate_password
-+        4.7 get_localpart
-+        4.8 get_domain
-+        4.9 get_username
-+        4.10 parse_select_clause
-+        4.11 parse_chpass_clause
-+        4.12 auth_mysql_on_trigger
-+      5 Ideas and TODO
-+      6 Thanks
--0 What's that?
--1 Modifications overview
--2 Definitions
--3 New data types
--  3.1 struct var_data
--  3.2 typedef size_t (*parsefunc)
--  
--4 New functions
--  4.1 get_variable
--  4.2 parse_core
--  4.3 ParsePlugin_counter
--  4.4 ParsePlugin_builder
--  4.5 parse_string
--  4.6 validate_password
--  4.7 get_localpart
--  4.8 get_domain
--  4.9 parse_select_clause
--  4.10 parse_chpass_clause
--  
--5 Ideas and TODO
-+//////////////////////////////// PART I - Usage ///////////////////////////////
-+
-+                  *-----------------------
-+                   1 What's that?
-+                  *-----------------------
-+
-+Courier-imap-myownquery's features allow the administrator to set his own MySQL
-+queries used by authdaemon to authenticate a user (including fetchig his
-+credentials) and to change the user's password. It allows one to write a
-+SELECT and UPDATE clause in the configuration file (authmysqlrc) using
-+the new configuration options. It may be useful in mail environments where
-+there is a need to have a different database structure and/or tables
-+scheme than expected by authmysql module.
--6 Thanks
-+It also implements a small parsing engine for substitution of variables which
-+may appear in the SQL clauses, such as a username or a domain.
-+
-+                  *-----------------------
-+                   2 When will I need it?
-                   *-----------------------
--                   0 What's that?
-+
-+ o  When you already have some MySQL database filled up with the data
-+    and there is no chance to change the whole structure to make it
-+    work with a standard authmysql table. Typical situation is when all the
-+    data required to authenticate a user is arranged in more than one table.
-+
-+ o  When you have some great idea how to make the database structure 
-+    more efficient due to your needs and your requirements.
-+      
-+ o  When doing something 'by-myself' is in your style and you just want
-+    to create your own database, just to feel the pleasure of doing
-+    something original. :)
-+
-+
-+
-+
-+
-                   *-----------------------
-+                   3 How does it work?
-+                  *-----------------------
-+
-+There are three things which the feature concerns:
-+
-+- fetching clauses from the configuration file
-+- doing substitution replacements inside of SQL clauses
-+- passing prepared query on to the mysql interface funtions
-+
-+3.1 configuration options
-+
-+You can apply your own MySQL queries using a set of the configuration options.
-+The options you'll need to make the authmysql your slave are:
-+
-+MYSQL_SERVER          (required)
-+MYSQL_USERNAME                (required)
-+MYSQL_PASSWORD                (required)
-+
-+              The server name, userid, and password used to log in.
-+
-+MYSQL_DATABASE                (required)
-+
-+              The name of the MySQL database we will open.
-+
-+DEFAULT_DOMAIN                (optional)
-+
-+              If DEFAULT_DOMAIN is defined, and someone tries to log in as
-+              'user', we will look up 'user@DEFAULT_DOMAIN' instead.
-+
-+USER_DOMAIN_CONCAT    (optional)
-+
-+              The USER_DOMAIN_CONCAT defines a character(s) used to
-+              concatenate a local part and a domain while parsing
-+              the $(username) substitution variable (see section 3.3
-+              for more info). If it's not defined the @ sign is assumed.
-+
-+USER_DOMAIN_SEPARATORS        (optional)
-+
-+              This may contain the set of characters used by parsing
-+              routines to split local part of the virtual mailbox name
-+              from the part which describes the domain name. If it's not
-+              defined the set containing @% is assumed, so the user can
-+              enter either: user@domain or user%domain when he wants to be
-+              authenticated.
-+
-+MYSQL_SELECT_CLAUSE   (required)
-+MYSQL_CHPASS_CLAUSE   (required under some circumstances)
-+
-+              These are the major options you should use. See 3.2 section
-+              for more info.
-+
-+MYSQL_ONSUCCESS_CLAUSE        (optional)
-+MYSQL_ONFAIL_CLAUSE   (optional)
-+
-+              These are used to do a MySQL query whether user has passed
-+              the authentication verification (MYSQL_ONSUCCESS_CLAUSE)
-+              or there was the authentication failure (MYSQL_ONFAIL_CLAUSE).
-+              Query results have no meaning. You can use the same
-+              substitution variables in your query as with
-+              MYSQL_SELECT_CLAUSE. See 3.4 section for more info.
-+
-+The options which have no effect, and may be safetly left blank are:
-+
-+MYSQL_USER_TABLE
-+MYSQL_CRYPT_PWFIELD
-+MYSQL_CLEAR_PWFIELD
-+MYSQL_UID_FIELD
-+MYSQL_GID_FIELD
-+MYSQL_LOGIN_FIELD
-+MYSQL_HOME_FIELD
-+MYSQL_NAME_FIELD
-+MYSQL_MAILDIR_FIELD
-+MYSQL_QUOTA_FIELD
-+MYSQL_WHERE_CLAUSE
-+
-+3.2 queries
-+
-+The feature adds two configuration options (clauses), which are parsed first,
-+and then applied as MySQL queries to MySQL interface routines. These options
-+are: MYSQL_SELECT_CLAUSE and MYSQL_CHPASS_CLAUSE. After each option a number of
-+spaces and/or tabs is allowed, and then MySQL query is expected. For better
-+look, your queries can have line breaks. Each line break should be preceded by
-+the backslash sign. Look into examples chapter (4) to see how it should look
-+like. First clause is used to authenticate a user, and the second to change his
-+password.
-+
-+You should note that a query identified by MYSQL_SELECT_CLAUSE should return
-+fixed number (9) of fields and each field should match the variable expected
-+by authentication routines. These fields are:
-+
-+* username    - which is the currently logged user's username (or the
-+                username with domain if you want it)
-+
-+* cryptpw     - which is the user's crypted password
-+
-+* clearpw     - which is the user's plaintext password
-+
-+* uid         - which is a numerical UID value used as a process's UID when
-+                accessing the mailbox directory
-+
-+* gid         - as above, but refers to GID
-+
-+* home                - which contains full path to the user's home directory
-+
-+maildir               - which contains the directory name inside the user's home
-+                which is treated as INBOX folder when accessing mailbox
-+                - if it's empty then the 'Maildir' string is used
-+
-+quota         - which describes a quota size for the mailbox
-+
-+fullname      - which may contain the user's fullname
-+
-+(The fields marked by the asterix sign are required and cannot have an
-+ empty results)
-+
-+So, the typical query clause may start with:
-+
-+MYSQL_SELECT_CLAUSE SELECT                                      \
-+ users.username,                                              \
-+ users.cryptpw,                                                       \
-+ users.clearpw,                                               \
-+ domains.uid,                                                 \
-+ domains.gid,                                                 \
-+ users.mailbox_path)                                          \
-+ ''                                                           \ 
-+ domains.quota,                                                       \
-+ ''                                                           \
-+...
-+
-+Note that in this short example we're assuming that we have two tables
-+(users and domains) and INBOX path is always called 'Maildir' and
-+we're not using the fullname field (the query will always return an empty
-+string in its place).
-+
-+Also note that you may discard one of the password fields if you don't want
-+to use an authentication mechanism, which needs it. For example, if you don't
-+want to use MD5-CRAM you may put '' into the place of clearpw (because, for
-+example you're in paranoid mode and you don't even want to keep plain passwords
-+in the database:).
-+
-+3.3 substitutions
-+
-+Substitutions are strings, which may appear in your query, and which have a
-+special meaning. You can also call them substitution variables. If substitution
-+variable is known for a clause context then it is parsed. If it isn't known the
-+error is generated. In the default compilation of authmysql module any
-+substitution variable is declared inside of two substrings - the first is a 
-+dollar sign concatenated with opening parenthesis, and the second is a closing
-+parenthesis sign. First symbol identifies beginning of a substitution variable,
-+and the second closes it. The string between the beginning and the closing
-+symbol is called substitution variable's name.
-+
-+When, as I said before, the name is known to the parsing routine the
-+substitution is made and the proper value appears in place of the substitution
-+variable, while passing on the query for later processing.
-+
-+Allowed substitution variables:
-+
-+context: MYSQL_SELECT_CLAUSE, MYSQL_ONFAIL_CLAUSE, MYSQL_ONSUCCESS_CLAUSE
-+
-+$(local_part)         will be replaced by currently verified user's username
-+                      (without the domain part)
-+
-+$(domain)             will be replaced by currently verified user's domain
-+                      name (if present, or if not present but the 
-+                      DEFAULT_DOMAIN was used) or by the empty, zero-length
-+                      string if the domain cannot be obtained
-+
-+$(username)           will be replaced by currently verified user's username
-+                      concatenated with the given domain name using symbol
-+                      defined by USER_DOMAIN_CONCAT - if the domiain name
-+                      cannot be obtained (even by looking up DEFAULT_DOMAIN)
-+                      the separation sign will not appear and only the given
-+                      username will be presented
-+
-+context: MYSQL_CHPASS_CLAUSE
-+
-+$(local_part)           will be replaced by currently verified user's username
-+                        (without the domain part)
-+
-+$(domain)               will be replaced by currently verified user's domain
-+                        name (if present, or if not present but the
-+                        DEFAULT_DOMAIN was used) or by the empty, zero-length
-+                        string if the domain cannot be obtained
-+
-+$(username)             will be replaced by currently verified user's username
-+                        concatenated with the given domain name using symbol
-+                        defined by USER_DOMAIN_CONCAT - if the domiain name
-+                        cannot be obtained (even by looking up DEFAULT_DOMAIN)
-+                        the separation sign will not appear and only the given
-+                        username will be presented
-+
-+$(newpass)            will be replaced by currently authenticated user's
-+                      new password to set up (plaintext password)
-+
-+$(newpass_crypt)      will be replaced by currently authenticated user's
-+                      new password to set up (MD5 form created from entered
-+                      plain form)
-+
-+3.4 triggers
-+
-+Triggers are MySQL queries, which are performed depending on authentication
-+state. Currently, there are two triggers which you may use. First is called
-+MYSQL_ONSUCCESS_CLAUSE and it is performed when the authentication succeedes.
-+The second is called MYSQL_ONFAIL_CLAUSE and has the reverse meaning. You can
-+declare triggers in the authmysqlrc configuration file. They can be used to
-+arrange some logging facility in the database or just to keep last times
-+of the successful/failed login tries. The typical trigger, which puts last
-+login date into the users' table can look like this:
-+
-+MYSQL_ONSUCCESS_CLAUSE        UPDATE users SET last_login=CURRENT_TIMESTAMP \
-+                      WHERE username='$(username)';
-+
-+or, if you would like to know about last login failure for users you can try:
-+
-+MYSQL_ONFAIL_CLAUSE   UPDATE users SET last_bad_login=CURRENT_TIMESTAMP \
-+                      WHERE username='$(username)';
--Courier-imap-myownquery.patch allows administrator to set own MySQL queries
--used by authdaemon to authenticate user (including fetchig credentials) and to
--change user's password. It allows to construct SELECT or UPDATE clause in the
--configuration file (authmysqlrc) by adding two new configuration variables:
--MYSQL_SELECT_CLAUSE and MYSQL_CHPASS_CLAUSE. It may be useful in the mail
--environments where there is such a need to have different database structure
--and/or tables scheme than expected by authmysql module.
-+Note, that YOU CAN use the triggers even if you aren't using
-+MYSQL_SELECT_CLAUSE. Also note, that there is such a possibility that ONFAIL
-+trigger may be performed without a proper username. Take it into consideration
-+when creating queries to avoid messy data on INSERT operations.
--It also implements a small parsing engine for substitution variables which
--may appear in the clauses and are used to put informations like username
--or domain into the right place of a query.
--This patch was created using `diff -Nur` on courier-imap-1.3.12 source.
-+                  *-----------------------
-+                   4 Examples of usage
-+                  *-----------------------
-+
-+The "ownquery" feature gives you possibility to adapt an authentication query
-+to the database. So the first thing you have to do is to design the database
-+structure you need, whithout being grieved at what structure authentication
-+routines like. You have to take care about four essential things:
-+
-+ o  The database
-+ 
-+ o  The users' data in the database
-+ 
-+ o  The proper directories for keeping virtual mailboxes and a system user
-+    which can read and write them
-+ 
-+ o  The proper MySQL queries in your authmysqlrc configuration file
-+
-+4.1 corporate mail system
-+
-+This example is concerned about a corporate mail system with a small
-+ammount of served virtual domains. The database scheme was derived from tpop3d
-+documentation and modified a bit.
-+
-+4.1.1 database structure
-+
-+Our goal here is to separate the data responsible for keeping mailbox
-+credentials from the data, which describes a domain.
-+
-+Let's create some tables for our example, filled up with an example data:
-+
-+table:          domains
-+
-+purpose:        associates virtual domain with domain name and informations
-+              necessary to access mailboxes withing the domain
-+
-+fields:         domain_name             - fully qualified domain name
-+                path_prefix             - absolute pathname which points to
-+                                          a directory where domain's mailboxes
-+                                          are located
-+                quota                   - default quota for each mailbox
-+                uid                     - UID used to work on mailboxes
-+                gid                     - GID used to work on mailboxes
-+              
-+        +----------------+-------------+-----+-----+----------+
-+        | domain_name    | path_prefix | uid | gid | quota    |
-+        +----------------+-------------+-----+-----+----------+
-+        | exampledom.com | /var/mail/x | 555 | 555 | 10000000 |
-+      | pld.org.pl     | /var/mail/p | 556 | 556 | 20000000 |
-+      | pld.net.pl     | /var/mail/p | 556 | 556 | 20000000 |
-+      +----------------+-------------+-----+-----+----------+
-+
-+table:          users
-+
-+purpose:        associates virtual mailbox with user and domain name,
-+              and with informations necessary to access mailbox
-+
-+fields:         username              - user login name (mailbox name)
-+              domain_name             - fully qualified domain name
-+                mailbox_path            - relative pathname for mailbox
-+                                          (will be appended to the path_prefix
-+                                          from domain_auth table to specify
-+                                        user's mailbox location)
-+                cryptpw                 - crypted password
-+                plainpw                 - plaintext password
-+
-+        +----------+----------------+--------------+------------+--------+
-+      | username | domain_name    | mailbox_path | cryptpw   | plainpw |
-+      +----------+----------------+--------------+-----------+---------+
-+      | siefca   | pld.org.pl     | s/siefca     | $1$fs45.. | dupa.8  |
-+      | siefca   | pld.net.pl     | s/siefca     | $1$fs45.. | dupa.8  |
-+      | f00bar   | exampledom.com | foobar       | $1$g44w.. | secret  |
-+      +----------+----------------+--------------+-----------+---------+ 
-+
-+Using MySQL monitor you can create these tables entering CREATE sequences.
-+Be sure to connect to the database using administrative MySQL account
-+(usualy: mysql -u mysql -p).
-+
-+--------------------- cut here
-+
-+# Create the database called vmail.
-+
-+CREATE database vmail;
-+
-+# Create an example MySQL user, which can read, write and delete data from
-+# vmail database. Username: vuser Password: secret_password
-+
-+GRANT SELECT,INSERT,UPDATE,DELETE ON vmail.*
-+             TO vuser@localhost
-+             IDENTIFIED BY 'secret_password';
-+
-+FLUSH PRIVILEGES;
-+
-+# Create the tables.
-+
-+use vmail;
-+
-+CREATE TABLE domains (
-+        domain_name           char(255) DEFAULT '',
-+        path_prefix           char(255) DEFAULT '' NOT NULL,
-+        uid                   int(10) unsigned DEFAULT '15000' NOT NULL,
-+        gid                   int(10) unsigned DEFAULT '15000' NOT NULL,
-+        quota                 char(255) DEFAULT '2000000' NOT NULL,
-+        KEY domain_name (domain_name(255))
-+        );
-+
-+CREATE TABLE users (
-+        username              char(128) DEFAULT '' NOT NULL,
-+        domain_name           char(255) DEFAULT '',
-+        mailbox_path          char(255) DEFAULT '' NOT NULL,
-+        cryptpw               char(128) DEFAULT '' NOT NULL,
-+        clearpw               char(128) DEFAULT '' NOT NULL,
-+        KEY username (username(128))
-+        );
-+
-+# Create an example virtual domain entry
-+# name  : exampledom.com
-+# uid   : 555
-+# gid   : 555
-+# path  : /var/mail/x
-+# quota : 10 Megs per mailbox
-+
-+INSERT INTO domains VALUES ('exampledom.com', '/var/mail/x', 555, 555,
-+                            '10000000');
-+
-+# Create an example virtual user entry
-+# username      : siefca
-+# domain name   : exampledom.com
-+# cryptpw       : $1$wIfVZ8uK$qhagYAcIoZpQM83Et7c1e/
-+# clearpw       : dupa.8
-+# mailbox path  : s/siefca
-+
-+INSERT INTO users VALUES ('siefca', 'exampledom.com', 's/siefca',
-+                        '$1$wIfVZ8uK$qhagYAcIoZpQM83Et7c1e/',
-+                        'dupa.8');
-+
-+--------------------- cut here
-+
-+Note: If you would like to have your passwords more safe then just omit the
-+      clearpw column and put '' into the config-query in its place while
-+      doing SELECT on a database. But be ware - you'll be unable to use
-+      authentication methods which needs it, like MD5_CRAM.
-+
-+4.1.2 authdaemon configuration
-+
-+When our database is ready we can set up the configuration. :-) Go to
-+authmysqlrc file and edit it.
-+
-+At the beginning we should take care about general informations, which
-+are identifying our database:
-+
-+MYSQL_SERVER            localhost
-+MYSQL_USERNAME          vuser
-+MYSQL_PASSWORD          secret_password
-+MYSQL_DATABASE          vmail
-+
-+Then we should add a clause responsible for authenticating user and
-+fetching credentials:
-+
-+DEFAULT_DOMAIN          exampledom.com
-+
-+MYSQL_SELECT_CLAUSE SELECT                                      \
-+ users.username, users.cryptpw, users.clearpw,                  \
-+ domains.uid, domains.gid,                                      \
-+ CONCAT_WS('/',domains.path_prefix,users.mailbox_path),         \
-+ '', domains.quota, ''                                          \
-+ FROM users, domains                                            \
-+  WHERE domains.domain_name='$(domain)'                         \
-+    AND users.username='$(local_part)'                          \
-+    AND domains.domain_name=users.domain_name
-+
-+
-+Note the '' in the place of field which tells where user's INBOX resides
-+and in place of realname field. You should use '' if you want to put an empty
-+value as a query result for some field.
-+
-+We also should add some configuration for changing user's password:
-+
-+MYSQL_CHPASS_CLAUSE UPDATE                                             \
-+ users                                                                 \
-+ SET clearpw='$(newpass)',                                             \
-+     cryptpw='$(newpass_crypt)'                                        \
-+ WHERE username='$(local_part)'                                        \
-+ AND   domain_name='$(domain)'
-+
-+And finally...
-+Create a system user/group and a proper directory structure. In our example:
-+
-+groupadd -g 555 xdomain
-+useradd -u 555 -g 555 xdomain
-+mkdir -p /var/mail/x/s/siefca
-+chmod -R 0770 /var/mail/x
-+maildirmake /var/mail/x/s/siefca/Maildir
-+chown -R xdomain.xdomain /var/mail/x
-+
-+Now, restart the authdaemon and see if it works. Try: telnet 0 pop3
-+
-+and type:
-+
-+USER siefca [ENTER]
-+PASS dupa.8 [ENTER]
-+
-+You should get Ok response. ;)
-+
-+4.2 virtual mail domains provider
-+
-+Let's consider more complicated database scheme, where there is a need to
-+associate a lot of information with the domain name, including registrant
-+information, owner, etc. That implies data separation between domain name,
-+user and domain additional informations (which are unwanted when 
-+authentication process takes place). By proper data separation I mean 
-+avoiding unwanted redundancy in the database.
-+
-+Currently applied example doesn't care about the update password problem.
-+This is due to current abilities of MySQL and authdaemon (authmysql).
-+MySQL doesn't support subsequent SELECTs on UPDATE operation, and authmysql
-+doesn't supports batched queries at the moment.
-+
-+4.2.1 database structure
-+
-+table:                domain_names
-+
-+purpose:      associates domain_id with domain name
-+
-+fields:               domain_name             - fully qualified domain name
-+              domain_id               - domain identifier
-+
-+      +----------------+-----------+
-+      | domain_name    | domain_id |
-+      +----------------+-----------+
-+      | exampledom.com |         1 |
-+      | pld.org.pl     |         2 |
-+      | pld.net.pl     |         2 |
-+      | foobare.net.uk |         3 |
-+      +----------------+-----------+
-+
-+Note, that for pld.org.pl and pld.net.pl the domain identifiers are the same.
-+We can create a domain aliases in such a way. :)
-+
-+table:                domain_auth
-+
-+purpose:      associates domain_id with authentication credentials
-+              which are common for all users in the virtual domain
-+
-+fields:               domain_id               - domain identifier
-+              path_prefix             - absolute pathname which points to
-+                                        a directory where domain's mailboxes
-+                                        are located
-+              quota                   - default quota for each mailbox
-+              uid                     - UID used to work on mailboxes
-+              gid                     - GID used to work on mailboxes
-+              
-+      +------------+---------------+--------+-------+-------+
-+      | domain_id  | path_prefix   | quota  | uid   | gid   |
-+      +------------+---------------+--------+-------+-------+
-+      |          1 | /var/mail/ex  | 100000 | 15000 | 15000 | 
-+      |          2 | /var/mail/pld | 555500 | 15001 | 15000 |
-+      |          3 | /home/f0/mail |   8000 | 15002 | 15000 |
-+      +------------+---------------+--------+-------+-------+
-+
-+table:                domain_info
-+
-+purpose:      associates domain_id with additional informations
-+
-+fields:               domain_id               - domain identifier
-+              registrant_id           - registrant identifier
-+              nic_handle              - NIC handle
-+              owner_id                - domain's owner identifier
-+              expires                 - domain's expiration date
-+
-+      +------------+---------------+------------+----------+---------+
-+      | domain_id  | registrant_id | nic_handle | owner_id | expires |
-+      +------------+---------------+------------+----------+---------+
-+
-+      (we don't need to say anything more about this table indeed)
-+
-+table:                users
-+
-+purpose:      associates users' identifiers with domains' identifiers
-+              and infers the credentials for various virtual mailboxes
-+
-+fields:               username                - user's login name
-+              domain_id               - domain identifier
-+              cryptpw                 - crypted password
-+              plainpw                 - plaintext password
-+              quota                   - user's mailbox quota
-+                                        (will override quota value set for
-+                                        the whole virtual domain)
-+              path                    - relative pathname for mailbox
-+                                        (will be appended to the path_prefix
-+                                        from domain_auth table to specify
-+                                        user's mailbox location)
-+
-+      +------------+-----------+----------+-----------+-------+------------+
-+      | username   | domain_id | cryptpw  | plainpw   | quota | path       |
-+      +------------+-----------+----------+-----------+-------+------------+
-+      | foobar     |         1 | $1$hlIeE | dupa.8    | NULL  | f/o/foobar |
-+      | breeder    |         2 | $1$TWsdf | ziarno128 | 77777 | brd        |
-+      +------------+-----------+----------+-----------+-------+------------+
-+
-+    (you can add a realname column here, it doesn't fit to my terminal window:)
-+
-+--------------------- cut here
-+
-+# Create the database called vmail.
-+
-+CREATE database vmail;
-+
-+# Create an example MySQL user, which can read, write and delete data from
-+# vmail database. Username: vuser Password: secret_password
-+
-+GRANT SELECT,INSERT,UPDATE,DELETE ON vmail.*
-+           TO vuser@localhost
-+           IDENTIFIED BY 'secret_password';
-+
-+FLUSH PRIVILEGES;
-+
-+# Create the tables.
-+
-+use vmail;
-+
-+CREATE TABLE domain_names (
-+      domain_id             int(10) unsigned NOT NULL,
-+      domain_name           char(255) DEFAULT '' NOT NULL,
-+      KEY domain_name (domain_name(255))
-+      );
-+
-+CREATE TABLE domain_auth (
-+      domain_id             int(10) unsigned DEFAULT 1 NOT NULL,
-+      uid                   int(10) unsigned DEFAULT '15000' NOT NULL,
-+      gid                   int(10) unsigned DEFAULT '15000' NOT NULL,
-+      path_prefix           char(255) DEFAULT '' NOT NULL,
-+      quota                 char(255) DEFAULT '20000000' NOT NULL,
-+      KEY domain_id (domain_id)
-+      );
-+
-+CREATE TABLE users (
-+        username            char(128) DEFAULT '' NOT NULL,
-+      domain_id             int(10) unsigned DEFAULT 1 NOT NULL,
-+        cryptpw               char(128) DEFAULT '' NOT NULL,
-+      plainpw               char(128) DEFAULT '' NOT NULL,
-+        name                  char(128) DEFAULT '' NOT NULL,
-+        quota                 char(255),
-+      path                  char(255) DEFAULT '' NOT NULL,
-+        KEY username (username(128))
-+      );
-+      
-+# Create an example virtual domain entry
-+# id  : 1
-+# name        : exampledom.com
-+# uid : 15000
-+# gid : 15000
-+# path        : /var/mail/example
-+# quota       : 20 Megs per mailbox
-+
-+INSERT INTO domain_names VALUES (1, 'exampledom.com');
-+INSERT INTO domain_auth VALUES (1, '15000', '15000', '/var/mail/example',
-+                              '20000000');
-+
-+# Create an example virtual user entry
-+# username    : siefca
-+# domain id   : 1 (points to exampledom.com)
-+# cryptpw     : $1$wIfVZ8uK$qhagYAcIoZpQM83Et7c1e/
-+# clearpw     : dupa.8
-+# name                : Pawel Wilk
-+# quota               : NULL (we want it to be fetched from domain_auth table)
-+# mailbox path        : s/i/siefca
-+
-+INSERT INTO users VALUES ('siefca', 1, '$1$wIfVZ8uK$qhagYAcIoZpQM83Et7c1e/',
-+                        'dupa.8', 'Pawel Wilk', NULL, 's/i/siefca');
-+
-+--------------------- cut here
-+
-+Ok, we've done what we need. Don't forget to create system user with UID and
-+GID set to 15000, and a directory containing mailboxes (in this case:
-+/var/mail/example) owned by system user I've mentioned above.
-+There is also necessary to create Maildir folder structure for our user
-+inside the virtual domain directory - you can configure your MTA agent to do
-+such thing when first message arrive or use maildirmake tool, which comes
-+with Courier-IMAP.
-+
-+
-+4.2.2 authdaemon configuration
-+
-+DEFAULT_DOMAIN                exampledom.com
-+
-+MYSQL_SELECT_CLAUSE SELECT                                    \
-+ users.username,                                              \
-+ users.cryptpw,                                                       \
-+ users.plainpw,                                                       \
-+ domain_auth.uid,                                             \
-+ domain_auth.gid,                                             \
-+ CONCAT_WS('/',domain_auth.path_prefix,users.path),           \
-+ '',                                                          \
-+ IFNULL(users.quota, domain_auth.quota),                      \
-+ users.name                                                   \
-+ FROM users, domain_names, domain_auth                                \
-+ WHERE domain_names.domain_name='$(domain)'                   \
-+  AND users.username='$(local_part)'                          \
-+  AND domain_names.domain_id=users.domain_id                  \
-+  AND domain_names.domain_id=domain_auth.domain_id
-+
-+
-+.
-+.
-+.
-+.
-+.
-+.
-+
-+/////////////////////////// PART II - Developer Notes /////////////////////////
-                   *-----------------------
-                    1 Modifications overview
-                   *-----------------------
--Modified files:       authmysqllib.c authmysqlrc
-+Modified files:       authmysqllib.c authmysql.c authmysql.h authmysqlrc
- Each modified set of instructions is marked by my e-mail address:
- siefca@pld.org.pl
--Changes in the current source code are related to:
-+Changes in the source code are related to:
- - sections where the queries are constructed
-   (including memory allocation for the buffers)
-@@ -102,6 +785,10 @@
-       newline as the second is replaced by two whitespaces while
-       putting into the buffer
-+      i've also added USER_DOMAIN_CONCAT and USER_DOMAIN_SEPARATORS
-+      configuration options - they're used by get_localpart(), get_domain()
-+      and get_username() functions, which are described below
-+
- - sections where the query is constructed
-       selection is made, depending on configuration variables which
-@@ -130,7 +817,16 @@
- MAX_SUBSTITUTION_LEN defines maximal length of a substitution variable's
- identifier (name).
--The last two definitions are just for code simplification.
-+The last two definitions (SV_BEGIN_LEN and SV_END_LEN) are just for code
-+simplification.
-+
-+#define         DEF_CONCAT_STRING       "@"
-+#define         DEF_SEPARATORS_SET      "@%"
-+
-+The first (DEF_CONCAT_STRING) is used to set the defaults for a
-+concatenation string, used when parsing $(username) substitution variable.
-+The second (DEF_SEPARATORS_SET) is the set of characters, which are treated as
-+separators when splitting local part from the domain.
-@@ -179,7 +875,7 @@
- In this example we've declared that $(some) in the query should be
- replaced by 'replacement' text, and replacement for $(anotha) will
- be defined in the code before passing on the array pointer to
--the paring function.
-+the general parsing function.
- 3.2 typedef size_t (*parsefunc)
-@@ -230,6 +926,10 @@
-       structure of var_data type, which contains variable definition
-       of a given name. It returns NULL on error or failure.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
- 4.2 parse_core
-@@ -285,6 +985,11 @@
-       This function returns -1 if an error has occured and 0 if
-       everything went good.
-+
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-       
- 4.3 ParsePlugin_counter
-@@ -314,6 +1019,11 @@
-       This function returns the variable size or -1 if an error
-       has occured, 0 if everything went good.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+
- 4.4 ParsePlugin_builder
- NAME
-@@ -333,7 +1043,7 @@
-       type pointer and refers to the (char *) pointer variable.
-       After each call it shifts the value of pointer variable (char *)
-       incrementing it by len bytes. Be careful when using this function
--      - its changes the given pointer value. Always operate on an
-+      - it changes the given pointer value. Always operate on an
-       additional pointer type variable when passing it as the third
-       argument.
-@@ -342,6 +1052,10 @@
-       This function returns the variable size or -1 if an error
-       has occured, 0 if everything went good.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
- 4.5 parse_string
- NAME
-@@ -353,7 +1067,7 @@
- DESCRIPTION
--      This function parses the string pointed with source according to the
-+      This function parses the string pointed to by source according to the
-       replacement instructions set in var_data array, which is passed with
-       its pointer vdt. It produces changed string located in newly allocated
-       memory area.
-@@ -377,6 +1091,10 @@
-       Function returns pointer to the result buffer or NULL
-       if an error has occured.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
- WARNINGS
-       This function allocates some amount of memory using standard
-@@ -405,6 +1123,10 @@
-       It returns a pointer to the static buffer which contains
-       validated password string or NULL if an error has occured.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
- 4.7 get_localpart
-@@ -414,20 +1136,28 @@
- SYNOPSIS
--      static const char *get_localpart (const char *username);
-+      static const char *get_localpart (const char *username,
-+                                        const char *separators);
- DESCRIPTION
-       This function detaches local part of an e-mail address
-       from string pointed with username and puts it to the
-       buffer of the fixed length. All necessary cleaning is
--      made on the result string.
-+      made on the result string. String pointed with separators
-+      refers to a set of characters, which are treated as
-+      separation signs between local part and a domain.
- RETURN VALUE
-       Pointer to the static buffer containing local part or
-       NULL if there was some error.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+
- 4.8 get_domain
-@@ -438,24 +1168,68 @@
- SYNOPSIS
-       static const char *get_domain (const char *username, 
--                                     const char *defdomain);
-+                                     const char *defdomain,
-+                                     const char *separators);
- DESCRIPTION
-         This function detaches domain part of an e-mail address
-       from string pointed with username and puts it to the
-       buffer of the fixed length. All necessary cleaning is
--      made on the result string. If function cannot find domain
--      part in the string the string pointed by defdomain is
--      used instead.
-+      made on the result string. If the function cannot find a domain
-+      part in the string then the string pointed to by defdomain is
-+      used instead. If this function cannot find a domain part
-+      as well as it cannot obtain the default domain (it's empty string
-+      or the defdomain pointer is NULL) the returned result string is an
-+      empty string. The string pointed with separators refers to a set
-+      of characters, which are treated as separation signs between local
-+      part and a domain.
- RETURN VALUE
-         Pointer to the static buffer containing domain name or
-       NULL if there was some error.
-+FILES
-+
-+      authlib/authmysqllib.c
-+
--4.9 parse_select_clause
-+4.9 get_username
-+
-+NAME
-+
-+      get_username
-+
-+SYNOPSIS
-+
-+      static const char *get_username (const char *username,
-+                                       const char *domainname,
-+                                       const char *concat_str);
-+
-+DESCRIPTION
-+
-+      This function concatenates the localpart with a domain name
-+      using the string pointed with concat_str. If the domain is
-+      empty or NULL the result comes without binding string.
-+
-+RETURN VALUE
-+
-+        Pointer to the static buffer containing output string or
-+        NULL if there was some error.
-+
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+WARNINGS
-+
-+      This function does not any string cleaning, nor default domain
-+      checking. It is designed to work on results of get_localpart() and
-+      get_domain().
-+
-+
-+4.10 parse_select_clause
- NAME
-@@ -465,7 +1239,9 @@
-       static char *parse_select_clause (const char *clause,
-                                         const char *username,
--                                        const char *defdomain);
-+                                        const char *defdomain
-+                                        const char *concat_str,
-+                                        const char *separators_set);
- DESCRIPTION
-@@ -473,15 +1249,21 @@
-       function. It parses a query pointed by caluse. username
-       and defdomain strings are used to replace corresponding
-       substitution strings if present in the query: $(local_part)
--      and $(domain).
-+      and $(domain). The separators_set is passed to get_username()
-+      and get_domain() invocations, and the concat_str is passed
-+      to get_username() function, which is responsible for replacing
-+      $(username) substitution variable.
-       
--
- RETURN VALUE
-       Same as parse_string().
-+FILES
-+
-+      authlib/authmysqllib.c
--4.10 parse_chpass_clause
-+
-+4.11 parse_chpass_clause
- NAME
-@@ -492,6 +1274,8 @@
-         static char *parse_chpass_clause (const char *clause,
-                                           const char *username,
-                                           const char *defdomain,
-+                                        const char *separators_set,
-+                                        const char *concat_str,
-                                         const char *newpass,
-                                         const char *newpass_crypt);
-                                                                   
-@@ -502,12 +1286,56 @@
-       defdomain, newpass and newpass_crypt strings are used to
-       replace corresponding substitution strings if present in
-       the query: $(local_part), $(domain), $(newpass),
--      $(newpass_crypt).
-+      $(newpass_crypt). The separators_set and the concat_str
-+      are passed to get_localpart(), get_domain(), and get_username()
-+      functions as described in the entry for parse_select_clause().
- RETURN VALUE
-       Same as parse_string().
-+FILES
-+
-+      authlib/authmysqllib.c
-+
-+
-+4.12 auth_mysql_on_trigger
-+
-+NAME
-+
-+      auth_mysql_on_trigger
-+
-+SYNOPSIS
-+
-+      int auth_mysql_on_trigger (const char *clause_name,
-+                                 const char *username);
-+
-+DESCRIPTION
-+
-+      This function is responsible for calling out the MySQL queries 
-+      depending on which authentication state was reached.
-+
-+      The clause_name should contain the name of a clause, which can be found
-+      in the configuration file, and the username is simply the string used
-+      as username (including the domain if entered).
-+
-+      This function reads DEFAULT_DOMAIN, USER_DOMAIN_CONCAT and
-+      USER_DOMAIN_SEPARATORS from the configuration file using read_env(),
-+      then it uses parse_select_clause() to parse the query obtained using
-+      read_env(clause_name), and then it calls querying subroutines to
-+      perform the action.
-+
-+RETURN VALUE
-+
-+      This function returns 1 on success and 0 on failure. The query results
-+      are simply discarded. If a trigger's clause is not defined in the
-+      configuration file the 1 is returned and function silently ends its
-+      work.
-+
-+FILES
-+
-+      authlib/authmysql.h
-+      authlib/authmysql.c
-@@ -520,11 +1348,9 @@
-   strings after split                                         (problem?)
- - allow admin to set a group name instead of numerical group id
- - allow admin to set a username instead of numerical user id
--
--- add clauses:
--
--  - MYSQL_PRESELECT_CLAUSE (query which comes before MYSQL_SELECT_CLAUSE)
--  - MYSQL_POSTSELECT_CLAUSE (query which comes after MYSQL_SELECT_CLAUSE)
-+- allow batched queries and register variables for keeping results
-+- put the parsing routines into separate files to make possible of sharing it
-+  by more authentication modules
-@@ -534,10 +1360,20 @@
-                    6 Thanks
-                   *------------------------
--At the beginning this patch was messy indeed. :> I would like to thank
--Sam Varshavchik for pointing me a lot how to make it more fast and solid.
--I would also thank Philip Hazel, Chris Lightfoot and Mike Bremford which
--by their software capabilities inspired me to write it.
-+At the beginning the patch was messy indeed. :> I would like to thank:
-+
-+Sam Varshavchik
-+  for pointing me a lot, how to make it more fast and solid
-+          
-+Philip Hazel, Chris Lightfoot, Mike Bremford
-+  which by their software's capabilities inspired me to write it
-+              
-+Oliver Oblasnik
-+  which remainded me to make the documentation more friendly for
-+  those who are not programmers and just want to use it
-+  
-+Jacek Surazski
-+  for reviewing this document just before it was published
- ---------------------------------------------------------------------------
-diff -ur courier-imap-1.5.3.20020921.orig/authlib/authmysql.c courier-imap-1.5.3.20020921/authlib/authmysql.c
---- courier-imap-1.5.3.20020921.orig/authlib/authmysql.c       Mon Aug 19 17:52:28 2002
-+++ courier-imap-1.5.3.20020921/authlib/authmysql.c    Sat Sep 28 00:01:07 2002
-@@ -31,7 +31,11 @@
-       if ((user=strtok(authdata, "\n")) == 0 ||
-               (pass=strtok(0, "\n")) == 0)
-       {
--              errno=EPERM;
-+              if (!auth_mysql_on_trigger("MYSQL_ONFAIL_CLAUSE", user))
-+                      errno=EACCES;
-+              else
-+                      errno=EPERM;
-+                      
-               return (0);
-       }
-@@ -50,7 +54,11 @@
-       {
-               if (authcheckpassword(pass,authinfo->cryptpw))
-               {
--                      errno=EPERM;
-+                      if (!auth_mysql_on_trigger("MYSQL_ONFAIL_CLAUSE", user))
-+                          errno=EACCES;
-+                      else
-+                          errno=EPERM;
-+      
-                       return (0);     /* User/Password not found. */
-               }
-       }
-@@ -58,13 +66,21 @@
-       {
-               if (strcmp(pass, authinfo->clearpw))
-               {
--                      errno=EPERM;
-+                      if (!auth_mysql_on_trigger("MYSQL_ONFAIL_CLAUSE", user))
-+                          errno=EACCES;
-+                      else
-+                          errno=EPERM;
-+
-                       return (0);
-               }
-       }
-       else
-       {
--              errno=EPERM;
-+              if (!auth_mysql_on_trigger("MYSQL_ONFAIL_CLAUSE", user))
-+                  errno=EACCES;
-+              else
-+                  errno=EPERM;
-+
-               return (0);             /* Username not found */
-       }
-@@ -132,6 +148,12 @@
-               (*callback_func)(&aa, callback_arg);
-       }
-+      if (!auth_mysql_on_trigger("MYSQL_ONSUCCESS_CLAUSE", user))
-+      {
-+          errno=EACCES;
-+          return (0);
-+      }
-+
-       return (strdup(authinfo->username));
- }
-@@ -153,7 +175,11 @@
-       {
-               if (authcheckpassword(pass,authinfo->cryptpw))
-               {
--                      errno=EPERM;
-+                      if (!auth_mysql_on_trigger("MYSQL_ONFAIL_CLAUSE", user))
-+                          errno=EACCES;
-+                      else
-+                          errno=EPERM;
-+
-                       return (-1);    /* User/Password not found. */
-               }
-       }
-@@ -161,13 +187,21 @@
-       {
-               if (strcmp(pass, authinfo->clearpw))
-               {
--                      errno=EPERM;
-+                      if (!auth_mysql_on_trigger("MYSQL_ONFAIL_CLAUSE", user))
-+                          errno=EACCES;
-+                      else
-+                          errno=EPERM;
-+
-                       return (-1);
-               }
-       }
-       else
-       {
--              errno=EPERM;
-+              if (!auth_mysql_on_trigger("MYSQL_ONFAIL_CLAUSE", user))
-+                      errno=EACCES;
-+              else
-+                      errno=EPERM;
-+
-               return (-1);
-       }
-@@ -176,6 +210,13 @@
-               errno=EPERM;
-               return (-1);
-       }
-+      
-+      if (!auth_mysql_on_trigger("MYSQL_ONSUCCESS_CLAUSE", user))
-+      {
-+              errno=EACCES;
-+              return (-1);
-+      }
-+      
-       return (0);
- }
-diff -ur courier-imap-1.5.3.20020921.orig/authlib/authmysql.h courier-imap-1.5.3.20020921/authlib/authmysql.h
---- courier-imap-1.5.3.20020921.orig/authlib/authmysql.h       Mon Aug  6 05:12:39 2001
-+++ courier-imap-1.5.3.20020921/authlib/authmysql.h    Sat Sep 28 00:01:07 2002
-@@ -21,6 +21,7 @@
-       } ;
- extern struct authmysqluserinfo *auth_mysql_getuserinfo(const char *);
-+extern int auth_mysql_on_trigger (const char *clause_name, const char *username);
- extern void auth_mysql_cleanup();
- extern int auth_mysql_setpass(const char *, const char *);
-diff -ur courier-imap-1.5.3.20020921.orig/authlib/authmysqllib.c courier-imap-1.5.3.20020921/authlib/authmysqllib.c
---- courier-imap-1.5.3.20020921.orig/authlib/authmysqllib.c    Sun Aug 11 22:01:25 2002
-+++ courier-imap-1.5.3.20020921/authlib/authmysqllib.c Sat Sep 28 06:06:41 2002
-@@ -24,6 +24,9 @@
- #define               SV_BEGIN_LEN            ((sizeof(SV_BEGIN_MARK))-1)
- #define               SV_END_LEN              ((sizeof(SV_END_MARK))-1)
-+#define               DEF_CONCAT_STRING       "@"
-+#define               DEF_SEPARATORS_SET      "@%"
-+
- static const char rcsid[]="$Id$";
- /* siefca@pld.org.pl */
-@@ -268,7 +271,7 @@
-                        SV_BEGIN_MARK
-                        "%.*s"
-                        SV_END_MARK
--                       "\n", len, begin);
-+                       "\n", (int) len, begin);
-       
-       return NULL;
- }
-@@ -426,21 +429,43 @@
-               return NULL;
-       }       
-       *pass_buf = '\0';
--      
-+
-       return output_buf;
- }
- /* siefca@pld.org.pl */
--static const char *get_localpart (const char *username)
-+static const char *get_username (const char *username, const char *domainname,
-+                               const char *concat_str)
-+{
-+static char   username_buf[400];
-+
-+      if (!username || !domainname || !concat_str ||
-+          *username == '\0' || *concat_str == '\0')   return NULL;
-+      if ((   strlen(username)   +
-+              strlen(concat_str) +
-+              strlen(domainname)) > 397)      return NULL;
-+
-+      if (*domainname == '\0')
-+              strcpy (username_buf, username);
-+      else
-+              sprintf (username_buf, "%s%s%s", username, concat_str,
-+                                               domainname);
-+
-+      return (username_buf);
-+}
-+
-+/* siefca@pld.org.pl */
-+static const char *get_localpart (const char *username, const char *separators)
- {
- size_t                lbuf    = 0;
- const char    *l_end, *p;
- char          *q;
- static char   localpart_buf[130];
-       
--      if (!username || *username == '\0')     return NULL;
-+      if (!username || *username == '\0' ||
-+          !separators || *separators == '\0') return NULL;
-       
--      p = strchr(username,'@');
-+      p = strpbrk (username, separators);
-       if (p)
-       {
-               if ((p-username) > 128)
-@@ -469,21 +494,27 @@
- }
- /* siefca@pld.org.pl */
--static const char *get_domain (const char *username, const char *defdomain)
-+static const char *get_domain (const char *username, const char *defdomain,
-+                             const char *separators)
- {
- static char   domain_buf[260];
- const char    *p;
- char          *q;
-       
--      if (!username || *username == '\0')     return NULL;
--      p = strchr(username,'@');
-+      if (!username || *username == '\0' ||
-+          !separators || *separators == '\0') return NULL;
-+      
-+      p = strpbrk (username, separators);
-       
-       if (!p || *(p+1) == '\0')
-       {
--              if (defdomain && *defdomain)
-+              if (defdomain && *defdomain != '\0')
-                       return defdomain;
-               else
--                      return NULL;
-+                {
-+                  *domain_buf = '\0';
-+                  return domain_buf;
-+                }
-       }
-       p++;
-@@ -536,20 +567,27 @@
- /* siefca@pld.org.pl */
- static char *parse_select_clause (const char *clause, const char *username,
--                                const char *defdomain)
-+                                const char *defdomain,
-+                                const char *concat_str,
-+                                const char *separators_set)
- {
- static struct var_data vd[]={
-           {"local_part",      NULL,   sizeof("local_part"),   0},
-           {"domain",          NULL,   sizeof("domain"),       0},
-+          {"username",        NULL,   sizeof("username"),     0},
-           {NULL,              NULL,   0,                      0}};
-       if (clause == NULL || *clause == '\0' ||
--          !username || *username == '\0')
-+          !username || *username == '\0' ||
-+          !concat_str || *concat_str == '\0' ||
-+          !separators_set || *separators_set == '\0')
-               return NULL;
-       
--      vd[0].value     = get_localpart (username);
--      vd[1].value     = get_domain (username, defdomain);
--      if (!vd[0].value || !vd[1].value)
-+      vd[0].value     = get_localpart (username, separators_set);
-+      vd[1].value     = get_domain (username, defdomain, separators_set);
-+      vd[2].value     = get_username (vd[0].value, vd[1].value, concat_str);
-+
-+      if (!vd[0].value || !vd[1].value || !vd[2].value)
-               return NULL;
-       
-       return (parse_string (clause, vd));
-@@ -557,12 +595,16 @@
- /* siefca@pld.org.pl */
- static char *parse_chpass_clause (const char *clause, const char *username,
--                                const char *defdomain, const char *newpass,
-+                                const char *defdomain,
-+                                const char *separators_set,
-+                                const char *concat_str,
-+                                const char *newpass,
-                                 const char *newpass_crypt)
- {
- static struct var_data vd[]={
-           {"local_part",      NULL,   sizeof("local_part"),           0},
-           {"domain",          NULL,   sizeof("domain"),               0},
-+          {"username",        NULL,   sizeof("username"),             0},
-           {"newpass",         NULL,   sizeof("newpass"),              0},
-           {"newpass_crypt",   NULL,   sizeof("newpass_crypt"),        0},
-           {NULL,              NULL,   0,                              0}};
-@@ -570,19 +612,83 @@
-       if (clause == NULL || *clause == '\0'           ||
-           !username || *username == '\0'              ||
-           !newpass || *newpass == '\0'                ||
-+          !separators_set || *separators_set == '\0'  ||
-           !newpass_crypt || *newpass_crypt == '\0')   return NULL;
--      vd[0].value     = get_localpart (username);
--      vd[1].value     = get_domain (username, defdomain);
--      vd[2].value     = validate_password (newpass);
--      vd[3].value     = validate_password (newpass_crypt);
-+      vd[0].value     = get_localpart (username, separators_set);
-+      vd[1].value     = get_domain (username, defdomain, separators_set);
-+      vd[3].value     = get_username (vd[0].value, vd[1].value, concat_str);
-+      vd[4].value     = validate_password (newpass);
-+      vd[5].value     = validate_password (newpass_crypt);
-       
-       if (!vd[0].value || !vd[1].value ||
--          !vd[2].value || !vd[3].value)       return NULL;
-+          !vd[2].value || !vd[3].value ||
-+          !vd[4].value || !vd[5].value)       return NULL;
-       return (parse_string (clause, vd));
- }
-+/* siefca@pld.org.pl */
-+int auth_mysql_on_trigger (const char *clause_name, const char *username)
-+{
-+char          *querybuf       =NULL;
-+const char    *concat_str     =NULL,
-+              *separators_set =NULL,
-+              *defdomain      =NULL,
-+              *on_clause      =NULL;
-+MYSQL_RES     *result;
-+
-+      if (!clause_name || *clause_name == '\0') return (0);
-+      on_clause = read_env (clause_name);
-+      if (!on_clause || *on_clause == '\0')   return (1);
-+
-+      defdomain = read_env ("DEFAULT_DOMAIN");        
-+      concat_str = read_env ("USER_DOMAIN_CONCAT");
-+      separators_set = read_env ("USER_DOMAIN_SEPARATORS");
-+      if (!defdomain) defdomain = "";
-+      if (!concat_str || *concat_str == '\0')
-+              concat_str = DEF_CONCAT_STRING;
-+      if (!separators_set || *separators_set == '\0')
-+              separators_set = DEF_SEPARATORS_SET;
-+      
-+      querybuf = parse_select_clause (on_clause,
-+                                      username,
-+                                      defdomain,
-+                                      concat_str,
-+                                      separators_set);
-+      
-+      if (!querybuf)  return (0);
-+
-+      if (mysql_query (mysql, querybuf))
-+      {
-+              /* <o.blasnik@nextra.de> */
-+
-+              auth_mysql_cleanup();
-+
-+              if (do_connect())
-+              {
-+                      free(querybuf);
-+                      return (1);
-+              }
-+
-+              if (mysql_query (mysql, querybuf))
-+              {
-+                      free(querybuf);
-+                      auth_mysql_cleanup();
-+                      /* Server went down, that's OK,
-+                      ** try again next time.
-+                      */
-+                      return (1);
-+              }
-+      }
-+      free(querybuf);
-+      result = mysql_store_result(mysql);
-+      if (result) mysql_free_result(result);
-+      
-+      return (1);
-+}
-+
-+
- struct authmysqluserinfo *auth_mysql_getuserinfo(const char *username)
- {
- const char *user_table        =NULL;
-@@ -601,6 +707,8 @@
-           *gid_field          =NULL,
-           *quota_field        =NULL,
-           *where_clause       =NULL,
-+          *concat_str         =NULL,
-+          *separators_set     =NULL,
-           *select_clause      =NULL; /* siefca@pld.org.pl */
- static const char query[]=
-@@ -709,7 +817,19 @@
-       else
-       {
-               /* siefca@pld.org.pl */
--              querybuf=parse_select_clause (select_clause, username, defdomain);
-+              concat_str = read_env ("USER_DOMAIN_CONCAT");
-+              separators_set = read_env ("USER_DOMAIN_SEPARATORS");
-+
-+              if (!concat_str || *concat_str == '\0')
-+                      concat_str = DEF_CONCAT_STRING;
-+              if (!separators_set || *separators_set == '\0')
-+                      separators_set = DEF_SEPARATORS_SET;
-+
-+              querybuf = parse_select_clause (select_clause,
-+                                              username,
-+                                              defdomain,
-+                                              concat_str,
-+                                              separators_set);
-               if (!querybuf) return 0;
-       }
-@@ -793,6 +913,8 @@
-                   *where_clause       =NULL,
-                   *user_table         =NULL,
-                   *login_field        =NULL,
-+                  *concat_str        =NULL,
-+                  *separators_set     =NULL,  
-                   *chpass_clause      =NULL; /* siefca@pld.org.pl */
-       if (!mysql)
-@@ -842,13 +964,22 @@
-       }
-       else
-       {
-+              concat_str = read_env ("USER_DOMAIN_CONCAT");
-+                separators_set = read_env ("USER_DOMAIN_SEPARATORS");
-+              
-+              if (!concat_str || *concat_str == '\0')
-+                      concat_str = DEF_CONCAT_STRING;
-+              if (!separators_set || *separators_set == '\0')
-+                      separators_set = DEF_SEPARATORS_SET;
-+              
-               sql_buf=parse_chpass_clause(chpass_clause,
-                                           user,
-                                           defdomain,
-+                                          concat_str,
-+                                          separators_set,
-                                           pass,
-                                           newpass_crypt_ptr);
-       }
--      
-       if (!sql_buf)
-       {
-diff -ur courier-imap-1.5.3.20020921.orig/authlib/authmysqlrc courier-imap-1.5.3.20020921/authlib/authmysqlrc
---- courier-imap-1.5.3.20020921.orig/authlib/authmysqlrc       Thu Apr  4 06:36:29 2002
-+++ courier-imap-1.5.3.20020921/authlib/authmysqlrc    Sat Sep 28 02:46:41 2002
-@@ -1,4 +1,4 @@
--##VERSION: $Id$
-+##VERSION: $Id$
- #
- # Copyright 2000 Double Precision, Inc.  See COPYING for
- # distribution information.
-@@ -141,65 +141,99 @@
- #
- # MYSQL_WHERE_CLAUSE  server='mailhost.example.com'
--##NAME: MYSQL_SELECT_CLAUSE:0
--#
--# (EXPERIMENTAL)
--# This is optional, MYSQL_SELECT_CLAUSE can be set when you have a database,
--# which is structuraly different from proposed. The fixed string will
--# be used to do a SELECT operation on database, which should return fields
--# in order specified bellow:
--#
--# username, cryptpw, uid, gid, clearpw, home, maildir, quota, fullname
-+##NAME: USER_DOMAIN_CONCAT:0
- #
--# Enabling this option causes ignorance of any other field-related
--# options, excluding default domain.
-+# This is optional. Here, you can write the string used to concatenate
-+# username with domain part while expanding the $(username) substitution
-+# variable. If it's not set the '@' character is used.
-+# See README.authmysql.myownquery for more information
- #
--# There are two variables, which you can use. Substitution will be made
--# for them, so you can put entered username (local part) and domain name
--# in the right place of your query. These variables are:
--#             $(local_part) and $(domain)
-+# USER_DOMAIN_CONCAT  @
-+
-+##NAME: USER_DOMAIN_SEPARATORS:0
- #
--# If a $(domain) is empty (not given by the remote user) the default domain
--# name is used in its place.
-+# This is optional. Using this option you can set the set of characters
-+# which are treated as separators when splitting entered username into the
-+# local part and the domain name. If it's not set the defaults @% are used,
-+# so the user can authenticate using user@domain or user%domain form.
-+# See README.authmysql.myownquery for more information
- #
--# This example is a little bit modified adaptation of vmail-sql
--# database scheme:
-+# USER_DOMAIN_SEPARATORS      @%+
-+
-+##NAME: MYSQL_SELECT_CLAUSE:0
- #
--# MYSQL_SELECT_CLAUSE SELECT popbox.local_part,                       \
--#                     CONCAT('{MD5}', popbox.password_hash),          \
--#                     popbox.clearpw,                                 \
--#                     domain.uid,                                     \
--#                     domain.gid,                                     \
--#                     CONCAT(domain.path, '/', popbox.mbox_name),     \
--#                     '',                                             \
--#                     domain.quota,                                   \
--#                     '',                                             \
--#                     FROM popbox, domain                             \
--#                     WHERE popbox.local_part = '$(local_part)'       \
--#                     AND popbox.domain_name = '$(domain)'            \
--#                     AND popbox.domain_name = domain.domain_name
-+# This is optional, MYSQL_SELECT_CLAUSE can be set when you have a database,
-+# which is structuraly different from proposed. You can type here your MySQL
-+# query, which will be used to fetch user's credentials, and which should
-+# return fields in order specified bellow:
-+#
-+# username, cryptpw, clearpw, uid, gid, home, maildir, quota, fullname
-+#
-+# Enabling this option causes ignorance of any other field-related options.
-+#
-+# There also are variables, which you can use. Substitution will be made
-+# for them, so you can pass currently entered username and a domain name
-+# up to the right place within your query. These variables are:
-+# $(local_part) , $(domain) , $(username)
- #
-+# If a $(domain) is empty (not given by the remote user) the default domain
-+# name is used in its place. $(username) is a local part concatenated with
-+# domain name using symbol defined in USER_DOMAIN_CONCAT or '@' if this option
-+# is not set.
-+# See README.authmysql.myownquery for more information
-+#
-+# MYSQL_SELECT_CLAUSE SELECT                                  \
-+# users.username, users.cryptpw, users.clearpw,                       \
-+# domains.uid, domains.gid,                                   \
-+# CONCAT_WS('/',domains.path_prefix,users.mailbox_path),      \
-+# '', domains.quota, ''                                               \
-+# FROM users, domains                                         \
-+#  WHERE domains.domain_name='$(domain)'                      \
-+#    AND users.username='$(local_part)'                               \
-+#    AND domains.domain_name=users.domain_name
-+
- ##NAME: MYSQL_CHPASS_CLAUSE:0
- #
--# (EXPERIMENTAL)
- # This is optional, MYSQL_CHPASS_CLAUSE can be set when you have a database,
--# which is structuraly different from proposed. The fixed string will
--# be used to do an UPDATE operation on database. In other words, it is
--# used, when changing password.
-+# which is structuraly different from proposed. You can use it to set up
-+# a MySQL query used to change user's password.
- #
- # There are four variables, which you can use. Substitution will be made
--# for them, so you can put entered username (local part) and domain name
--# in the right place of your query. There variables are:
--#     $(local_part) , $(domain) , $(newpass) , $(newpass_crypt)
-+# for them, so you can put the currently entered username and the domain name
-+# in the right place of your query. These variables are:
-+# $(local_part) , $(domain) , $(username) , $(newpass) , $(newpass_crypt)
- #
- # If a $(domain) is empty (not given by the remote user) the default domain
--# name is used in its place.
--# $(newpass) contains plain password
--# $(newpass_crypt) contains its crypted form
--#
--# MYSQL_CHPASS_CLAUSE UPDATE  popbox                                  \
--#                     SET     clearpw='$(newpass)',                   \
--#                             password_hash='$(newpass_crypt)'        \
--#                     WHERE   local_part='$(local_part)'              \
--#                     AND     domain_name='$(domain)'
-+# name is used in its place. $(newpass) contains plain password and
-+# $(newpass_crypt) contains its crypted form.
-+# See README.authmysql.myownquery for more information
-+#
-+# MYSQL_CHPASS_CLAUSE UPDATE users            \
-+# SET clearpw='$(newpass)',                   \
-+#     cryptpw='$(newpass_crypt)'              \
-+# WHERE username='$(local_part)'              \
-+# AND domain_name='$(domain)'
-+
-+##NAME: MYSQL_ONSUCCESS_CLAUSE:0
-+# (EXPERIMENTAL)
-+#
-+# This is optional, MYSQL_ONSUCCESS_CLAUSE is a trigger - the query is performed
-+# each time user has successfuly logged in.
-+# See README.authmysql.myownquery for more information
-+#
-+# MYSQL_ONSUCCESS_CLAUSE      UPDATE users                            \
-+#                             SET last_ok=CURRENT_TIMESTAMP           \
-+#                             WHERE username='$(local_part)'          \
-+#                             AND domain_name='$(domain)'
-+
-+##NAME: MYSQL_ONFAIL_CLAUSE:0
-+# (EXPERIMENTAL)
- #
-+# This is optional, MYSQL_ONFAIL_CLAUSE is a trigger - the query is performed
-+# each time user has successfuly logged in.
-+# See README.authmysql.myownquery for more information
-+#
-+# MYSQL_ONFAIL_CLAUSE         UPDATE users                            \
-+#                             SET last_fail=CURRENT_TIMESTAMP         \
-+#                             WHERE username='$(local_part)'          \
-+#                             AND domain_name='$(domain)'
This page took 0.392924 seconds and 4 git commands to generate.