commit ff74814d3e7c0c60fb42099ca55c1b945dfedde6 Author: Mischa Peters Date: Sat Mar 24 07:27:00 2007 +0000 Initial Import in SourceForge git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/tags/postfixadmin-2.0.0@1 a1433add-5e2c-0410-b055-b7f2511e0802 diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT new file mode 100644 index 00000000..ef848bde --- /dev/null +++ b/CHANGELOG.TXT @@ -0,0 +1,111 @@ +############################# +# Postfix Admin Release 2.x # +############################# +# +# 2004 (c) High5! +# Created by: Mischa Peters +# + +Version 2.0.0 -- 2004/01/03 +---------------------------- + - Added: The ability for one domain admin to maintain multiple domains. + - Added: Domain to domain forwarding. + - Added: Mailboxes can now be activated or deactivated. + - Added: Configurable welcome message for new mailboxes. + - Added: Optional sending of welcome message. + - Added: Create alias "To" defaults to current domain. + - Added: Logging of admin / user actions. + - Added: Limit for aliases and/or mailboxes per domain. + - Added: Disable aliases and/or mailboxes per domain. + - Added: Max quota per mailbox per domain. + - Added: Multi-Language support. + - Added: Statistics overview for all domains. + - Added: User .forwarding for mailbox users. + - Added: Logo for Postfix Admin (Thanx Andrew). + - Added: Extra MySQL debugging capabilities. + - Added: Clear text password support. + - Added: PHP crypt() support. + - Changed: Separated logic and SQL from content. + - Changed: config.inc.php doesn't point to example.com anymore. + - Changed: Virtual Vacation no longer requires procmail. + - Changed: Complete re-write. + + +Version 1.5.4 -- 2003/06/16 +---------------------------- + - Added: Option for "Back to". + - Added: Option for Vacation module. + - Added: Table declaration for the use of Quota in the INSTALL.TXT. + This requires an additional local delivery agent. + Quotas are not supported by Postfix! + - Changed: The word "View" to "List". + + +Version 1.5.3 -- 2003/06/06 +---------------------------- + - Fixed: Even more minor bugs in regards to declaration of variables. + (Thanx Aquilante and Kyle_m) + + +Version 1.5.2 -- 2003/06/05 +---------------------------- + - Fixed: Minor bugs in regards to declaration of variables. + + +Version 1.5.1 -- 2003/06/04 +---------------------------- + - Added: Optional mailbox per domain directory structure. (Thanx Jim) + - Added: Option to completely control the stored aliases. (Thanx Alex) + - Change: config.inc.php is renamed to config.inc.php.sample. (Thanx Alex) + - Fixed: $PHP_SELF in config.inc.php and my_lib.php. (Thanx Jim) + + +Version 1.5.0 -- 2003/05/28 +---------------------------- + - Added: Support for "Back to Main Site" + - Added: config.inc.php as the main configuration file. + - Added: Drop down box for domain selection when adding a new admin. + - Added: Resend of test email to newly created mailbox. + - Added: Mailbox and Aliases count for domainview. + - Added: Change description of domain without deleting the complete + domain. + - Added: Change name of mailbox user without deleting the mailbox. + - Added: Expire headers for unnecessary reloads. (Thanx Alex) + - Removed: Completely removed the site_lib.php. + - Removed: my_lib.php from the admin directory. + - Removed: Symlink to index.php. + - Fix: Code clean up. + - Fix: Minor bugs and cosmetic fixes. + - Fix: Modified check_string() to check numbers and returns false if not + matched. (Thanx btaber) + - Fix: Correct session handling in login.php (Thanx Yen-Wei Liu) + - Fix: Correct deletion of RFC822 email addresses. (Thanx Yen-Wei Liu) + + +Version 1.4.0 -- 2003/04/07 +---------------------------- + - Added: When deleting a domain, all aliases and mailboxes for that domain + are also deleted from the database. + - Added: Add standard aliases for every domain that is created. + These aliases can point to the main "local" administrator. + The aliases are configured in the config.php in the admin directory. + - Change: The layout of my_lib.php and site_lib.php have been changed. + - Change: Modifying an alias is now done with TEXTAREA for more + flexibility. + - Fix: Minor bugs and cosmetic fixes. + + +Version 1.3.8a -- 2003/03/31 +---------------------------- + - Fix: After deletion of a domain it would not return to the correct page. + + +Version 1.3.8 -- 2003/03/25 +---------------------------- + - Added: Admin password change. No longer needed to delete and re-enter + the admin user for a specific domain. + + +Version 1.3.7 -- 2002/12/24 +---------------------------- + - Initial public release of Postfix Admin. diff --git a/DATABASE.TXT b/DATABASE.TXT new file mode 100644 index 00000000..f3ba41f3 --- /dev/null +++ b/DATABASE.TXT @@ -0,0 +1,133 @@ +############################# +# Postfix Admin Release 2.x # +############################# +# +# 2004 (c) High5! +# Created by: Mischa Peters +# +# This is the complete database structure for Postfix Admin. +# If you are installing from scratch you can use this file otherwise you +# need to use the upgrader that comes with Postfix Admin. +# +# There are 2 entries for a database user in the file. +# One you can use for Postfix and one for Postfix Admin. +# +# You can create the database from the shell with: +# +# mysql -u root [-p] < DATABASE.TXT + +# +# Postfix / MySQL +# +USE mysql; +# Postfix user & password +INSERT INTO user (Host, User, Password) VALUES ('localhost','postfix',password('postfix')); +INSERT INTO db (Host, Db, User, Select_priv) VALUES ('localhost','postfix','postfix','Y'); +# Postfix Admin user & password +INSERT INTO user (Host, User, Password) VALUES ('localhost','postfixadmin',password('postfixadmin')); +INSERT INTO db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv) VALUES ('localhost', 'postfix', 'postfixadmin', 'Y', 'Y', 'Y', 'Y'); +FLUSH PRIVILEGES; +GRANT USAGE ON postfix.* TO postfix@localhost; +GRANT SELECT, INSERT, DELETE, UPDATE ON postfix.* TO postfix@localhost; +GRANT USAGE ON postfix.* TO postfixadmin@localhost; +GRANT SELECT, INSERT, DELETE, UPDATE ON postfix.* TO postfixadmin@localhost; +CREATE DATABASE postfix; +USE postfix; + +# +# Table structure for table admin +# +CREATE TABLE admin ( + username varchar(255) NOT NULL default '', + password varchar(255) NOT NULL default '', + created datetime NOT NULL default '0000-00-00 00:00:00', + modified datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + PRIMARY KEY (username), + KEY username (username) +) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Admins'; + +# +# Table structure for table alias +# +CREATE TABLE alias ( + address varchar(255) NOT NULL default '', + goto text NOT NULL, + domain varchar(255) NOT NULL default '', + created datetime NOT NULL default '0000-00-00 00:00:00', + modified datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + PRIMARY KEY (address), + KEY address (address) +) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Aliases'; + +# +# Table structure for table domain +# +CREATE TABLE domain ( + domain varchar(255) NOT NULL default '', + description varchar(255) NOT NULL default '', + aliases int(10) NOT NULL default '-1', + mailboxes int(10) NOT NULL default '-1', + maxquota int(10) NOT NULL default '-1', + created datetime NOT NULL default '0000-00-00 00:00:00', + modified datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + PRIMARY KEY (domain), + KEY domain (domain) +) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Domains'; + +# +# Table structure for table domain_admins +# +CREATE TABLE domain_admins ( + username varchar(255) NOT NULL default '', + domain varchar(255) NOT NULL default '', + created datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + KEY username (username) +) TYPE=MyISAM COMMENT='Postfix Admin - Domain Admins'; + +# +# Table structure for table log +# +CREATE TABLE log ( + timestamp datetime NOT NULL default '0000-00-00 00:00:00', + username varchar(255) NOT NULL default '', + domain varchar(255) NOT NULL default '', + action varchar(255) NOT NULL default '', + data varchar(255) NOT NULL default '', + KEY timestamp (timestamp) +) TYPE=MyISAM COMMENT='Postfix Admin - Log'; + +# +# Table structure for table mailbox +# +CREATE TABLE mailbox ( + username varchar(255) NOT NULL default '', + password varchar(255) NOT NULL default '', + name varchar(255) NOT NULL default '', + maildir varchar(255) NOT NULL default '', + quota int(10) NOT NULL default '-1', + domain varchar(255) NOT NULL default '', + created datetime NOT NULL default '0000-00-00 00:00:00', + modified datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + PRIMARY KEY (username), + KEY username (username) +) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Mailboxes'; + +# +# Table structure for table vacation +# +CREATE TABLE vacation ( + email varchar(255) NOT NULL default '', + subject varchar(255) NOT NULL default '', + body text NOT NULL, + cache text NOT NULL, + domain varchar(255) NOT NULL default '', + created datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + PRIMARY KEY (email), + KEY email (email) +) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Vacation'; diff --git a/INSTALL.TXT b/INSTALL.TXT new file mode 100644 index 00000000..b7136b65 --- /dev/null +++ b/INSTALL.TXT @@ -0,0 +1,77 @@ +############################# +# Postfix Admin Release 2.x # +############################# +# +# 2004 (c) High5! +# Created by: Mischa Peters +# + +REQUIRED!! +---------- +- You are using Postfix 2.0 or higher. +- You are using Apache 1.3.27 or higher. +- You are using PHP 4.1 or higher. +- You are using MySQL 3.23.55 or higher. + + +READ THIS FIRST! +---------------- +When this is an upgrade from Postfix Admin 1.5.4 please read UPGRADE.TXT!! +If you used the table structure from the Howto please read the UPGRADE.TXT!! + + +1. Unarchive new Postfix Admin +------------------------------ +Make sure that you are in your WWW directory and then unarchive the +Postfix Admin archive (whatever the filename is): + + $ tar -zxvf postfixadmin-2.0.0.tgz + + +2. Change permissions +---------------------- +Since the database password is stored in the config.inc.php it's a good idea +to have Postfix Admin set to the permission of the webserver. In this +example, we assume that user "www" and group "www" are the web server as is +often the case with Apache. + + $ cd /usr/local/www + $ chown -R www:www postfixadmin-2.0.0 + +This is also a good idea for the file permissions. + + $ cd /usr/local/www/postfixadmin-2.0.0 + $ chmod 640 *.php *.css + $ cd /usr/local/www/postfixadmin-2.0.0/admin/ + $ chmod 640 *.php *.css + $ cd /usr/local/www/postfixadmin-2.0.0/users/ + $ chmod 640 *.php *.css + $ cd /usr/local/www/postfixadmin-2.0.0/templates/ + $ chmod 640 *.php *.css + +Additionally, if "chown user:group" doesn't work, you can use "chown user" +and "chgrp group" instead. See the man pages for these commands for more +information. + + +3. Create the MySQL Tables +-------------------------- +In DATABASE.TXT you can find the table structure that you need in order to +configure Postfix Admin and Postfix in general to work with Virtual Domains +and Users + + +4. Configure +------------ +Check the config.inc.php file. There you can specify settings that are +relevant to your setup. + +The default password for the admin part of Postfix Admin is admin/admin. +This is specified in the .htpasswd file in the admin directory. Make sure +that the location of the .htpasswd file matches your path. + + +5. Done +------- +This is all that is needed. Fire up your browser and go to the site that you +specified to host Postfix Admin. diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 00000000..e6cedfce --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,50 @@ +License for Postfix Admin: + + The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is Postfix Admin. + + The Initial Developer of the Original Code is Mischa Peters . + Portions created by Mischa Peters are Copyright (c) 2002, 2003, 2004. + All Rights Reserved. + + Contributor(s): + + +This project includes work by Mischa Peters and others that is: + + Copyright (c) 2002,2003,2004 Mischa Peters + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the names of the copyright holders nor the names of the XLW + Group and its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/TABLE_CHANGES.TXT b/TABLE_CHANGES.TXT new file mode 100644 index 00000000..68ef3c6e --- /dev/null +++ b/TABLE_CHANGES.TXT @@ -0,0 +1,102 @@ +############################# +# Postfix Admin Release 2.x # +############################# +# +# 2004 (c) High5! +# Created by: Mischa Peters +# +# mysql -u root [-p] < TABLE_CHANGES.TXT + +# +# Table structure for table domain_admins +# +USE postfix; +CREATE TABLE IF NOT EXISTS domain_admins ( + username varchar(255) NOT NULL default '', + domain varchar(255) NOT NULL default '', + created datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + KEY username (username) +) TYPE=MyISAM COMMENT='Postfix Admin - Domain Admins'; + +# +# Table structure for table log +# +CREATE TABLE IF NOT EXISTS log ( + timestamp datetime NOT NULL default '0000-00-00 00:00:00', + username varchar(255) NOT NULL default '', + domain varchar(255) NOT NULL default '', + action varchar(255) NOT NULL default '', + data varchar(255) NOT NULL default '', + KEY timestamp (timestamp) +) TYPE=MyISAM COMMENT='Postfix Admin - Log'; + +# +# Table structure for table vacation +# +CREATE TABLE IF NOT EXISTS vacation ( + email varchar(255) NOT NULL default '', + subject varchar(255) NOT NULL default '', + body text NOT NULL, + cache text NOT NULL, + domain varchar(255) NOT NULL default '', + created datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + PRIMARY KEY (email), + KEY email (email) +) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Vacation'; + +# +# Modify table structure for table admin +# +ALTER TABLE admin CHANGE create_date created DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL; +ALTER TABLE admin CHANGE change_date modified DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL; +ALTER TABLE admin ADD INDEX (username); + +# +# Modify table structure for table alias +# +ALTER TABLE alias CHANGE create_date created DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL; +ALTER TABLE alias CHANGE change_date modified DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL; +ALTER TABLE alias ADD INDEX (address); + +# +# Modify table structure for table domain +# +ALTER TABLE domain CHANGE create_date created DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL; +ALTER TABLE domain CHANGE change_date modified DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL; +ALTER TABLE domain ADD aliases INT(10) DEFAULT '-1' NOT NULL AFTER description; +ALTER TABLE domain ADD mailboxes INT(10) DEFAULT '-1' NOT NULL AFTER aliases; +ALTER TABLE domain ADD maxquota INT(10) DEFAULT '-1' NOT NULL AFTER mailboxes; +ALTER TABLE domain ADD INDEX (domain); + +# +# Modify table structure for table mailbox +# +ALTER TABLE mailbox CHANGE create_date created DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL; +ALTER TABLE mailbox CHANGE change_date modified DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL; +ALTER TABLE mailbox ADD quota INT(10) DEFAULT '-1' NOT NULL AFTER maildir; +ALTER TABLE mailbox ADD INDEX (username); + +# +# Modify table structure for table vacation +# +ALTER TABLE vacation ADD domain VARCHAR(255) DEFAULT '' NOT NULL AFTER cache; +ALTER TABLE vacation ADD created DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL AFTER domain; +ALTER TABLE vacation ADD active TINYINT(4) DEFAULT '' NOT NULL AFTER created; +ALTER TABLE vacation DROP PRIMARY KEY, ADD PRIMARY KEY(email); + +# +# Dumping data for table domain_admins +# +INSERT INTO domain_admins (username,domain,created) SELECT admin.username,admin.domain,domain.created FROM admin LEFT JOIN domain ON domain.domain=admin.domain; + +# +# Modify data for table vacation +# +UPDATE vacation SET domain=SUBSTRING_INDEX(email, '@', -1) WHERE email=email; + +# +# Modify table structure for table domain +# +ALTER TABLE admin DROP domain; diff --git a/UPGRADE.TXT b/UPGRADE.TXT new file mode 100644 index 00000000..5580be54 --- /dev/null +++ b/UPGRADE.TXT @@ -0,0 +1,84 @@ +############################# +# Postfix Admin Release 2.x # +############################# +# +# 2004 (c) High5! +# Created by: Mischa Peters +# + +REQUIRED!! +---------- +- You are using Postfix 2.0 or higher. +- You are using Apache 1.3.27 or higher. +- You are using PHP 4.1 or higher. +- You are using MySQL 3.23.55 or higher. + + +READ THIS FIRST! +---------------- +It's recommened that you install Postfix Admin in a new folder and not +on-top of the old install!! +Make sure you backup your database before you run the TABLE_CHANGES.TXT on +your database. + + +1. Backup the Database +---------------------- +When you install from a previous version make sure you backup your database +first. There are a lot of changes in the database structure since Postfix Admin +1.5.4. + + $ mysqldump -a -u root -p > /tmp/postfixadmin-backup.sql + + +2. Unarchive new Postfix Admin +------------------------------ +Make sure that you are in your WWW directory and then unarchive the +Postfix Admin archive (whatever the filename is): + + $ tar -zxvf postfixadmin-2.0.0.tgz + + +3. Change permissions +---------------------- +Since the database password is stored in the config.inc.php it's a good idea +to have Postfix Admin set to the permission of the webserver. In this +example, we assume that user "www" and group "www" are the web server as is +often the case with Apache. + + $ cd /usr/local/www + $ chown -R www:www postfixadmin-2.0.0 + +This is also a good idea for the file permissions. + + $ cd /usr/local/www/postfixadmin-2.0.0 + $ chmod 640 *.php *.css + $ cd /usr/local/www/postfixadmin-2.0.0/admin/ + $ chmod 640 *.php *.css + $ cd /usr/local/www/postfixadmin-2.0.0/users/ + $ chmod 640 *.php *.css + $ cd /usr/local/www/postfixadmin-2.0.0/templates/ + $ chmod 640 *.php *.css + +Additionally, if "chown user:group" doesn't work, you can use "chown user" +and "chgrp group" instead. See the man pages for these commands for more +information. + + +4. Modify the MySQL Tables +-------------------------- +In TABLE_CHANGES.TXT you can find the table structure that you need in order +to configure Postfix Admin 2.0.0 and Postfix in general to work with Virtual +Domains and Users + + +5. Configure +------------ +Check the config.inc.php file. There you can specify settings that are +relevant to your setup. + + +6. Done +------- +This is all that is needed. Fire up your browser and go to the site that you +specified to host Postfix Admin. diff --git a/VIRTUAL_VACATION/FILTER_README b/VIRTUAL_VACATION/FILTER_README new file mode 100644 index 00000000..e403b523 --- /dev/null +++ b/VIRTUAL_VACATION/FILTER_README @@ -0,0 +1,512 @@ +Introduction +============ + +This is a very first implementation of Postfix content filtering. +A Postfix content filter receives unfiltered mail from Postfix and +does one of the following: + +- re-injects the mail back into Postfix, perhaps after changing content +- rejects the mail (by sending a suitable status code back to + Postfix) so that it is returned to sender. +- sends the mail somewhere else + +This document describes two approaches to content filtering: simple +and advanced. Both filter all the mail by default. + +At the end are examples that show how to filter only mail from +users, about using different filters for different domains that +you provide MX service for, and about selective filtering on the +basis of message envelope and/or header/body patterns. + +Simple content filtering example +================================ + +The first example is simple to set up. It uses a shell script that +receives unfiltered mail from the Postfix pipe delivery agent, and +that feeds filtered mail back into the Postfix sendmail command. + +Only mail arriving via SMTP will be content filtered. + + .................................. + : Postfix : +Unfiltered mail----->smtpd \ /local---->Filtered mail + : -cleanup->queue- : + ---->pickup / \smtp----->Filtered mail + ^ : | : + | : \pipe-----+ + | .................................. | + | | + | | + +-Postfix sendmail<----filter script<--+ + +Mail is filtered by a /some/where/filter program. This can be a +simple shell script like this: + + #!/bin/sh + + # Localize these. + INSPECT_DIR=/var/spool/filter + SENDMAIL="/usr/sbin/sendmail -i" + + # Exit codes from + EX_TEMPFAIL=75 + EX_UNAVAILABLE=69 + + # Clean up when done or when aborting. + trap "rm -f in.$$" 0 1 2 3 15 + + # Start processing. + cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; } + + cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; } + + # filter smtpd \ /local----> + : -cleanup->queue- : + ---->pickup / ^ | \smtp-----> + : | v : + : smtpd smtp : + : 10026 | : + ......................|........... + ^ | + | v + ....|............ + : | 10025 : + : filter : + : : + ................. + +To enable content filtering in this manner, specify in main.cf a +new parameter: + + /etc/postfix/main.cf: + content_filter = scan:localhost:10025 + +This causes Postfix to add one extra content filtering record to +each incoming mail message, with content scan:localhost:10025. +The content filtering records are added by the smtpd and pickup +servers. + +When a queue file has content filtering information, the queue +manager will deliver the mail to the specified content filter +regardless of its final destination. + +In this example, "scan" is an instance of the Postfix SMTP client +with slightly different configuration parameters. This is how +one would set up the service in the Postfix master.cf file: + + /etc/postfix/master.cf: + scan unix - - n - 10 smtp + +Instead of a limit of 10 concurrent processes, use whatever process +limit is feasible for your machine. Content inspection software +can gobble up a lot of system resources, so you don't want to have +too much of it running at the same time. + +The content filter can be set up with the Postfix spawn service, +which is the Postfix equivalent of inetd. For example, to instantiate +up to 10 content filtering processes on demand: + + /etc/postfix/master.cf: + localhost:10025 inet n n n - 10 spawn + user=filter argv=/some/where/filter localhost 10026 + +"filter" is a dedicated local user account. The user will never +log in, and can be given a "*" password and non-existent shell and +home directory. This user handles all potentially dangerous mail +content - that is why it should be a separate account. + +In the above example, Postfix listens on port localhost:10025. If +you want to have your filter listening on port localhost:10025 +instead of Postfix, then you must run your filter as a stand-alone +program. + +Note: the localhost port 10025 SMTP server filter should announce +itself as "220 localhost...". Postfix aborts delivery when it +connects to an SMTP server that uses the same hostname as Postfix +("host greeted me with my own hostname"), because that +normally means you have a mail delivery loop problem. + +The example here assumes that the /some/where/filter command is a +PERL script. PERL has modules that make talking SMTP easy. The +command-line specifies that mail should be sent back into Postfix +via localhost port 10026. + +The simplest content filter just copies SMTP commands and data +between its inputs and outputs. If it has a problem, all it has to +do is to reply to an input of `.' with `550 content rejected', and +to disconnect without sending `.' on the connection that injects +mail back into Postfix. + +The job of the content filter is to either bounce mail with a +suitable diagnostic, or to feed the mail back into Postfix through +a dedicated listener on port localhost 10026: + + /etc/postfix/master.cf: + localhost:10026 inet n - n - 10 smtpd + -o content_filter= + -o local_recipient_maps= + -o relay_recipient_maps= + -o myhostname=localhost.domain.tld + -o smtpd_helo_restrictions= + -o smtpd_client_restrictions= + -o smtpd_sender_restrictions= + -o smtpd_recipient_restrictions=permit_mynetworks,reject + -o mynetworks=127.0.0.0/8 + +Warning for Postfix version 2 users: in this SMTP server after the +content filter, do not override main.cf settings for virtual_alias_maps +or virtual_alias_domains. That would cause mail to be rejected with +"User unknown". + +This SMTP server has the same process limit as the "filter" master.cf +entry. + +The "-o content_filter=" requests no content filtering for incoming +mail. + +The "-o local_recipient_maps=" and "-o relay_recipient_maps=" avoid +unnecessary table lookups. + +The "-o myhostname=localhost.domain.tld" avoids false alarms ("host + greeted me with my own hostname") if your content +filter is based on a proxy that simply relays SMTP commands. + +The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8" +turn off UCE controls that would only waste time here. + +Squeezing out more performance +============================== + +Many refinements are possible, such as running a specially-configured +smtp delivery agent for feeding mail into the content filter, and +turning off address rewriting before content filtering. + +As the example below shows, things quickly become very complex, +because a lot of main.cf like information gets listed in the +master.cf file. This makes the system hard to understand. + +Even worse, details change as Postfix evolves and different +configuration parameters are implemented by different programs. + +If you need to squeeze out more performance, it is probably simpler +to run multiple Postfix instances, one before and one after the +content filter. That way, each instance can have simple main.cf +and master.cf files, each instance can have its own mail queue, +and the system will be easier to understand. + +As before, we will set up a content filtering program that receives +SMTP mail via localhost port 10025, and that submits SMTP mail back +into Postfix via localhost port 10026. + + ....................................... + : Postfix : + ----->smtpd \ : + : -pre-cleanup-\ /local----> + ---->pickup / -queue- : + : -cleanup-/ | \smtp-----> + : bounces/ ^ v : + : and locally | v : + : forwarded smtpd scan : + : messages 10026 | : + ...........................|........... + ^ | + | v + ....|............. + : | 10025 : + : filter : + : : + .................. + +To enable content filtering in this manner, specify in main.cf a +new parameter: + +/etc/postfix/main.cf: + content_filter = scan:localhost:10025 + +/etc/postfix/master.cf: +# +# These are the usual input "smtpd" and local "pickup" servers already +# present in master.cf. We add an option to select a non-default +# cleanup service (defined further below). +# +smtp inet n - n - - smtpd + -o cleanup_service_name=pre-cleanup +pickup fifo n - n 60 1 pickup + -o cleanup_service_name=pre-cleanup +# +# ------------------------------------------------------------------ +# +# This is the cleanup daemon that handles messages in front of +# the content filter. It does header_checks and body_checks (if +# any), but does no virtual alias or canonical address mapping, +# so that mail passes through your content filter with the original +# recipient addresses mostly intact. +# +# Virtual alias or canonical address mapping happens in the second +# cleanup phase after the content filter. This gives the content_filter +# access to *largely* unmodified addresses for maximum flexibility. +# +# Some sites may specifically want to perform canonical or virtual +# address mapping in front of the content_filter. In that case you +# still have to enable address rewriting in the after-filter cleanup +# instance, in order to correctly process forwarded mail or bounced +# mail. +# +pre-cleanup unix n - n - 0 cleanup + -o canonical_maps= + -o sender_canonical_maps= + -o recipient_canonical_maps= + -o masquerade_domains= + -o virtual_alias_maps= +# +# ------------------------------------------------------------------ +# +# This is the delivery agent that injects mail into the content +# filter. It is tuned for low concurrency, because most content +# filters burn CPU and use lots of memory. The process limit of 10 +# re-enforces the effect of $default_destination_concurrency_limit. +# Even without an explicit process limit, the concurrency is bounded +# because all messages heading into the content filter have the same +# destination. +# +scan unix - - n - 10 smtp +# +# ------------------------------------------------------------------ +# +# This is the SMTP listener that receives filtered messages from +# the content filter. It *MUST* clear the content_filter +# parameter to avoid loops, and use a different hostname to avoid +# triggering the Postfix SMTP loop detection code. +# +# This "smtpd" uses the normal cleanup service which is also used +# for bounces and for internally forwarded mail. +# +# The parameters from mynetworks onward disable all access +# control other than insisting on connections from one of the IP +# addresses of the host. This is typically overkill, but can +# reduce resource usage, if the default restrictions use lots of +# tables. +# +localhost:10026 inet n - n - - smtpd + -o content_filter= + -o myhostname=localhost.domain.tld + -o local_recipient_maps= + -o relay_recipient_maps= + -o mynetworks=127.0.0.0/8 + -o mynetworks_style=host + -o smtpd_restriction_classes= + -o smtpd_client_restrictions= + -o smtpd_helo_restrictions= + -o smtpd_sender_restrictions= + -o smtpd_recipient_restrictions=permit_mynetworks,reject +# +# Do not override main.cf settings here for virtual_alias_maps or +# virtual_mailbox_maps. This causes mail to be rejected with "User +# unknown in virtual (alias|mailbox) recipient table". +# +# ------------------------------------------------------------------ +# +# This is the normal cleanup daemon for use after content filtering. +# No header or body checks, because those have already been taken +# care of by the pre-cleanup service before the content filter. +# +# The normal cleanup instance does all the virtual alias and canonical +# address mapping that was disabled in the pre-cleanup instance before +# the content filter. This rewriting must be done even when you didn't +# disable address rewriting in the pre-cleanup instance, in order to +# correctly process bounces and locally forwarded mail. +# +cleanup unix n - n - 0 cleanup + -o header_checks= + -o mime_header_checks= + -o nested_header_checks= + -o body_checks= +# +# ------------------------------------------------------------------ +# +# The normal "smtp" delivery agent for contrast with "scan". +# +smtp unix - - n - - smtp + +The above example causes Postfix to add one content filtering record +to each incoming mail message, with content scan:localhost:10025. +You can use the same syntax as in the right-hand side of a Postfix +transport table. The content filtering records are added by the +smtpd and pickup servers. + +The "scan" transport is a dedicated instance of the "smtp" delivery +agent for injecting messages into the SMTP content filter. Using +a dedicated "smtp" transport allows one to tune it for the specific +task of delivering mail to a local content filter (low latency, +low concurrency, throughput dependent on predictably low latency). + +See the previous example for setting up the content filter with +the Postfix spawn service; you can of course use any server that +can be run stand-alone outside the Postfix environment. + +Filtering mail from outside users only +====================================== + +The easiest approach is to configure ONE Postfix instance with TWO +SMTP server addresses in master.cf: + +- One SMTP server address for inside users only that never invokes + content filtering. + +- One SMTP server address for outside users that always invokes + content filtering. + +/etc/postfix.master.cf: + # SMTP service for internal users only, no content filtering. + 1.2.3.4:smtp inet n - n - - smtpd + -o smtpd_client_restrictions=permit_mynetworks,reject + 127.0.0.1:smtp inet n - n - - smtpd + -o smtpd_client_restrictions=permit_mynetworks,reject + + # SMTP service for external users, with content filtering. + 1.2.3.5:smtp inet n - n - - smtpd + -o content_filter=foo:bar + +Getting really nasty +==================== + +The above filtering configurations are static. Mail that follows +a given path is either always filtered or it is never filtered. As +of Postfix 2.0 you can also turn on content filtering on the fly. +The Postfix UCE features allow you to specify a filtering action +on the fly: + + FILTER foo:bar + +You can do this in smtpd access maps as well as the cleanup server's +header/body_checks. This feature must be used with great care: +you must disable all the UCE features in the after-filter smtpd +and cleanup daemons or else you will have a content filtering loop. + +Limitations: + +- There can be only one content filter action per message. + +- FILTER actions from smtpd access maps and header/body_checks take + precedence over filters specified with the main.cf content_filter + parameter. + +- Only the last FILTER action from smtpd access maps or from + header/body_checks takes effect. + +- The same content filter is applied to all the recipients of a + given message. diff --git a/VIRTUAL_VACATION/INSTALL.TXT b/VIRTUAL_VACATION/INSTALL.TXT new file mode 100644 index 00000000..6581f7cc --- /dev/null +++ b/VIRTUAL_VACATION/INSTALL.TXT @@ -0,0 +1,138 @@ +################################################## +# Virtual Vacation for Postfix Admin Release 2.x # +################################################## +# +# 2003 (c) High5! +# Created by: Mischa Peters +# + +REQUIRED! +--------- +You need to have the following installed to be able to use Virtual Vacation. +- Perl5 +- Perl DBI + + +About Virtual Vacation +---------------------- +Virual Vacation is today done with a local shell account that can receive +email. The email is then handled by a Perl script which sends the Vacation +message back to the sender. + + +Install Virtual Vacation +------------------------ + + +1. Create a local account +------------------------- +Create a dedicated local user account called "vacation". +This user handles all potentially dangerous mail content - that is why it +should be a separate account. + +Do not use "nobody", and most certainly do not use "root" or "postfix". The +user will never log in, and can be given a "*" password and non-existent +shell and home directory. + +This should look like this: + +#/etc/passwd +vacation:*:65501:65501::0:0:Virtual Vacation:/nonexistent:/sbin/nologin + + +2. Create a directory +--------------------- +Create a directory, for example /var/spool/vacation, that is accessible +only to the "vacation" user. This is where the content filtering script is +supposed to store its temporary files. + + +3. Define the filter +-------------------- +Define the content filter in the Postfix master file: + +#/etc/postfix/master.cf: +filter unix - n n - - pipe + flags=Rq user=filter argv=/somewhere/filter -f ${sender} -- ${recipient} + +To turn on content filtering for mail arriving via SMTP only, append +"-o content_filter=filter:dummy" to the master.cf entry that defines +the Postfix SMTP server: + +#/etc/postfix/master.cf: +smtp inet ...stuff... smtpd + -o content_filter=filter:dummy + +The content_filter configuration parameter accepts the same syntax as the +right-hand side in a Postfix transport table. + +Execute "postfix reload" to complete the change. + +For more information on filtering in Postfix read the FILTER_README. + +4. Copy the files +----------------- + + $ cp mail-filter /mail-filter + $ cp vacation.pl /vacation.pl + $ chown -R vacation:nogroup + +Which will then look something like: + +-rwx------ 1 vacation nogroup 409 Dec 21 00:00 mail-filter* +-rwx------ 1 vacation nogroup 3356 Dec 21 00:00 vacation.pl* + + +5. Create the table +------------------- + +To use Virtual Vacation with Postfix Admin you need to create an extra table +in the database that is used by Postfix Admin. + +USE postfix; +# +# Table structure for table vacation +# +CREATE TABLE vacation ( + email varchar(255) NOT NULL default '', + subject varchar(255) NOT NULL default '', + body text NOT NULL, + cache text NOT NULL, + domain varchar(255) NOT NULL default '', + created datetime NOT NULL default '0000-00-00 00:00:00', + active tinyint(4) NOT NULL default '1', + PRIMARY KEY (email), + KEY email (email) +) TYPE=MyISAM COMMENT='Postfix Admin - Virtual Vacation'; + + +What do these files do? +----------------------- +mail-filter picks up every single email and pushes it towards the +vacation.pl + +vacation.pl then checks the database to see wether a user is on holiday and +what message to send back. Make sure that vacation.pl is able to communicate +to your databse. In the first couple of lines you have to specify the +database, username and password for it. + +NOTE: In mail-filter make sure that the path to the vacation usrer and +sendmail are correct! + +In vacation.pl make sure that the path to sendmail is correct and that +database information is correct! + + +I'm in trouble! +--------------- +When something is not working there are a couple of files that you can have +a look at. The most important one is your maillog (usually in /var/log/). + +Vacation.pl also has some debugging and logging capabilties. Check the top +of vacation.pl. + + +Done! +----- +When this is all in place you need to have a look at the Postfix Admin +config.inc.php. Here you need to enable Virtual Vacation for the site. diff --git a/VIRTUAL_VACATION/mail-filter b/VIRTUAL_VACATION/mail-filter new file mode 100644 index 00000000..271f4b2d --- /dev/null +++ b/VIRTUAL_VACATION/mail-filter @@ -0,0 +1,17 @@ +#!/bin/sh +FILTER_DIR=/home/vacation +SENDMAIL="/usr/sbin/sendmail -i" +EX_TEMPFAIL=75 +EX_UNAVAILABLE=69 + +trap "rm -rf in.$$" 0 1 2 3 15 + +cd $FILTER_DIR || { echo $FILTER_DIR does not exist; exit $EX_TEMPFAIL; } + +cat > in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; } + +/home/vacation/vacation.pl < in.$$ || { echo Message content rejected; exit $EX_UNAVAILABLE; } + +$SENDMAIL "$@" < in.$$ + +exit $? diff --git a/VIRTUAL_VACATION/vacation.pl b/VIRTUAL_VACATION/vacation.pl new file mode 100644 index 00000000..4e4d94f2 --- /dev/null +++ b/VIRTUAL_VACATION/vacation.pl @@ -0,0 +1,107 @@ +#!/usr/bin/perl -w +# +# Virtual Vacation +# Version 2.5 +# 2003 (c) High5! +# Created by: Mischa Peters +# +use DBI; + +$db_name = "postfix"; +$db_user = "postfixadmin"; +$db_pass = "postfixadmin"; +$sendmail = "/usr/sbin/sendmail"; +$logfile = ""; # specify a file name here for example: vacation.log +$debugfile = ""; # sepcify a file name here for example: vacation.debug + +@input = <>; + +for ($i = 0; $i <= $#input; $i++) { + if ($input[$i] =~ /^From: (.*)\n$/) { $from = lc($1); } + if ($input[$i] =~ /^To: (.*)\n$/) { $to = lc($1); } + if ($input[$i] =~ /^Cc: (.*)\n$/) { $cc = lc($1); } + if ($input[$i] =~ /^Subject: (.*)\n$/) { $subject = $1; } +} + +$dbh = DBI->connect("DBI:mysql:$db_name", "$db_user", "$db_pass", { RaiseError => 1}); +sub do_query { + my ($query) = @_; + my $sth = $dbh->prepare($query) or die "Can't prepare $query: $dbh->errstr\n"; + $sth->execute or die "Can't execute the query: $sth->errstr"; + $sth; +} + +sub do_debug { + my ($to, $from, $subject, $row0, $row1) = @_; + open (DEBUG, ">> $debugfile") or die ("Unable to open debug file"); + chop ($date = `date "+%Y/%m/%d %H:%M:%S"`); + print DEBUG "====== $date ======\n"; + print DEBUG "$to - $from - $subject\n"; + print DEBUG "Out of Office Subject: $row0\n"; + print DEBUG "Out of Office Body:\n$row1\n\n"; + close (DEBUG); +} + +sub do_cache { + my ($to, $from, $cache) = @_; + $query = qq{SELECT cache FROM vacation WHERE email='$to' AND FIND_IN_SET('$from',cache)}; + $sth = do_query ($query); + $rv = $sth->rows; + if ($rv == 0) { + $query = qq{UPDATE vacation SET cache=CONCAT(cache,',','$from') WHERE email='$to'}; + $sth = do_query ($query); + } + return $rv; +} + +sub do_mail { + my ($to, $from, $subject, $body) = @_; + open (MAIL, "| $sendmail -t -f $to") or die ("Unable to open sendmail"); + print MAIL "From: $to\n"; + print MAIL "To: $from\n"; + print MAIL "Subject: $subject\n"; + print MAIL "X-Loop: Postfix Vacation\n\n"; + print MAIL "$body"; + close (MAIL); +} + +sub do_log { + my ($to, $from, $subject) = @_; + open (LOG, ">> $logfile") or die ("Unable to open log file"); + chop ($date = `date "+%Y/%m/%d %H:%M:%S"`); + print LOG "$date: $to - $from - $subject\n"; + close (LOG); +} + +@strip_to_array = split(/,/, $to); +if (defined $cc) { @strip_cc_array = split(/,/, $cc); } +push (@strip_to_array, @strip_cc_array); + +foreach $strip_element (@strip_to_array) { + if ($strip_element =~ /(\S*@\S*)/) { $strip_element = $1; } + if ($strip_element =~ /\<(.*)\>/) { $strip_element = $1; } + push (@search_array, $strip_element); +} + +foreach $search_element (@search_array) { + $query = qq{SELECT email FROM vacation WHERE email='$search_element'}; + $sth = do_query ($query); + $rv = $sth->rows; + if ($rv == 1) { + push (@found_array, $search_element); + } +} + +foreach $found_element (@found_array) { + $query = qq{SELECT subject,body FROM vacation WHERE email='$found_element'}; + $sth = do_query ($query); + $rv = $sth->rows; + if ($rv == 1) { + @row = $sth->fetchrow_array; + if ($debugfile) { do_debug ($found_element, $from, $subject, $row[0], $row[1]); } + if (do_cache ($found_element, $from, $row[2])) { next; } + do_mail ($found_element, $from, $row[0], $row[1]); + if ($logfile) { do_log ($found_element, $from, $subject); } + } +} +1; diff --git a/admin/.htaccess b/admin/.htaccess new file mode 100644 index 00000000..6ca3543b --- /dev/null +++ b/admin/.htaccess @@ -0,0 +1,8 @@ +AuthUserFile /usr/local/www//admin/.htpasswd +AuthGroupFile /dev/null +AuthName "Postfix Admin" +AuthType Basic + + +require valid-user + diff --git a/admin/.htpasswd b/admin/.htpasswd new file mode 100644 index 00000000..99cab860 --- /dev/null +++ b/admin/.htpasswd @@ -0,0 +1 @@ +admin:$apr1$5ip4S/..$cmAmYFlZa1gLHGwFFw2.G0 diff --git a/admin/backup.php b/admin/backup.php new file mode 100644 index 00000000..0f9b3bea --- /dev/null +++ b/admin/backup.php @@ -0,0 +1,81 @@ +Cannot open file ($backup)"; + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/delete.tpl"); + include ("../templates/footer.tpl"); + } + else + { + fwrite ($fh, $header); + + $tables = array('admin','alias','domain','domain_admins','log','mailbox','vacation'); + + for ($i = 0 ; $i < sizeof ($tables) ; ++$i) + { + $result = db_query ("SHOW CREATE TABLE $tables[$i]"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + fwrite ($fh, "$row[1]\n\n"); + } + } + } + + for ($i = 0 ; $i < sizeof ($tables) ; ++$i) + { + $result = db_query ("SELECT * FROM $tables[$i]"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_assoc ($result['result'])) + { + foreach ($row as $key=>$val) + { + $fields[] = $key; + $values[] = $val; + } + + fwrite ($fh, "INSERT INTO ". $tables[$i] . " (". implode (',',$fields) . ") VALUES ('" . implode ('\',\'',$values) . "')\n"); + $fields = ""; + $values = ""; + } + } + } + } + header ("Content-Type: application/octet-stream"); + header ("Content-Disposition: attachment; filename=\"$filename\""); + header ("Content-Transfer-Encoding: binary"); + header ("Content-Length: " . filesize("$backup")); + header ("Content-Description: Postfix Admin"); + $download_backup = fopen ("$backup", "r"); + fpassthru ($download_backup); +} +?> diff --git a/admin/create-admin.php b/admin/create-admin.php new file mode 100644 index 00000000..45bdd3bb --- /dev/null +++ b/admin/create-admin.php @@ -0,0 +1,98 @@ +($fUsername)
"; + } + else + { + if (sizeof ($fDomains) > 0) + { + for ($i = 0; $i < sizeof ($fDomains); $i++) + { + $domain = $fDomains[$i]; + $result = db_query ("INSERT INTO domain_admins (username,domain,created) VALUES ('$fUsername','$domain',NOW())"); + } + } + $tMessage = $LANG['pAdminCreate_admin_result_succes'] . "
($fUsername)
"; + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/admin_create-admin.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/admin/create-alias.php b/admin/create-alias.php new file mode 100644 index 00000000..4be06255 --- /dev/null +++ b/admin/create-alias.php @@ -0,0 +1,112 @@ +($fAddress -> $fGoto)
"; + } + else + { + db_log ("site admin", $fDomain, "create alias", "$fAddress -> $fGoto"); + + $tDomain = $fDomain; + $tMessage = $LANG['pCreate_alias_result_succes'] . "
($fAddress -> $fGoto)
"; + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/create-alias.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/admin/create-domain.php b/admin/create-domain.php new file mode 100644 index 00000000..c7198d01 --- /dev/null +++ b/admin/create-domain.php @@ -0,0 +1,93 @@ +($fDomain)
"; + } + else + { + if ($fDefaultaliases == "on") + { + foreach ($CONF['default_aliases'] as $address=>$goto) + { + $address = $address . "@" . $fDomain; + $result = db_query ("INSERT INTO alias (address,goto,domain,created,modified) VALUES ('$address','$goto','$fDomain',NOW(),NOW())"); + } + } + $tMessage = $LANG['pAdminCreate_domain_result_succes'] . "
($fDomain)
"; + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/admin_create-domain.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/admin/create-mailbox.php b/admin/create-mailbox.php new file mode 100644 index 00000000..58d7e73d --- /dev/null +++ b/admin/create-mailbox.php @@ -0,0 +1,176 @@ +($fUsername -> $fUsername)
"; + } + + $result = db_query ("INSERT INTO mailbox (username,password,name,maildir,quota,domain,created,modified,active) VALUES ('$fUsername','$password','$fName','$maildir','$quota','$fDomain',NOW(),NOW(),'$fActive')"); + if ($result['rows'] != 1) + { + $tDomain = $fDomain; + $tMessage .= $LANG['pCreate_mailbox_result_error'] . "
($fUsername)
"; + } + else + { + + db_log ("site admin", $fDomain, "create mailbox", "$fUsername"); + + $tDomain = $fDomain; + $tMessage = $LANG['pCreate_mailbox_result_succes'] . "
($fUsername)
"; + $tQuota = $CONF['maxquota']; + + if ($fMail == "on") { + if (!mail ($fUsername, $LANG['pSendmail_subject_text'], $LANG['pSendmail_message_text'], "From:" . $SESSID_USERNAME)) + { + $tMessage .= "
" . $LANG['pSendmail_result_error'] . "
"; + } + else + { + $tMessage .= "
" . $LANG['pSendmail_result_succes'] . "
"; + + } + } + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/create-mailbox.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/admin/delete.php b/admin/delete.php new file mode 100644 index 00000000..d225c1f6 --- /dev/null +++ b/admin/delete.php @@ -0,0 +1,120 @@ += 0) and ($result_alias >= 0) and ($result_mailbox >= 0) and ($result_vacation >= 0)) + { + $error = 1; + $tMessage = $LANG['pAdminDelete_domain_error']; + } + else + { + $url = "list-domain.php"; + } + } + + if ($fTable == "admin") + { + $result_admin = db_delete ("admin",$fWhere,$fDelete); + $result_domain_admins = db_delete ("domain_admins",$fWhere,$fDelete); + + if (!($result_admin == 1) and ($result_domain_admins >= 0)) + { + $error = 1; + $tMessage = $LANG['pAdminDelete_admin_error']; + } + else + { + $url = "list-admin.php"; + } + } + + if ($fTable == "alias" or $fTable == "mailbox") + { + $result = db_query ("DELETE FROM alias WHERE address='$fDelete' AND domain='$fDomain'"); + if ($result['rows'] != 1) + { + $error = 1; + $tMessage = $LANG['pDelete_delete_error'] . "$fDelete (alias)!"; + } + else + { + $url = "list-virtual.php?domain=$fDomain"; + db_log ("site admin", $fDomain, "delete alias", $fDelete); + } + + $result = db_query ("SELECT * FROM mailbox WHERE username='$fDelete' AND domain='$fDomain'"); + if ($result['rows'] == 1) + { + $result = db_query ("DELETE FROM mailbox WHERE username='$fDelete' AND domain='$fDomain'"); + if ($result['rows'] != 1) + { + $error = 1; + $tMessage = $LANG['pDelete_delete_error'] . "$fDelete (mailbox)!"; + } + else + { + $url = "list-virtual.php?domain=$fDomain"; + db_log ("site admin", $fDomain, "delete mailbox", $fDelete); + } + } + } + + if ($error != 1) + { + header ("Location: $url"); + exit; + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/delete.tpl"); + include ("../templates/footer.tpl"); +} + +if ($_SERVER['REQUEST_METHOD'] == "POST") +{ + include ("../templates/header.tpl"); + include ("../templates/menu.tpl"); + include ("../templates/delete.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/admin/edit-admin.php b/admin/edit-admin.php new file mode 100644 index 00000000..9b7334f0 --- /dev/null +++ b/admin/edit-admin.php @@ -0,0 +1,114 @@ + 0) + { + for ($i = 0; $i < sizeof ($fDomains); $i++) + { + $domain = $fDomains[$i]; + $result_domains = db_query ("INSERT INTO domain_admins (username,domain,created) VALUES ('$username','$domain',NOW())"); + } + } + + if ($result['rows'] == 1) + { + if (sizeof ($fDomains) > 0) + { + $result = db_query ("DELETE FROM domain_admins WHERE username='$username'"); + for ($i = 0; $i < sizeof ($fDomains); $i++) + { + $domain = $fDomains[$i]; + $result = db_query ("INSERT INTO domain_admins (username,domain,created) VALUES ('$username','$domain',NOW())"); + } + } + header ("Location: list-admin.php"); + } + else + { + $tMessage = $LANG['pAdminEdit_admin_result_error']; + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/admin_edit-admin.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/admin/edit-alias.php b/admin/edit-alias.php new file mode 100644 index 00000000..da6819f6 --- /dev/null +++ b/admin/edit-alias.php @@ -0,0 +1,97 @@ +"; + } + } + + if ($error != 1) + { + $result = db_query ("UPDATE alias SET goto='$goto',modified=NOW() WHERE address='$fAddress' AND domain='$fDomain'"); + if ($result['rows'] != 1) + { + $tMessage = $LANG['pEdit_alias_result_error']; + } + else + { + db_log ("site admin", $fDomain, "edit alias", "$fAddress -> $goto"); + + header ("Location: list-virtual.php?domain=$fDomain"); + exit; + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/edit-alias.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/admin/edit-domain.php b/admin/edit-domain.php new file mode 100644 index 00000000..c572b2dd --- /dev/null +++ b/admin/edit-domain.php @@ -0,0 +1,83 @@ + diff --git a/admin/edit-mailbox.php b/admin/edit-mailbox.php new file mode 100644 index 00000000..761a1a6f --- /dev/null +++ b/admin/edit-mailbox.php @@ -0,0 +1,114 @@ + diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 00000000..84bce926 --- /dev/null +++ b/admin/index.php @@ -0,0 +1,3 @@ + diff --git a/admin/list-admin.php b/admin/list-admin.php new file mode 100644 index 00000000..2c8bde06 --- /dev/null +++ b/admin/list-admin.php @@ -0,0 +1,40 @@ + diff --git a/admin/list-domain.php b/admin/list-domain.php new file mode 100644 index 00000000..e5df1b4f --- /dev/null +++ b/admin/list-domain.php @@ -0,0 +1,63 @@ + diff --git a/admin/list-virtual.php b/admin/list-virtual.php new file mode 100644 index 00000000..e4f0a70d --- /dev/null +++ b/admin/list-virtual.php @@ -0,0 +1,104 @@ + 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tAlias[] = $row; + } + } + + $result = db_query ("SELECT * FROM mailbox WHERE domain='$fDomain' ORDER BY username"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tMailbox[] = $row; + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/admin_list-virtual.tpl"); + include ("../templates/footer.tpl"); +} + +if ($_SERVER['REQUEST_METHOD'] == "POST") +{ + $fDomain = $_POST['fDomain']; + + $limit = get_domain_properties ($fDomain); + + if ($CONF['alias_control'] == "YES") + { + $query = "SELECT alias.address,alias.goto,alias.modified FROM alias WHERE alias.domain='$fDomain' ORDER BY alias.address"; + } + else + { + $query = "SELECT alias.address,alias.goto,alias.modified FROM alias LEFT JOIN mailbox ON alias.address=mailbox.username WHERE alias.domain='$fDomain' AND mailbox.maildir IS NULL ORDER BY alias.address"; + } + + $result = db_query ("$query"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tAlias[] = $row; + } + } + + $result = db_query ("SELECT * FROM mailbox WHERE domain='$fDomain' ORDER BY username"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tMailbox[] = $row; + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/admin_list-virtual.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/admin/viewlog.php b/admin/viewlog.php new file mode 100644 index 00000000..2709ab6f --- /dev/null +++ b/admin/viewlog.php @@ -0,0 +1,62 @@ + 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tLog[] = $row; + } + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/viewlog.tpl"); + include ("../templates/footer.tpl"); +} + +if ($_SERVER['REQUEST_METHOD'] == "POST") +{ + $fDomain = $_POST['fDomain']; + + $result = db_query ("SELECT * FROM log WHERE domain='$fDomain' ORDER BY timestamp DESC LIMIT 10"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tLog[] = $row; + } + } + + include ("../templates/header.tpl"); + include ("../templates/admin_menu.tpl"); + include ("../templates/viewlog.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/config.inc.php.sample b/config.inc.php.sample new file mode 100644 index 00000000..16cb3954 --- /dev/null +++ b/config.inc.php.sample @@ -0,0 +1,83 @@ + 'abuse@domain.tld', + 'hostmaster' => 'hostmaster@domain.tld', + 'postmaster' => 'postmaster@domain.tld', + 'webmaster' => 'webmaster@domain.tld' +); + +// Mailboxes +// If you want to store the mailboxes per domain set this to 'YES'. +// Example: /usr/local/virtual/domain.tld/username@domain.tld +$CONF['domain_path'] = 'NO'; +// If you don't want to have the domain in your mailbox set this to 'NO'. +// Example: /usr/local/virtual/domain.tld/username +$CONF['domain_in_mailbox'] = 'YES'; + +// Default Domain Values +// Specify your default values below. Quota in MB. +$CONF['aliases'] = '10'; +$CONF['mailboxes'] = '10'; +$CONF['maxquota'] = '10'; + +// Quota +// When you want to enforce quota for your mailbox users set this to 'YES'. +$CONF['quota'] = 'NO'; + +// Virtual Vacation +// If you want to use virtual vacation for you mailbox users set this to 'YES'. +// NOTE: Make sure that you install the vacation module. http://high5.net/postfixadmin/ +$CONF['vacation'] = 'NO'; + +// Alias Control +// If you want to control your mailbox aliases as well set this to 'YES'. +$CONF['alias_control'] = 'NO'; + +// Logging +// If you don't want logging set this to 'NO'; +$CONF['logging'] = 'YES'; + +// Header +// Some header configuration. +// If you don't want the Postfix Admin logo to appear set this to 'NO'. +$CONF['logo'] = 'YES'; +$CONF['header_text'] = ':: Welcome to Postfix Admin ::'; + +// Footer +// Below information will be on all pages. +// If you don't want the footer information to appear set this to 'NO'. +$CONF['show_footer_text'] = 'YES'; +$CONF['footer_text'] = 'Return to domain.tld'; +$CONF['footer_link'] = 'http://domain.tld'; + +?> diff --git a/create-alias.php b/create-alias.php new file mode 100644 index 00000000..b960f99f --- /dev/null +++ b/create-alias.php @@ -0,0 +1,122 @@ +($fAddress -> $fGoto)
"; + } + else + { + db_log ($SESSID_USERNAME, $fDomain, "create alias", "$fAddress -> $fGoto"); + + $tDomain = $fDomain; + $tMessage = $LANG['pCreate_alias_result_succes'] . "
($fAddress -> $fGoto)
"; + } + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/create-alias.tpl"); + include ("./templates/footer.tpl"); +} +?> diff --git a/create-mailbox.php b/create-mailbox.php new file mode 100644 index 00000000..10c4b1b4 --- /dev/null +++ b/create-mailbox.php @@ -0,0 +1,187 @@ +($fUsername -> $fUsername)
"; + } + + $result = db_query ("INSERT INTO mailbox (username,password,name,maildir,quota,domain,created,modified,active) VALUES ('$fUsername','$password','$fName','$maildir','$quota','$fDomain',NOW(),NOW(),'$fActive')"); + if ($result['rows'] != 1) + { + $tDomain = $fDomain; + $tMessage .= $LANG['pCreate_mailbox_result_error'] . "
($fUsername)
"; + } + else + { + + db_log ($SESSID_USERNAME, $fDomain, "create mailbox", "$fUsername"); + + $tDomain = $fDomain; + $tMessage = $LANG['pCreate_mailbox_result_succes'] . "
($fUsername)
"; + $tQuota = $CONF['maxquota']; + + if ($fMail == "on") { + if (!mail ($fUsername, $LANG['pSendmail_subject_text'], $LANG['pSendmail_message_text'], "From:" . $SESSID_USERNAME)) + { + $tMessage .= "
" . $LANG['pSendmail_result_error'] . "
"; + } + else + { + $tMessage .= "
" . $LANG['pSendmail_result_succes'] . "
"; + + } + } + } + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/create-mailbox.tpl"); + include ("./templates/footer.tpl"); +} +?> diff --git a/delete.php b/delete.php new file mode 100644 index 00000000..d6fb1cfd --- /dev/null +++ b/delete.php @@ -0,0 +1,81 @@ +$fDomain!"; + } + else + { + + $result = db_query ("DELETE FROM alias WHERE address='$fDelete' AND domain='$fDomain'"); + if ($result['rows'] != 1) + { + $error = 1; + $tMessage = $LANG['pDelete_delete_error'] . "$fDelete (alias)!"; + } + else + { + db_log ($SESSID_USERNAME, $fDomain, "delete alias", $fDelete); + } + + $result = db_query ("SELECT * FROM mailbox WHERE username='$fDelete' AND domain='$fDomain'"); + if ($result['rows'] == 1) + { + $result = db_query ("DELETE FROM mailbox WHERE username='$fDelete' AND domain='$fDomain'"); + if ($result['rows'] != 1) + { + $error = 1; + $tMessage = $LANG['pDelete_delete_error'] . "$fDelete (mailbox)!"; + } + else + { + db_log ($SESSID_USERNAME, $fDomain, "delete mailbox", $fDelete); + } + } + } + + if ($error != 1) + { + header ("Location: overview.php?domain=$fDomain"); + exit; + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/delete.tpl"); + include ("./templates/footer.tpl"); +} + +if ($_SERVER['REQUEST_METHOD'] == "POST") +{ + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/delete.tpl"); + include ("./templates/footer.tpl"); +} +?> diff --git a/edit-alias.php b/edit-alias.php new file mode 100644 index 00000000..1adce513 --- /dev/null +++ b/edit-alias.php @@ -0,0 +1,109 @@ +"; + } + + if (empty ($fGoto)) + { + $error = 1; + $tGoto = $fGoto; + $tMessage = $LANG['pEdit_alias_goto_text_error1']; + } + + $goto = preg_replace ('/\r\n/', ',', $fGoto); + $goto = preg_replace ('/[\s]+/i', '', $goto); + $goto = preg_replace ('/\,*$/', '', $goto); + $array = preg_split ('/,/', $goto); + + for ($i = 0; $i < sizeof ($array); $i++) { + if (in_array ("$array[$i]", $CONF['default_aliases'])) continue; + if (empty ($array[$i])) continue; + if (!check_email ($array[$i])) + { + $error = 1; + $tGoto = $goto; + $tMessage = $LANG['pEdit_alias_goto_text_error2'] . "$array[$i]"; + } + } + + if ($error != 1) + { + $result = db_query ("UPDATE alias SET goto='$goto',modified=NOW() WHERE address='$fAddress' AND domain='$fDomain'"); + if ($result['rows'] != 1) + { + $tMessage = $LANG['pEdit_alias_result_error']; + } + else + { + db_log ($SESSID_USERNAME, $fDomain, "edit alias", "$fAddress -> $goto"); + + header ("Location: overview.php?domain=$fDomain"); + exit; + } + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/edit-alias.tpl"); + include ("./templates/footer.tpl"); +} +?> diff --git a/edit-mailbox.php b/edit-mailbox.php new file mode 100644 index 00000000..ddc0b3ca --- /dev/null +++ b/edit-mailbox.php @@ -0,0 +1,127 @@ +"; + } + + if ($fPassword != $fPassword2) + { + $error = 1; + $tName = $fName; + $tQuota = $fQuota; + $pEdit_mailbox_password_text = $LANG['pEdit_mailbox_password_text_error']; + } + + if (!check_quota ($fQuota, $fDomain)) + { + $error = 1; + $tName = $fName; + $tQuota = $fQuota; + $pEdit_mailbox_quota_text = $LANG['pEdit_mailbox_quota_text_error']; + } + + if ($error != 1) + { + if (!empty ($fQuota)) $quota = $fQuota . "000000"; + if ($fActive == "on") $fActive = 1; + + if (empty ($fPassword) and empty ($fPassword2)) + { + $result = db_query ("UPDATE mailbox SET name='$fName',quota='$quota',modified=NOW(),active='$fActive' WHERE username='$fUsername' AND domain='$fDomain'"); + } + else + { + $password = pacrypt ($fPassword); + $result = db_query ("UPDATE mailbox SET password='$password',name='$fName',quota='$quota',modified=NOW(),active='$fActive' WHERE username='$fUsername' AND domain='$fDomain'"); + } + + if ($result['rows'] != 1) + { + $tMessage = $LANG['pEdit_mailbox_result_error']; + } + else + { + db_log ($SESSID_USERNAME, $fDomain, "edit mailbox", $fUsername); + + header ("Location: overview.php?domain=$fDomain"); + exit; + } + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/edit-mailbox.tpl"); + include ("./templates/footer.tpl"); +} +?> diff --git a/functions.inc.php b/functions.inc.php new file mode 100644 index 00000000..aaa580b7 --- /dev/null +++ b/functions.inc.php @@ -0,0 +1,512 @@ += 0) + { + if ($limit['alias_count'] >= $limit['aliases']) + { + return false; + } + } + return true; +} + + + +// +// check_mailbox +// Action: Checks if the domain is still able to create mailboxes. +// Call: ceck_mailbox (string domain) +// +function check_mailbox ($domain) +{ + $limit = get_domain_properties ($domain); + if ($limit['mailboxes'] >= 0) + { + if ($limit['mailbox_count'] >= $limit['mailboxes']) + { + return false; + } + } + return true; +} + + + +// +// check_quota +// Action: Checks if the user is creating a mailbox with the correct quota +// Call: check_quota (string domain) +// +function check_quota ($quota, $domain) +{ + $limit = get_domain_properties ($domain); + if ($limit['maxquota'] >= 0) + { + if ($quota > $limit['maxquota']) + { + return false; + } + } + return true; +} + + + +// +// check_owner +// Action: Checks if the admin is the owner of the domain. +// Call: check_owner (string admin, string domain) +// +function check_owner ($username, $domain) +{ + $result = db_query ("SELECT * FROM domain_admins WHERE username='$username' AND domain='$domain' AND active='1'"); + if ($result['rows'] != 1) + { + return false; + } + else + { + return true; + } +} + + + +// +// list_domains_for_admin +// Action: Lists all the domains for an admin. +// Call: list_domains_for_admin (string admin) +// +function list_domains_for_admin ($username) +{ + $result = db_query ("SELECT * FROM domain LEFT JOIN domain_admins ON domain.domain=domain_admins.domain WHERE domain_admins.username='$username' AND domain.active='1' ORDER BY domain_admins.domain"); + if ($result['rows'] > 0) + { + $i = 0; + while ($row = mysql_fetch_array ($result['result'])) + { + $list[$i] = $row['domain']; + $i++; + } + } + return $list; +} + + + +// +// list_domains +// Action: List all available domains. +// Call: list_domains () +// +function list_domains () +{ + $result = db_query ("SELECT * FROM domain ORDER BY domain"); + if ($result['rows'] > 0) + { + $i = 0; + while ($row = mysql_fetch_array ($result['result'])) + { + $list[$i] = $row['domain']; + $i++; + } + } + return $list; +} + + + +// +// admin_exist +// Action: Checks if the admin already exists. +// Call: admin_exist (string admin) +// +// was check_admin +// +function admin_exist ($username) +{ + $result = db_query ("SELECT * FROM admin WHERE username='$username'"); + if ($result['rows'] != 1) + { + return false; + } + else + { + return true; + } +} + +// +// domain_exist +// Action: Checks if the domain already exists. +// Call: domain_exist (string domain) +// +function domain_exist ($domain) +{ + $result = db_query ("SELECT * FROM domain WHERE domain='$domain'"); + if ($result['rows'] != 1) + { + return false; + } + else + { + return true; + } +} + + +// +// list_admins +// Action: Lists all the admins +// Call: list_admins () +// +// was admin_list_admins +// +function list_admins () +{ + $result = db_query ("SELECT * FROM admin ORDER BY username"); + if ($result['rows'] > 0) + { + $i = 0; + while ($row = mysql_fetch_array ($result['result'])) + { + $list[$i] = $row['username']; + $i++; + } + } + return $list; +} + + + +// +// get_admin_properties +// Action: Get all the admin properties. +// Call: get_admin_properties (string admin) +function get_admin_properties ($username) +{ + $result = db_query ("SELECT * FROM domain_admins WHERE username='$username'"); + $list['domain_count'] = $result['rows']; + + $result = db_query ("SELECT * FROM admin WHERE username='$username'"); + $row = mysql_fetch_array ($result['result']); + $list['created'] = $row['created']; + $list['modified'] = $row['modified']; + $list['active'] = $row['active']; + + return $list; +} + + + +// +// pacrypt +// Action: Encrypts password based on config settings +// Call: pacrypt (string cleartextpassword) +// +function pacrypt ($pw, $salt="") +{ + global $CONF; + + if ($CONF['encrypt'] == 'md5crypt') + { + $password = md5crypt ($pw, $salt); + } + + if ($CONF['encrypt'] == 'system') + { + $password = crypt ($pw, $salt); + } + + if ($CONF['encrypt'] == 'cleartext') + { + $password = $pw; + } + + return $password; +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// md5crypt +// Action: Creates MD5 encrypted password +// Call: md5crypt (string cleartextpassword) +// +$MAGIC = "$1$"; +$ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +function md5crypt ($pw, $salt="", $magic="") +{ + global $MAGIC; + if ($magic == "") $magic = $MAGIC; + if ($salt == "") $salt = create_salt(); + $slist = explode ("$", $salt); + if ($slist[0] == "1") $salt = $slist[1]; + $salt = substr ($salt, 0, 8); + $ctx = $pw . $magic . $salt; + $final = hex2bin (md5 ($pw . $salt . $pw)); + for ($i=strlen ($pw); $i>0; $i-=16) { + if ($i > 16) + $ctx .= substr ($final,0,16); + else + $ctx .= substr ($final,0,$i); + } + $i = strlen ($pw); + while ($i > 0) { + if ($i & 1) $ctx .= chr (0); + else $ctx .= $pw[0]; + $i = $i >> 1; + } + $final = hex2bin (md5 ($ctx)); + for ($i=0;$i<1000;$i++) { + $ctx1 = ""; + if ($i & 1) $ctx1 .= $pw; + else $ctx1 .= substr ($final,0,16); + if ($i % 3) $ctx1 .= $salt; + if ($i % 7) $ctx1 .= $pw; + if ($i & 1) $ctx1 .= substr ($final,0,16); + else $ctx1 .= $pw; + $final = hex2bin (md5 ($ctx1)); + } + $passwd = ""; + $passwd .= to64 ( ( (ord ($final[0]) << 16) | (ord ($final[6]) << 8) | (ord ($final[12])) ), 4); + $passwd .= to64 ( ( (ord ($final[1]) << 16) | (ord ($final[7]) << 8) | (ord ($final[13])) ), 4); + $passwd .= to64 ( ( (ord ($final[2]) << 16) | (ord ($final[8]) << 8) | (ord ($final[14])) ), 4); + $passwd .= to64 ( ( (ord ($final[3]) << 16) | (ord ($final[9]) << 8) | (ord ($final[15])) ), 4); + $passwd .= to64 ( ( (ord ($final[4]) << 16) | (ord ($final[10]) << 8) | (ord ($final[5])) ), 4); + $passwd .= to64 ( ord ($final[11]), 2); + return "$magic$salt\$$passwd"; +} + +function create_salt () +{ + srand ((double)microtime ()*1000000); + $salt = substr (md5 (rand (0,9999999)), 0, 8); + return $salt; +} + +function hex2bin ($str) +{ + $len = strlen ($str); + $nstr = ""; + for ($i=0;$i<$len;$i+=2) { + $num = sscanf (substr ($str,$i,2), "%x"); + $nstr.=chr ($num[0]); + } + return $nstr; +} + +function to64 ($v, $n) +{ + global $ITOA64; + $ret = ""; + while (($n - 1) >= 0) { + $n--; + $ret .= $ITOA64[$v & 0x3f]; + $v = $v >> 6; + } + return $ret; +} + + + +// +// db_connect +// Action: Makes a connection to the database if it doesn't exist +// Call: db_connect () +// +function db_connect () +{ + global $CONF; + $link = @mysql_connect ($CONF['database_host'], $CONF['database_user'], $CONF['database_password']) or die ("

DEBUG INFORMATION:
Connect: " . mysql_error ()); + $succes = @mysql_select_db ($CONF['database_name'], $link) or die ("

DEBUG INFORMATION:
MySQL Select Database: " . mysql_error ()); + return $link; +} + + + +// +// db_query +// Action: Sends a query to the database and returns query result and number of rows +// Call: db_query (string query) +// +function db_query ($query) +{ + global $CONF; + $link = db_connect (); + $result = @mysql_query ($query, $link) or die ("

DEBUG INFORMATION:
Invalid query: " . mysql_error()); + if (eregi ("^select", $query)) + { + // if $query was a select statement check the number of rows with mysql_num_rows (). + $number_rows = mysql_num_rows ($result); + } + else + { + // if $query was something else, UPDATE, DELETE or INSERT check the number of rows with + // mysql_affected_rows (). + $number_rows = mysql_affected_rows ($link); + } + $return = array ( + "result" => $result, + "rows" => $number_rows + ); + return $return; +} + + + +// +// db_delete +// Action: Deletes a row from a specified table +// Call db_delete (string table, string where, string delete) +// +function db_delete ($table,$where,$delete) +{ + $result = db_query ("DELETE FROM $table WHERE $where='$delete'"); + if ($result['rows'] >= 1) + { + return $result['rows']; + } + else + { + return true; + } +} + + + +// +// db_log +// Action: Logs actions from admin +// Call: db_delete (string username, string domain, string action, string data) +// +function db_log ($username,$domain,$action,$data) +{ + global $CONF; + + if ($CONF['logging'] == 'YES') + { + $result = db_query ("INSERT INTO log (timestamp,username,domain,action,data) VALUES (NOW(),'$username','$domain','$action','$data')"); + if ($result['rows'] != 1) + { + return false; + } + else + { + return true; + } + } +} + +?> diff --git a/index.php b/index.php new file mode 100644 index 00000000..51dde5c3 --- /dev/null +++ b/index.php @@ -0,0 +1,17 @@ + diff --git a/languages/en.lang b/languages/en.lang new file mode 100644 index 00000000..e2c3359d --- /dev/null +++ b/languages/en.lang @@ -0,0 +1,284 @@ +Unable to delete the entry '; +$LANG['pDelete_domain_error'] = 'This domain is not yours '; + +$LANG['pCreate_alias_welcome'] = 'Create a new alias for your domain.'; +$LANG['pCreate_alias_address'] = 'Alias'; +$LANG['pCreate_alias_address_text_error1'] = '
The ALIAS is not valid!'; +$LANG['pCreate_alias_address_text_error2'] = '
This email address already exists, please choose a different one!'; +$LANG['pCreate_alias_address_text_error3'] = '
You have reached your limit to create aliases!'; +$LANG['pCreate_alias_goto'] = 'To'; +$LANG['pCreate_alias_button'] = 'Add Alias'; +$LANG['pCreate_alias_goto_text'] = 'Where the mail needs to be send to.'; +$LANG['pCreate_alias_goto_text_error'] = 'Where the email needs to go.
The TO is not valid!'; +$LANG['pCreate_alias_result_error'] = 'Unable to add the alias to the alias table!'; +$LANG['pCreate_alias_result_succes'] = 'The alias has been added to the alias table!'; +$LANG['pCreate_alias_catchall_text'] = 'To create a catch-all use an "*" as alias.
For domain to domain forwarding use "*@domain.tld" as to.'; + +$LANG['pEdit_alias_welcome'] = 'Edit an alias for your domain.
One entry per line.'; +$LANG['pEdit_alias_address'] = 'Alias'; +$LANG['pEdit_alias_address_error'] = 'Unable to locate alias!'; +$LANG['pEdit_alias_goto'] = 'To'; +$LANG['pEdit_alias_goto_text_error1'] = 'You didn\'t enter anything at To'; +$LANG['pEdit_alias_goto_text_error2'] = 'The email address that you have entered is not valid: '; +$LANG['pEdit_alias_domain_error'] = 'This domain is not yours: '; +$LANG['pEdit_alias_button'] = 'Edit Alias'; +$LANG['pEdit_alias_result_error'] = 'Unable to modify the alias!'; + +$LANG['pCreate_mailbox_welcome'] = 'Create a new local mailbox for your domain.'; +$LANG['pCreate_mailbox_username'] = 'Username'; +$LANG['pCreate_mailbox_username_text_error1'] = '
The EMAIL is not valid!'; +$LANG['pCreate_mailbox_username_text_error2'] = '
This email address already exists, please choose a different one!'; +$LANG['pCreate_mailbox_username_text_error3'] = '
You have reached your limit to create mailboxes!'; +$LANG['pCreate_mailbox_password'] = 'Password'; +$LANG['pCreate_mailbox_password2'] = 'Password (again)'; +$LANG['pCreate_mailbox_password_text'] = 'Password for POP3/IMAP'; +$LANG['pCreate_mailbox_password_text_error'] = 'Password for POP3/IMAP
The passwords that you supplied don\'t match!
Or are empty!
'; +$LANG['pCreate_mailbox_name'] = 'Name'; +$LANG['pCreate_mailbox_name_text'] = 'Full name'; +$LANG['pCreate_mailbox_quota'] = 'Quota'; +$LANG['pCreate_mailbox_quota_text'] = 'MB'; +$LANG['pCreate_mailbox_quota_text_error'] = 'MB
The quota that you specified is to high!'; +$LANG['pCreate_mailbox_active'] = 'Active'; +$LANG['pCreate_mailbox_mail'] = 'Create mailbox'; +$LANG['pCreate_mailbox_button'] = 'Add Mailbox'; +$LANG['pCreate_mailbox_result_error'] = 'Unable to add the mailbox to the mailbox table!'; +$LANG['pCreate_mailbox_result_succes'] = 'The mailbox has been added to the mailbox table!'; + +$LANG['pEdit_mailbox_welcome'] = 'Edit a mailbox for your domain.'; +$LANG['pEdit_mailbox_username'] = 'Username'; +$LANG['pEdit_mailbox_username_error'] = 'Unable to locate mailbox!'; +$LANG['pEdit_mailbox_password'] = 'New Password'; +$LANG['pEdit_mailbox_password2'] = 'New Password (again)'; +$LANG['pEdit_mailbox_password_text_error'] = 'The passwords that you supplied don\'t match!'; +$LANG['pEdit_mailbox_name'] = 'Name'; +$LANG['pEdit_mailbox_quota'] = 'Quota'; +$LANG['pEdit_mailbox_quota_text'] = 'MB'; +$LANG['pEdit_mailbox_quota_text_error'] = 'MB
The quota that you specified is to high!'; +$LANG['pEdit_mailbox_domain_error'] = 'This domain is not yours: '; +$LANG['pEdit_mailbox_button'] = 'Edit Mailbox'; +$LANG['pEdit_mailbox_result_error'] = 'Unable to change the password!'; + +$LANG['pPassword_welcome'] = 'Change your login password.'; +$LANG['pPassword_admin'] = 'Login'; +$LANG['pPassword_admin_text_error'] = 'The LOGIN that you supplied doesn\'t match a mailbox!'; +$LANG['pPassword_password_current'] = 'Current Password'; +$LANG['pPassword_password_current_text_error'] = 'You didn\'t supply your current password!'; +$LANG['pPassword_password'] = 'New Password'; +$LANG['pPassword_password2'] = 'New Password (again)'; +$LANG['pPassword_password_text_error'] = 'The passwords that you supplied don\'t match!
Or are empty!
'; +$LANG['pPassword_button'] = 'Change Password'; +$LANG['pPassword_result_error'] = 'Unable to change your password!'; +$LANG['pPassword_result_succes'] = 'Your password has been changed!'; + +$LANG['pViewlog_welcome'] = 'View the last 10 actions for '; +$LANG['pViewlog_timestamp'] = 'Timestamp'; +$LANG['pViewlog_username'] = 'Admin'; +$LANG['pViewlog_domain'] = 'Domain'; +$LANG['pViewlog_action'] = 'Action'; +$LANG['pViewlog_data'] = 'Data'; + +$LANG['pViewlog_button'] = 'Go'; +$LANG['pViewlog_result_error'] = 'Unable to find the logs!'; + +$LANG['pSendmail_welcome'] = 'Send an email.'; +$LANG['pSendmail_admin'] = 'From'; +$LANG['pSendmail_to'] = 'To'; +$LANG['pSendmail_to_text_error'] = 'To is empty or is not a valid email address!'; +$LANG['pSendmail_subject'] = 'Subject'; +$LANG['pSendmail_subject_text'] = 'Welcome'; +$LANG['pSendmail_body'] = 'Body'; +$LANG['pSendmail_body_text'] = <<'; +$LANG['pVcp_password_current'] = 'Current Password'; +$LANG['pVcp_password_current_text_error'] = 'You didn\'t supply your current password!'; +$LANG['pVcp_password'] = 'New Password'; +$LANG['pVcp_password2'] = 'New Password (again)'; +$LANG['pVcp_password_text_error'] = 'The passwords that you supplied don\'t match!
Or are empty!
'; +$LANG['pVcp_button'] = 'Change Password'; +$LANG['pVcp_result_error'] = 'Unable to change your password!'; +$LANG['pVcp_result_succes'] = 'Your password has been changed!'; + +$LANG['pAdminMenu_list_admin'] = 'Admin List'; +$LANG['pAdminMenu_list_domain'] = 'Domain List'; +$LANG['pAdminMenu_list_virtual'] = 'Virtual List'; +$LANG['pAdminMenu_viewlog'] = 'View Log'; +$LANG['pAdminMenu_backup'] = 'Backup'; +$LANG['pAdminMenu_create_domain_admins'] = 'Domain Admins'; +$LANG['pAdminMenu_create_admin'] = 'New Admin'; +$LANG['pAdminMenu_create_domain'] = 'New Domain'; +$LANG['pAdminMenu_create_alias'] = 'Add Alias'; +$LANG['pAdminMenu_create_mailbox'] = 'Add Mailbox'; + +$LANG['pAdminList_admin_domain'] = 'Domain'; +$LANG['pAdminList_admin_username'] = 'Admin'; +$LANG['pAdminList_admin_count'] = 'Domains'; +$LANG['pAdminList_admin_modified'] = 'Last Modified'; +$LANG['pAdminList_admin_active'] = 'Active'; + +$LANG['pAdminList_domain_domain'] = 'Domain'; +$LANG['pAdminList_domain_description'] = 'Description'; +$LANG['pAdminList_domain_aliases'] = 'Aliases'; +$LANG['pAdminList_domain_mailboxes'] = 'Mailboxes'; +$LANG['pAdminList_domain_maxquota'] = 'Max Quota (MB)'; +$LANG['pAdminList_domain_modified'] = 'Last Modified'; +$LANG['pAdminList_domain_active'] = 'Active'; + +$LANG['pAdminList_virtual_button'] = 'Go'; +$LANG['pAdminList_virtual_welcome'] = 'Overview for '; +$LANG['pAdminList_virtual_alias_alias_count'] = 'Aliases'; +$LANG['pAdminList_virtual_alias_mailbox_count'] = 'Mailboxes'; +$LANG['pAdminList_virtual_alias_address'] = 'From'; +$LANG['pAdminList_virtual_alias_goto'] = 'To'; +$LANG['pAdminList_virtual_alias_modified'] = 'Last Modified'; +$LANG['pAdminList_virtual_mailbox_username'] = 'Email'; +$LANG['pAdminList_virtual_mailbox_name'] = 'Name'; +$LANG['pAdminList_virtual_mailbox_quota'] = 'Quota (MB)'; +$LANG['pAdminList_virtual_mailbox_modified'] = 'Last Modified'; +$LANG['pAdminList_virtual_mailbox_active'] = 'Active'; + +$LANG['pAdminCreate_domain_welcome'] = 'Add a new domain'; +$LANG['pAdminCreate_domain_domain'] = 'Domain'; +$LANG['pAdminCreate_domain_domain_text_error'] = 'The domain already exists!'; +$LANG['pAdminCreate_domain_description'] = 'Description'; +$LANG['pAdminCreate_domain_aliases'] = 'Aliases'; +$LANG['pAdminCreate_domain_aliases_text'] = '0 = disable | -1 = unlimited'; +$LANG['pAdminCreate_domain_mailboxes'] = 'Mailboxes'; +$LANG['pAdminCreate_domain_mailboxes_text'] = '0 = disable | -1 = unlimited'; +$LANG['pAdminCreate_domain_maxquota'] = 'Max Quota'; +$LANG['pAdminCreate_domain_maxquota_text'] = 'MB
0 = disable | -1 = unlimited'; +$LANG['pAdminCreate_domain_defaultaliases'] = 'Add default mail aliases'; +$LANG['pAdminCreate_domain_button'] = 'Add Domain'; +$LANG['pAdminCreate_domain_result_error'] = 'Unable to add domain!'; +$LANG['pAdminCreate_domain_result_succes'] = 'Domain has been added!'; + +$LANG['pAdminEdit_domain_welcome'] = 'Edit a domain'; +$LANG['pAdminEdit_domain_domain'] = 'Domain'; +$LANG['pAdminEdit_domain_description'] = 'Description'; +$LANG['pAdminEdit_domain_aliases'] = 'Aliases'; +$LANG['pAdminCreate_domain_aliases_text'] = '0 = disable | -1 = unlimited'; +$LANG['pAdminEdit_domain_mailboxes'] = 'Mailboxes'; +$LANG['pAdminCreate_domain_mailboxes_text'] = '0 = disable | -1 = unlimited'; +$LANG['pAdminEdit_domain_maxquota'] = 'Max Quota'; +$LANG['pAdminCreate_domain_maxquota_text'] = 'MB
0 = disable | -1 = unlimited'; +$LANG['pAdminEdit_domain_active'] = 'Active'; +$LANG['pAdminEdit_domain_button'] = 'Edit Domain'; +$LANG['pAdminEdit_domain_result_error'] = 'Unable to modify domain!'; + +$LANG['pAdminCreate_admin_welcome'] = 'Add a new domain admin'; +$LANG['pAdminCreate_admin_username'] = 'Admin'; +$LANG['pAdminCreate_admin_username_text'] = 'Email address'; +$LANG['pAdminCreate_admin_username_text_error1'] = 'Email address
Admin is not a valid email address!'; +$LANG['pAdminCreate_admin_username_text_error2'] = 'Email address
The admin already exists or is not valid'; +$LANG['pAdminCreate_admin_password'] = 'Password'; +$LANG['pAdminCreate_admin_password2'] = 'Password (again)'; +$LANG['pAdminCreate_admin_password_text_error'] = 'The passwords that you supplied don\'t match!
Or are empty!
'; +$LANG['pAdminCreate_admin_button'] = 'Add Admin'; +$LANG['pAdminCreate_admin_result_error'] = 'Unable to add admin!'; +$LANG['pAdminCreate_admin_result_succes'] = 'Admin has been added!'; +$LANG['pAdminCreate_admin_address'] = 'Domain'; + +$LANG['pAdminEdit_admin_welcome'] = 'Edit a domain admin'; +$LANG['pAdminEdit_admin_username'] = 'Admin'; +$LANG['pAdminEdit_admin_password'] = 'Password'; +$LANG['pAdminEdit_admin_password2'] = 'Password (again)'; +$LANG['pAdminEdit_admin_password_text_error'] = 'The passwords that you supplied don\'t match!
Or are empty!
'; +$LANG['pAdminEdit_admin_active'] = 'Active'; +$LANG['pAdminEdit_admin_button'] = 'Edit Admin'; +$LANG['pAdminEdit_admin_result_error'] = 'Unable to modify admin!'; +$LANG['pAdminEdit_admin_result_succes'] = 'Admin has been modified!'; + +$LANG['pUsersLogin_welcome'] = 'Mailbox users login to change your password and aliases.'; +$LANG['pUsersLogin_username'] = 'Login (email)'; +$LANG['pUsersLogin_password'] = 'Password'; +$LANG['pUsersLogin_button'] = 'Login'; +$LANG['pUsersLogin_username_incorrect'] = 'Your login is not correct. Make sure that you login with your email address!'; +$LANG['pUsersLogin_password_incorrect'] = 'Your password is not correct!'; + +$LANG['pUsersMenu_vacation'] = 'Auto Response'; +$LANG['pUsersMenu_edit_alias'] = 'Change your forward'; +$LANG['pUsersMenu_password'] = 'Change Password'; + +$LANG['pUsersMain_welcome'] = 'Change your mailbox settings here!'; +$LANG['pUsersMain_vacation'] = 'Set an "out of office" message or auto responder for your mail.'; +$LANG['pUsersMain_edit_alias'] = 'Change your email forwarding.'; +$LANG['pUsersMain_password'] = 'Change your current password.'; + +$LANG['pUsersVacation_welcome'] = 'Auto Response.'; +$LANG['pUsersVacation_welcome_text'] = 'You already have an auto response configured!'; +$LANG['pUsersVacation_subject'] = 'Subject'; +$LANG['pUsersVacation_subject_text'] = 'Out of Office'; +$LANG['pUsersVacation_body'] = 'Body'; +$LANG['pUsersVacation_body_text'] = << until . +For urgent matters you can contact . +EOM; +$LANG['pUsersVacation_button_away'] = 'Going Away'; +$LANG['pUsersVacation_button_back'] = 'Coming Back'; +$LANG['pUsersVacation_result_error'] = 'Unable to update your auto response settings!'; +$LANG['pUsersVacation_result_succes'] = 'Your auto response has been removed!'; +?> diff --git a/login.php b/login.php new file mode 100644 index 00000000..88c82649 --- /dev/null +++ b/login.php @@ -0,0 +1,68 @@ + diff --git a/logout.php b/logout.php new file mode 100644 index 00000000..52e904f9 --- /dev/null +++ b/logout.php @@ -0,0 +1,25 @@ + diff --git a/main.php b/main.php new file mode 100644 index 00000000..591e1212 --- /dev/null +++ b/main.php @@ -0,0 +1,36 @@ + diff --git a/overview.php b/overview.php new file mode 100644 index 00000000..470dfd6f --- /dev/null +++ b/overview.php @@ -0,0 +1,112 @@ + 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tAlias[] = $row; + } + } + + $result = db_query ("SELECT * FROM mailbox WHERE domain='$fDomain' ORDER BY username"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tMailbox[] = $row; + } + } + $template = "overview.tpl"; + } + else + { + $template = "overview-get.tpl"; + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/$template"); + include ("./templates/footer.tpl"); +} + +if ($_SERVER['REQUEST_METHOD'] == "POST") +{ + if (check_owner ($SESSID_USERNAME, $_POST['fDomain'])) + { + $fDomain = $_POST['fDomain']; + + $limit = get_domain_properties ($fDomain); + + if ($CONF['alias_control'] == "YES") + { + $query = "SELECT alias.address,alias.goto,alias.modified FROM alias WHERE alias.domain='$fDomain' ORDER BY alias.address"; + } + else + { + $query = "SELECT alias.address,alias.goto,alias.modified FROM alias LEFT JOIN mailbox ON alias.address=mailbox.username WHERE alias.domain='$fDomain' AND mailbox.maildir IS NULL ORDER BY alias.address"; + } + + $result = db_query ("$query"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tAlias[] = $row; + } + } + + $result = db_query ("SELECT * FROM mailbox WHERE domain='$fDomain' ORDER BY username"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tMailbox[] = $row; + } + } + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/overview.tpl"); + include ("./templates/footer.tpl"); +} +?> diff --git a/password.php b/password.php new file mode 100644 index 00000000..f5060698 --- /dev/null +++ b/password.php @@ -0,0 +1,86 @@ + diff --git a/postfixadmin.png b/postfixadmin.png new file mode 100644 index 00000000..4ee0ad64 Binary files /dev/null and b/postfixadmin.png differ diff --git a/sendmail.php b/sendmail.php new file mode 100644 index 00000000..2566cb8d --- /dev/null +++ b/sendmail.php @@ -0,0 +1,66 @@ + diff --git a/stylesheet.css b/stylesheet.css new file mode 100644 index 00000000..ae228e6d --- /dev/null +++ b/stylesheet.css @@ -0,0 +1,184 @@ +body { + background: white; + color: black; + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 13px; + margin: 8px; + padding: 0px; + text-align: center; +} + +h1 { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 18px; + font-weight: bold; + margin-bottom: 0px; + margin-top: 20px; +} + +a { + color: blue; + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + text-decoration: none; +} + +a:visited { + color: blue; + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + text-decoration: none; +} + +hr { + line-heigt: 1px; + margin-top: 10px; + margin-bottom: 10px; + width: auto; + text-align: center; +} + +hr.footer { + margin-top: 10px; + margin-bottom: 0px; + width: 640px; +} + +p { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 13px; + margin-top: 13px; + text-align: center; +} + +p.footer { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + margin-bottom: 0px; + margin-top: 5px; + text-align: center; +} + +p.error { + color: red; + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 13px; + text-align: center; +} + +table { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + width: 640px; + text-align: left; + margin-top: 0px; + margin-bottom: 0px; + padding-top: 0px; +} + +table.auto { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + width: auto; + text-align: left; + margin-top: 0px; + margin-bottom: 0px; + padding-top: 0px; +} + + +table.form { + font-size: 11px; + padding-left: 0px; + padding-right: 0px; + text-align: left; + width: auto; +} + +td { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + padding-left: 5px; + padding-right: 5px; +} + +tr.header { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-weight: bold; + padding-left: 11px; + padding-right: 11px; +} + +td.center { + text-align: center; +} + +td.header { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-weight: bold; + padding-left: 11px; + padding-right: 11px; + text-align: center; +} + +td.highlight { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + background: rgb(169,194,162); + padding-left: 5px; + padding-right: 5px; +} + +td.menu { + text-align: center; + background: #dfdfdf; + border-top: 1px solid #999; + border-right: 1px solid #999; + border-left: 1px solid #999; + border-bottom: 1px solid #999; + border-radius: 2px; + -moz-border-radius: 2px; + padding-bottom: 5px; + padding-top: 5px; + +} + +td.right { + text-align: center; + padding-left: 0px; + padding-right: 0px; + margin-left: 0px; + margin-right: 0px; +} + +input { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; + float: none; + clear: none; +} + +input.button { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + background: rgb(232,236,176) +} + +textarea { + font-family: Verdana; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 11px; +} diff --git a/templates/admin_create-admin.tpl b/templates/admin_create-admin.tpl new file mode 100644 index 00000000..f2a0042e --- /dev/null +++ b/templates/admin_create-admin.tpl @@ -0,0 +1,72 @@ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + + +
+ + + + + +
+ + + + +   +
+ +
+ + +
+

diff --git a/templates/admin_create-domain.tpl b/templates/admin_create-domain.tpl new file mode 100644 index 00000000..0c5c931f --- /dev/null +++ b/templates/admin_create-domain.tpl @@ -0,0 +1,92 @@ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; +} +?> + + + + + + + + +
+ +
+
+
+
+ +
+ + + +
+ + + + +   +
+ + + + + +
+ + + + + +
\n"; + print " " . $LANG['pAdminCreate_domain_maxquota'] . ":\n"; + print " \n"; + print " \n"; + print " \n"; + print " " . $LANG['pAdminCreate_domain_maxquota_text'] . "\n"; + print "
+ + + + > + + +
+ + +
+

diff --git a/templates/admin_create-mailbox.tpl b/templates/admin_create-mailbox.tpl new file mode 100644 index 00000000..3745e6fe --- /dev/null +++ b/templates/admin_create-mailbox.tpl @@ -0,0 +1,115 @@ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + } + ?> + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + + + +
+ + + + + +
+ + + + +   +
+ + + + + +
\n"; + print " " . $LANG['pCreate_mailbox_quota'] . ":\n"; + print " \n"; + print " \n"; + print " \n"; + print " $pCreate_mailbox_quota_text\n"; + print "
+ + + + +   +
+ + + + +   +
+ + +
diff --git a/templates/admin_edit-admin.tpl b/templates/admin_edit-admin.tpl new file mode 100644 index 00000000..c627251b --- /dev/null +++ b/templates/admin_edit-admin.tpl @@ -0,0 +1,84 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + +   +
+ + + + + +
+ + + + +   +
+ + + + > + +   +
+ + +
+ + +
+

diff --git a/templates/admin_edit-domain.tpl b/templates/admin_edit-domain.tpl new file mode 100644 index 00000000..a95a992c --- /dev/null +++ b/templates/admin_edit-domain.tpl @@ -0,0 +1,86 @@ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + +   +
+ + + + +   +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + > + +   +
+ + +
+

diff --git a/templates/admin_list-admin.tpl b/templates/admin_list-admin.tpl new file mode 100644 index 00000000..7c75f021 --- /dev/null +++ b/templates/admin_list-admin.tpl @@ -0,0 +1,32 @@ +

+ 0) +{ + print "
\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + + for ($i = 0; $i < sizeof ($list_admins); $i++) + { + print " "; + print " "; + print " "; + print " "; + $active = ($admin_properties[$i]['active'] == 1) ? $LANG['YES'] : $LANG['NO']; + print " "; + print " "; + print " "; + print " \n"; + } + + print "
" . $LANG['pAdminList_admin_username'] . "" . $LANG['pAdminList_admin_count'] . "" . $LANG['pAdminList_admin_modified'] . "" . $LANG['pAdminList_admin_active'] . " 
" . $list_admins[$i] . "" . $admin_properties[$i]['domain_count'] . "" . $admin_properties[$i]['modified'] . "" . $active . "" . $LANG['edit'] . "" . $LANG['del'] . "
\n"; + print "
\n"; + print "

\n"; +} +?> diff --git a/templates/admin_list-domain.tpl b/templates/admin_list-domain.tpl new file mode 100644 index 00000000..b7b9e440 --- /dev/null +++ b/templates/admin_list-domain.tpl @@ -0,0 +1,57 @@ +

+
+ + +
+

+ 0) +{ + print "

\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + if ($CONF['quota'] == 'YES') print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + + for ($i = 0; $i < sizeof ($list_domains); $i++) + { + print ""; + print ""; + print ""; + print ""; + print ""; + if ($CONF['quota'] == 'YES') print ""; + print ""; + $active = ($domain_properties[$i]['active'] == 1) ? $LANG['YES'] : $LANG['NO']; + print ""; + print ""; + print ""; + print "\n"; + } + + print "
" . $LANG['pAdminList_domain_domain'] . "" . $LANG['pAdminList_domain_description'] . "" . $LANG['pAdminList_domain_aliases'] . "" . $LANG['pAdminList_domain_mailboxes'] . "" . $LANG['pAdminList_domain_maxquota'] . "" . $LANG['pAdminList_domain_modified'] . "" . $LANG['pAdminList_domain_active'] . " 
" . $list_domains[$i] . "" . $domain_properties[$i]['description'] . "" . $domain_properties[$i]['alias_count'] . " / " . $domain_properties[$i]['aliases'] . "" . $domain_properties[$i]['mailbox_count'] . " / " . $domain_properties[$i]['mailboxes'] . "" . $domain_properties[$i]['maxquota'] . "" . $domain_properties[$i]['modified'] . "" . $active . "" . $LANG['edit'] . "" . $LANG['del'] . "
\n"; + print "
\n"; + print "

\n"; +} +?> diff --git a/templates/admin_list-virtual.tpl b/templates/admin_list-virtual.tpl new file mode 100644 index 00000000..12ecc170 --- /dev/null +++ b/templates/admin_list-virtual.tpl @@ -0,0 +1,85 @@ +

+
+ + +
+

+". $LANG['pAdminList_virtual_welcome'] . $fDomain . "
\n"; +print $LANG['pAdminList_virtual_alias_alias_count'] . ": " . $limit['alias_count'] . " / " . $limit['aliases'] . "   "; +print $LANG['pAdminList_virtual_alias_mailbox_count'] . ": " . $limit['mailbox_count'] . " / " . $limit['mailboxes'] . "
\n"; +print "

\n"; + +if (sizeof ($tAlias) > 0) +{ + print "

\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + + for ($i = 0; $i < sizeof ($tAlias); $i++) + { + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + } + + print "
" . $LANG['pAdminList_virtual_alias_address'] . "" . $LANG['pAdminList_virtual_alias_goto'] . "" . $LANG['pAdminList_virtual_alias_modified'] . " 
" . $tAlias[$i]['address'] . "" . ereg_replace (",", "
", $tAlias[$i]['goto']) . "
" . $tAlias[$i]['modified'] . "" . $LANG['edit'] . "" . $LANG['del'] . "
\n"; + print "
\n"; + print "

\n"; +} + +if (sizeof ($tMailbox) > 0) +{ + print "

\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + if ($CONF['quota'] == 'YES') print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + + for ($i = 0; $i < sizeof ($tMailbox); $i++) + { + print " \n"; + print " \n"; + print " \n"; + if ($CONF['quota'] == 'YES') print " \n"; + print " \n"; + $active = ($tMailbox[$i]['active'] == 1) ? $LANG['YES'] : $LANG['NO']; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + } + print "
" . $LANG['pAdminList_virtual_mailbox_username'] . "" . $LANG['pAdminList_virtual_mailbox_name'] . "" . $LANG['pAdminList_virtual_mailbox_quota'] . "" . $LANG['pAdminList_virtual_mailbox_modified'] . "" . $LANG['pAdminList_virtual_mailbox_active'] . " 
" . $tMailbox[$i]['username'] . "" . $tMailbox[$i]['name'] . "" . substr ($tMailbox[$i]['quota'], 0, -6) . "" . $tMailbox[$i]['modified'] . "" . $active . "" . $LANG['edit'] . "" . $LANG['del'] . "
\n"; + print "
\n"; + print "

\n"; +} +?> \ No newline at end of file diff --git a/templates/admin_menu.tpl b/templates/admin_menu.tpl new file mode 100644 index 00000000..b1f31311 --- /dev/null +++ b/templates/admin_menu.tpl @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + +
+   + +   + +   + +   + +   + +   + +   + +   + +   + +   +
+


diff --git a/templates/create-alias.tpl b/templates/create-alias.tpl new file mode 100644 index 00000000..07c748c6 --- /dev/null +++ b/templates/create-alias.tpl @@ -0,0 +1,57 @@ +
+ + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + + + +
+ + + + + +
+ + +
+

+ diff --git a/templates/create-mailbox.tpl b/templates/create-mailbox.tpl new file mode 100644 index 00000000..469ef1f3 --- /dev/null +++ b/templates/create-mailbox.tpl @@ -0,0 +1,116 @@ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; +} +?> + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + + + +
+ + + + + +
+ + + + +   +
+ + + + + +
\n"; + print " " . $LANG['pCreate_mailbox_quota'] . ":\n"; + print " \n"; + print " \n"; + print " \n"; + print " $pCreate_mailbox_quota_text\n"; + print "
+ + + + +   +
+ + + + +   +
+ + +
diff --git a/templates/delete.tpl b/templates/delete.tpl new file mode 100644 index 00000000..97824046 --- /dev/null +++ b/templates/delete.tpl @@ -0,0 +1,2 @@ +
+ diff --git a/templates/edit-alias.tpl b/templates/edit-alias.tpl new file mode 100644 index 00000000..343ed355 --- /dev/null +++ b/templates/edit-alias.tpl @@ -0,0 +1,49 @@ +
+ + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + +   +
+ + + + +   +
+ + +
diff --git a/templates/edit-mailbox.tpl b/templates/edit-mailbox.tpl new file mode 100644 index 00000000..b9b57285 --- /dev/null +++ b/templates/edit-mailbox.tpl @@ -0,0 +1,90 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; +} +?> + + + + + + + + +
+ +
+
+
+
+ +
+ + + +
+ + + + + +
+ + + + +   +
+ + + + +   +
\n"; + print " " . $LANG['pEdit_mailbox_quota'] . ":\n"; + print " \n"; + print " \n"; + print " \n"; + print " $pEdit_mailbox_quota_text\n"; + print "
+ + + + > + +   +
+ + +
diff --git a/templates/footer.tpl b/templates/footer.tpl new file mode 100644 index 00000000..34c66150 --- /dev/null +++ b/templates/footer.tpl @@ -0,0 +1,12 @@ +
+ + diff --git a/templates/header.tpl b/templates/header.tpl new file mode 100644 index 00000000..e10486ed --- /dev/null +++ b/templates/header.tpl @@ -0,0 +1,19 @@ + + + + + +\n"; +if (file_exists (realpath ("../stylesheet.css"))) print "\n"; +?> +Postfix Admin + + +
diff --git a/templates/login.tpl b/templates/login.tpl new file mode 100644 index 00000000..19cf7019 --- /dev/null +++ b/templates/login.tpl @@ -0,0 +1,69 @@ +\n"; +} +else +{ + print "

" . $CONF['header_text'] . "

\n"; +} +?> +

+

+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+

+ +

+

+
+
+
diff --git a/templates/main.tpl b/templates/main.tpl new file mode 100644 index 00000000..67182b1a --- /dev/null +++ b/templates/main.tpl @@ -0,0 +1,66 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

+

+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+
diff --git a/templates/menu.tpl b/templates/menu.tpl new file mode 100644 index 00000000..92f87d6a --- /dev/null +++ b/templates/menu.tpl @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + +
+   + +   + +   + +   + +   + +   + +   + +   +
+
diff --git a/templates/overview-get.tpl b/templates/overview-get.tpl new file mode 100644 index 00000000..1bf27b20 --- /dev/null +++ b/templates/overview-get.tpl @@ -0,0 +1,44 @@ +
+
+ + +
+

+\n"; +print "\n"; +print " \n"; +print " \n"; +print " \n"; +print " \n"; +if ($CONF['quota'] == 'YES') print " \n"; +print " \n"; + +for ($i = 0; $i < sizeof ($list_domains); $i++) +{ + $limit = get_domain_properties ($list_domains[$i]); + + print " \n"; + print " \n"; + print " \n"; + print " \n"; + if ($CONF['quota'] == 'YES') print " \n"; + print " \n"; +} +print "
" . $LANG['pOverview_get_domain'] . "" . $LANG['pOverview_get_aliases'] . "" . $LANG['pOverview_get_mailboxes'] . "" . $LANG['pOverview_get_quota'] . "
" . $list_domains[$i] . "" . $limit['alias_count'] . " / " . $limit['aliases'] . "" . $limit['mailbox_count'] . " / " . $limit['mailboxes'] . "" . $limit['maxquota'] . "
\n"; +print "

\n"; +?> diff --git a/templates/overview.tpl b/templates/overview.tpl new file mode 100644 index 00000000..e35d5957 --- /dev/null +++ b/templates/overview.tpl @@ -0,0 +1,85 @@ +

+
+ + +
+

+". $LANG['pOverview_welcome'] . $fDomain . "
\n"; +print $LANG['pOverview_alias_alias_count'] . ": " . $limit['alias_count'] . " / " . $limit['aliases'] . "   "; +print $LANG['pOverview_alias_mailbox_count'] . ": " . $limit['mailbox_count'] . " / " . $limit['mailboxes'] . "
\n"; +print "

\n"; + +if (sizeof ($tAlias) > 0) +{ + print "

\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + + for ($i = 0; $i < sizeof ($tAlias); $i++) + { + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + } + + print "
" . $LANG['pOverview_alias_address'] . "" . $LANG['pOverview_alias_goto'] . "" . $LANG['pOverview_alias_modified'] . " 
" . $tAlias[$i]['address'] . "" . ereg_replace (",", "
", $tAlias[$i]['goto']) . "
" . $tAlias[$i]['modified'] . "" . $LANG['edit'] . "" . $LANG['del'] . "
\n"; + print "
\n"; + print "

\n"; +} + +if (sizeof ($tMailbox) > 0) +{ + print "

\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + if ($CONF['quota'] == 'YES') print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + + for ($i = 0; $i < sizeof ($tMailbox); $i++) + { + print " \n"; + print " \n"; + print " \n"; + if ($CONF['quota'] == 'YES') print " \n"; + print " \n"; + $active = ($tMailbox[$i]['active'] == 1) ? $LANG['YES'] : $LANG['NO']; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + } + print "
" . $LANG['pOverview_mailbox_username'] . "" . $LANG['pOverview_mailbox_name'] . "" . $LANG['pOverview_mailbox_quota'] . "" . $LANG['pOverview_mailbox_modified'] . "" . $LANG['pOverview_mailbox_active'] . " 
" . $tMailbox[$i]['username'] . "" . $tMailbox[$i]['name'] . "" . substr ($tMailbox[$i]['quota'], 0, -6) . "" . $tMailbox[$i]['modified'] . "" . $active . "" . $LANG['edit'] . "" . $LANG['del'] . "
\n"; + print "
\n"; + print "

\n"; +} +?> \ No newline at end of file diff --git a/templates/password.tpl b/templates/password.tpl new file mode 100644 index 00000000..472875e7 --- /dev/null +++ b/templates/password.tpl @@ -0,0 +1,62 @@ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + + +
+ + + + + +
+ + + + + +
+ + + + +   +
+ + +
diff --git a/templates/sendmail.tpl b/templates/sendmail.tpl new file mode 100644 index 00000000..1b02c927 --- /dev/null +++ b/templates/sendmail.tpl @@ -0,0 +1,66 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + +   +
+ + + + +   +
+ + + + +   +
+ + + + +   +
+ + +
diff --git a/templates/users_edit-alias.tpl b/templates/users_edit-alias.tpl new file mode 100644 index 00000000..c3f33d13 --- /dev/null +++ b/templates/users_edit-alias.tpl @@ -0,0 +1,50 @@ +
+ + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + +   +
+ + + + +   +
+ + +
diff --git a/templates/users_login.tpl b/templates/users_login.tpl new file mode 100644 index 00000000..b2ace0c7 --- /dev/null +++ b/templates/users_login.tpl @@ -0,0 +1,62 @@ +\n"; +} +else +{ + print "

" . $CONF['header_text'] . "

\n"; +} +?> +

+

+ + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+
+
diff --git a/templates/users_main.tpl b/templates/users_main.tpl new file mode 100644 index 00000000..ed7519a4 --- /dev/null +++ b/templates/users_main.tpl @@ -0,0 +1,39 @@ +
+ + + + + \n"; + print " \n"; + print " \n"; + print "\n"; + } + ?> + + + + + + + + +
+ +

+

\n"; + print " " . $LANG['pUsersMenu_vacation'] . "\n"; + print " \n"; + print " " . $LANG['pUsersMain_vacation'] . "\n"; + print "
+ + + +
+ + + +
+
diff --git a/templates/users_menu.tpl b/templates/users_menu.tpl new file mode 100644 index 00000000..9645aa5a --- /dev/null +++ b/templates/users_menu.tpl @@ -0,0 +1,37 @@ + + + \n"; + print "  \n"; + print " \n"; + print " \n"; + } + ?> + + + + + + + + +
\n"; + print " " . $LANG['pUsersMenu_vacation'] . "\n"; + print " +   + +   + +   + +   +
+
diff --git a/templates/users_password.tpl b/templates/users_password.tpl new file mode 100644 index 00000000..cd221618 --- /dev/null +++ b/templates/users_password.tpl @@ -0,0 +1,62 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + + +
+ + + + + +
+ + + + + +
+ + + + +   +
+ + +
diff --git a/templates/users_vacation-get.tpl b/templates/users_vacation-get.tpl new file mode 100644 index 00000000..a3212aaa --- /dev/null +++ b/templates/users_vacation-get.tpl @@ -0,0 +1,17 @@ +
+ + + + + + + + +
+
+
+
+
+ +
+
diff --git a/templates/users_vacation.tpl b/templates/users_vacation.tpl new file mode 100644 index 00000000..78caa7e0 --- /dev/null +++ b/templates/users_vacation.tpl @@ -0,0 +1,42 @@ +
+ + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + +   +
+ + + + +   +
+ + +
diff --git a/templates/vcp.tpl b/templates/vcp.tpl new file mode 100644 index 00000000..da45c3e5 --- /dev/null +++ b/templates/vcp.tpl @@ -0,0 +1,62 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ +
+ + + +
+ + + + + +
+ + + + + +
+ + + + +   +
+ + +
diff --git a/templates/viewlog.tpl b/templates/viewlog.tpl new file mode 100644 index 00000000..9e9362ce --- /dev/null +++ b/templates/viewlog.tpl @@ -0,0 +1,53 @@ +
+
+ + +
+

+". $LANG['pViewlog_welcome'] . $fDomain . "
\n"; +print "

\n"; + +if (sizeof ($tLog) > 0) +{ + print "

\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + + for ($i = 0; $i < sizeof ($tLog); $i++) + { + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + } + + print "
" . $LANG['pViewlog_timestamp'] . "" . $LANG['pViewlog_username'] . "" . $LANG['pViewlog_domain'] . "" . $LANG['pViewlog_action'] . "" . $LANG['pViewlog_data'] . "
" . $tLog[$i]['timestamp'] . "" . $tLog[$i]['username'] . "" . $tLog[$i]['domain'] . "" . $tLog[$i]['action'] . "" . $tLog[$i]['data'] . "
\n"; + print "
\n"; + print "

\n"; +} +?> diff --git a/users/edit-alias.php b/users/edit-alias.php new file mode 100644 index 00000000..7a4abc59 --- /dev/null +++ b/users/edit-alias.php @@ -0,0 +1,97 @@ +"; + } + } + + if ($error != 1) + { + if (empty ($fGoto)) + { + $goto = $USERID_USERNAME; + } + else + { + $goto = $USERID_USERNAME . "," . $goto; + } + + $result = db_query ("UPDATE alias SET goto='$goto',modified=NOW() WHERE address='$USERID_USERNAME'"); + if ($result['rows'] != 1) + { + $tMessage = $LANG['pEdit_alias_result_error']; + } + else + { + db_log ($USERID_USERNAME, $USERID_DOMAIN, "edit alias", "$USERID_USERNAME -> $goto"); + + header ("Location: main.php"); + exit; + } + } + + include ("../templates/header.tpl"); + include ("../templates/users_menu.tpl"); + include ("../templates/users_edit-alias.tpl"); + include ("../templates/footer.tpl"); +} +?> diff --git a/users/index.php b/users/index.php new file mode 100644 index 00000000..51dde5c3 --- /dev/null +++ b/users/index.php @@ -0,0 +1,17 @@ + diff --git a/users/login.php b/users/login.php new file mode 100644 index 00000000..0da789bc --- /dev/null +++ b/users/login.php @@ -0,0 +1,68 @@ + diff --git a/users/logout.php b/users/logout.php new file mode 100644 index 00000000..e8afaff6 --- /dev/null +++ b/users/logout.php @@ -0,0 +1,25 @@ + diff --git a/users/main.php b/users/main.php new file mode 100644 index 00000000..b61f213f --- /dev/null +++ b/users/main.php @@ -0,0 +1,36 @@ + diff --git a/users/password.php b/users/password.php new file mode 100644 index 00000000..a3fb6931 --- /dev/null +++ b/users/password.php @@ -0,0 +1,89 @@ + diff --git a/users/vacation.php b/users/vacation.php new file mode 100644 index 00000000..fc0101aa --- /dev/null +++ b/users/vacation.php @@ -0,0 +1,88 @@ + diff --git a/viewlog.php b/viewlog.php new file mode 100644 index 00000000..8dc66daf --- /dev/null +++ b/viewlog.php @@ -0,0 +1,78 @@ + 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tLog[] = $row; + } + } + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/viewlog.tpl"); + include ("./templates/footer.tpl"); +} + +if ($_SERVER['REQUEST_METHOD'] == "POST") +{ + $fDomain = $_POST['fDomain']; + + if (!check_owner ($SESSID_USERNAME, $fDomain)) + { + $error = 1; + $tMessage = $LANG['pViewlog_error']; + } + + if ($error != 1) + { + $result = db_query ("SELECT * FROM log WHERE domain='$fDomain' ORDER BY timestamp DESC LIMIT 10"); + if ($result['rows'] > 0) + { + while ($row = mysql_fetch_array ($result['result'])) + { + $tLog[] = $row; + } + } + } + + include ("./templates/header.tpl"); + include ("./templates/menu.tpl"); + include ("./templates/viewlog.tpl"); + include ("./templates/footer.tpl"); +} +?>