From: Ben Klang Date: Wed, 16 Sep 2009 16:16:37 +0000 (-0400) Subject: Import Vilma from CVS X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=6f4a176845914aff70ace06bfefa0a6893afa34e;p=horde.git Import Vilma from CVS --- diff --git a/vilma/LICENSE b/vilma/LICENSE new file mode 100644 index 000000000..ae5539eb4 --- /dev/null +++ b/vilma/LICENSE @@ -0,0 +1,49 @@ +Version 1.0 + +Copyright 2001-2009 The Horde Project (http://www.horde.org/) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. 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. + +3. The end-user documentation included with the redistribution, if +any, must include the following acknowledgment: + + "This product includes software developed by the Horde Project + (http://www.horde.org/)." + +Alternately, this acknowledgment may appear in the software itself, if +and wherever such third-party acknowledgments normally appear. + +4. The names "Horde", "The Horde Project", and "Vilma" must not be +used to endorse or promote products derived from this software without +prior written permission. For written permission, please contact +core@horde.org. + +5. Products derived from this software may not be called "Horde" or +"Vilma", nor may "Horde" or "Vilma" appear in their name, without +prior written permission of the Horde Project. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED 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 HORDE PROJECT OR ITS 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. + +This software consists of voluntary contributions made by many +individuals on behalf of the Horde Project. For more information on +the Horde Project, please see . diff --git a/vilma/README b/vilma/README new file mode 100644 index 000000000..d1b48826f --- /dev/null +++ b/vilma/README @@ -0,0 +1,65 @@ +What is Vilma? +-------------- + +Vilma is a tool for administrators who need to handle various aspects +of domain administration. + + +Obtaining Vilma +--------------- + +Further information on Vilma and the latest version can be obtained at: + + http://www.horde.org/vilma/ + + +Documentation +------------- + +The following documentation is available in the Vilma distribution: + +README - This file +LICENSE - Copyright and license information +docs/CHANGES - List of changes by release +docs/CREDITS - Who developed this +docs/INSTALL - Installation instructions + + +Installation +------------ + +Instructions for installing Vilma can be found in the file INSTALL in the +docs/ directory of the Vilma distribution. + + +Assistance +---------- + +If you encounter problems with Vilma, help is available! + +The Horde Frequently Asked Questions List (FAQ), available on the Web at: + + http://www.horde.org/faq/ + +The Horde Project runs a number of mailing lists, for individual applications +and for issues relating to the project as a whole. Information, archives, and +subscription information can be found at: + + http://www.horde.org/mail/ + +Lastly, Horde developers, contributors and users also make occasional +appearances on IRC, on the channel #horde on the Freenode Network +(irc.freenode.net). + + +Licensing +--------- + +For licensing and copyright information, please see the file LICENSE in the +Vilma distribution. + +Thanks, + +The Vilma team + +$Horde: vilma/README,v 1.3 2007/08/05 22:37:11 mp Exp $ diff --git a/vilma/config/.cvsignore b/vilma/config/.cvsignore new file mode 100644 index 000000000..de7b27844 --- /dev/null +++ b/vilma/config/.cvsignore @@ -0,0 +1,2 @@ +conf.php +conf.bak.php diff --git a/vilma/config/conf.xml b/vilma/config/conf.xml new file mode 100644 index 000000000..67674ddd5 --- /dev/null +++ b/vilma/config/conf.xml @@ -0,0 +1,179 @@ + + + + + + + These are the settings for storing all the Vilma data, such as domains, + users within those domains, virtual addresses for users, etc. + + + 0 + 0 + + sql + + + + + + default + + + + + + + + + + + + + + + + default + + + + + + + + + + + + + + + + + + + + default + + + + + + + + + + + + + + + + + + localhost + + + + 3 + 3 + 2 + 3 + + + + objectclass + + + + + + + + + + + + + + + + + + + + Mailbox settings + maildrop + + + 1003 + 1000 + /home/vmail + vmail + true + + + + + + + localhost + 143 + imap + user. + + + + + + + + + + + + + + + + + MTA Settings + maildrop + + + + + + + + + + + + + diff --git a/vilma/config/hooks.php.dist b/vilma/config/hooks.php.dist new file mode 100644 index 000000000..101d2535a --- /dev/null +++ b/vilma/config/hooks.php.dist @@ -0,0 +1,103 @@ + _("Display listings"), + 'label' => _("Display details"), + 'desc' => _("Set default display parameters."), + 'members' => array('addresses_perpage')); + +// listing +$_prefs['addresses_perpage'] = array( + 'value' => 20, + 'locked' => false, + 'shared' => false, + 'type' => 'number', + 'desc' => _("How many domain to display per page.")); diff --git a/vilma/docs/CHANGES b/vilma/docs/CHANGES new file mode 100644 index 000000000..7a56b6512 --- /dev/null +++ b/vilma/docs/CHANGES @@ -0,0 +1,16 @@ +-------- +v0.1-cvs +-------- + +[bkl] Restructure application to have Users, Aliases, Groups and Forwards. +[bkl] Add qmailldap backend support. +[ben] Better support for MS-SQL. +[jan] Allow to use custom table and column names (guilleva@gmail.com, + Request #3244). +[cjh] Use bind variables in SQL driver (selsky@columbia.edu, Request #1795). +[jmf] Downcase user and virtuals. +[jmf] Support for virtuals with external (non-local) e-mail destinations. +[jan] Add Spanish translation (Manuel Perez Ayala ). +[jmf] Add support for creating mailboxes via IMAP protocol. +[jan] Add Lithuanian translation (Vilius ¦umskas ). +[jan] Add German translation. diff --git a/vilma/docs/CREDITS b/vilma/docs/CREDITS new file mode 100644 index 000000000..334ec6fa7 --- /dev/null +++ b/vilma/docs/CREDITS @@ -0,0 +1,26 @@ +======================================= +|| Vilma Version 1.0 Development Team || +======================================== + +=============== +Core Developers +=============== + +Marko Djukic +- Initial authoring. + +Ben Klang +- Rewrite for Aliases and Groups/Forwards + + +============ +Localization +============ + +German Jan Schneider +Italian Marko Djukic +Lithuanian Vilius ¦umskas +Spanish Manuel Perez Ayala + + +$Horde: vilma/docs/CREDITS,v 1.7 2008/03/22 10:43:53 jan Exp $ diff --git a/vilma/docs/INSTALL b/vilma/docs/INSTALL new file mode 100644 index 000000000..3bf7b70a1 --- /dev/null +++ b/vilma/docs/INSTALL @@ -0,0 +1,196 @@ +============================== +|| INSTALLING Vilma 0.1 || +============================== + +* PLEASE SEE IMPORTANT NOTE in the README file about Vilma's status +before you try to install it and are disappointed. + +This document contains instructions for installing the Vilma virtual mail +domain management application. + +For information on the capabilities and features of Vilma, see the +file README in the top-level directory of the Vilma distribution. + + +OBTAINING VILMA +----------------- + +Vilma can be obtained from the Horde website and FTP server, at + + http://www.horde.org/vilma/ + ftp://ftp.horde.org/pub/vilma/ + +Bleeding-edge development versions of Vilma are available via CVS; see +the file docs/HACKING in the Horde distribution for information on +accessing the Horde CVS repository. + + +PREREQUISITES +------------- + +To function properly, Vilma requires the following: + + 1. A working Horde installation. + + Vilma runs within the Horde Application Framework, a set of + common tools for Web applications written in PHP. You must + install Horde before installing Vilma. + + The Horde Framework can be obtained from the Horde website and + FTP server, at + + http://www.horde.org/horde/ + ftp://ftp.horde.org/pub/horde/ + + Many of Vilma's prerequisites are also Horde prerequisites. + Be sure to have completed all of the steps in the INSTALL + file for the Horde Framework before installing Vilma. + + 2. SQL support in PHP. + + Vilma store its data in an SQL database. Build PHP with whichever + SQL driver you require; see the Horde INSTALL file for details. + + +INSTALLING VILMA +------------------ + +Vilma is written in PHP, and must be installed in a web-accessible +directory. The precise location of this directory will differ from +system to system. Conventionally, Vilma is installed directly underneath +Horde in the webserver's document tree. + +Since Vilma is written in PHP, there is no compilation necessary; +simply expand the distribution where you want it to reside and rename +the root directory of the distribution to whatever you wish to appear +in the URL. For example, with the Apache webserver's default document +root of '/usr/local/apache/htdocs', you would type: + + cd /usr/local/apache/htdocs/horde + tar zxvf /path/to/vilma-0.1.tar.gz + mv vilma-0.1 vilma + +and would then find Vilma at the URL + + http://your-server/horde/vilma/ + + +CONFIGURING VILMA +------------------- + +1. Configuring Horde for Vilma + + a. Register the application + + In horde/config/registry.php, find the applications['vilma'] stanza. + The default settings here should be okay, but you can change + them if desired. If you have changed the location of Vilma relative + to Horde, either in the URL, in the filesystem or both, you must + update the 'fileroot' and 'webroot' settings to their correct + values. + +2. Creating the database table + + The specific steps to create the Vilma database table depend + on which database you've chosen to use. + + First, look in scripts/drivers/ to see if a script already + exists for your database type. If so, you should be + able to simply execute that script as superuser in your + database. (Note that executing the script as the "horde" user will + probably fail when granting privileges.) + + If such a script does not exist, you'll need to build your own, using + the file vilma.sql as a starting point. If you need + assistance in creating databases, you may wish to let us know on + the Vilma mailing list. + +3. Configuring Vilma. + + To configure Vilma, change to the config/ directory of the + installed distribution, and make copies of all of the configuration + "dist" files without the "dist" suffix: + + cd config/ + for foo in *.dist; do cp $foo `basename $foo .dist`; done + + Documentation on the format of those files can be found in each + file. With the exception of the conf.* files (see below), + the other files in config/ need only be modified if you wish + to customize Vilma's appearance or behavior, as the defaults will + be correct for most sites. + + You must login to Horde as a Horde Administrator to finish the + configuring of Vilma. Use the Horde "Administration" menu item to get + to the Administration page, and then click on the "Configuration" + icon to get the Configuration page. Select "Tasks" from the selection + list of applications, and click on the "Configure" button. Fill in or + change any configuration values as needed. When done click on "Generate + Tasks Configuration" to generate the conf.php file. If your web server + doesn't have write permissions to the Vilma configuration directory or + file, it will not be able to write the file. In this case, cut and + paste the returned configuration information into the file + vilma/config/conf.php. + + Note for international users: Vilma uses GNU gettext to provide local + translations of text displayed by applications; the translations are + found in the po/ directory. If a translation is not yet available + for your locale (and you wish to create one), or if you're having + trouble using a provided translation, please see the horde/docs/TRANSLATIONS + file for instructions. + +4. Testing Vilma + + Use Vilma to create, modify, and delete forms. Test at + least the following: + + - Creating a form + - Modifying a form + - Viewing and submitting a form + - Deleting a form + + +SAMPLE USAGE +------------ + +Vilma can be embedded internally within Horde in any application which +supports the Horde Blocks API. + +Otherwise Vilma can be called from any web page with the following simple +php code: + + . '/display.php'; + ?> + + +OBTAINING SUPPORT +----------------- + +If you encounter problems with Vilma, help is available! + +The Horde Frequently Asked Questions List (FAQ), available on the Web +at + + http://www.horde.org/faq/ + +The Horde Project runs a number of mailing lists, for individual +applications and for issues relating to the project as a whole. +Information, archives, and subscription information can be found at + + http://www.horde.org/mail/ + +Lastly, Horde developers, contributors and users may also be found on IRC, +on the channel #horde on the Freenode Network (irc.freenode.net). + +Please keep in mind that Vilma is free software written by volunteers. +For information on reasonable support expectations, please read + + http://www.horde.org/support.php + +Thanks for using Vilma! + +The Vilma team + +$Horde: vilma/docs/INSTALL,v 1.6 2007/08/30 05:10:06 chuck Exp $ diff --git a/vilma/docs/TODO b/vilma/docs/TODO new file mode 100644 index 000000000..c36707385 --- /dev/null +++ b/vilma/docs/TODO @@ -0,0 +1,17 @@ +=========================== +Vilma Development TODO List +=========================== + +* Implement an audit trail so that we know when and by whom accounts were + created, deleted, modified, etc. + +* Integrate with Beatnik to allow DNS zone and MX records to be created upon + domain creation + +* Abstract domains driver from accounts driver + +* Create Beatnik-integrated domains driver + +* Throw proper error if MySQL module not installed in PHP + +$Horde: vilma/docs/TODO,v 1.7 2007/08/06 00:08:29 mp Exp $ diff --git a/vilma/domains/delete.php b/vilma/domains/delete.php new file mode 100644 index 000000000..b73bfe579 --- /dev/null +++ b/vilma/domains/delete.php @@ -0,0 +1,57 @@ + + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; +require_once 'Horde/Form.php'; +require_once VILMA_BASE . '/lib/Forms/DeleteDomainForm.php'; + +/* Only admin should be using this. */ +if (!Vilma::hasPermission($domain)) { + Horde::authenticationFailureRedirect(); +} + +$vars = Horde_Variables::getDefaultVariables(); +$form = new DeleteDomainForm($vars); + +if ($vars->get('submitbutton') == _("Delete")) { + if ($form->validate($vars)) { + $form->getInfo($vars, $info); + $delete = $vilma_driver->deleteDomain($info['domain_id']); + if (is_a($delete, 'PEAR_Error')) { + Horde::logMessage($delete, __FILE__, __LINE__, PEAR_LOG_ERR); + $notification->push(sprintf(_("Error deleting domain. %s."), $delete->getMessage()), 'horde.error'); + } else { + $notification->push(_("Domain deleted."), 'horde.success'); + $url = Horde::applicationUrl('domains/index.php', true); + header('Location: ' . $url); + exit; + } + } +} elseif ($vars->get('submitbutton') == _("Do not delete")) { + $notification->push(_("Domain not deleted."), 'horde.message'); + header('Location: ' . Horde::applicationUrl('domains/index.php')); + exit; +} + +/* Render the form. */ +require_once 'Horde/Form/Renderer.php'; +$renderer = new Horde_Form_Renderer(); +$main = Horde_Util::bufferOutput(array($form, 'renderActive'), $renderer, $vars, 'delete.php', 'post'); + +$template->set('main', $main); +$template->set('menu', Vilma::getMenu('string')); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); + +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/main/main.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/vilma/domains/edit.php b/vilma/domains/edit.php new file mode 100644 index 000000000..492430e8b --- /dev/null +++ b/vilma/domains/edit.php @@ -0,0 +1,53 @@ + + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; +require_once 'Horde/Form.php'; +require_once VILMA_BASE . '/lib/Forms/EditDomainForm.php'; + +/* Only admin should be using this. */ +if (!Vilma::hasPermission($domain)) { + Horde::authenticationFailureRedirect(); +} + +//$domain_id = Horde_Util::getFormData('domain_id'); +$vars = Horde_Variables::getDefaultVariables(); +$form = new EditDomainForm($vars); + +if ($form->validate($vars)) { + $form->getInfo($vars, $info); + $info['name'] = Horde_String::lower($info['name']); + $domain_id = $vilma_driver->saveDomain($info); + if (is_a($domain_id, 'PEAR_Error')) { + Horde::logMessage($domain_id, __FILE__, __LINE__, PEAR_LOG_ERR); + $notification->push(sprintf(_("Error saving domain: %s."), $domain_id->getMessage()), 'horde.error'); + } else { + $notification->push(_("Domain saved."), 'horde.success'); + $url = Horde::applicationUrl('domains/index.php', true); + header('Location: ' . $url); + exit; + } +} + +/* Render the form. */ +require_once 'Horde/Form/Renderer.php'; +$renderer = &new Horde_Form_Renderer(); +$main = Horde_Util::bufferOutput(array($form, 'renderActive'), $renderer, $vars, 'edit.php', 'post'); + +$template->set('main', $main); +$template->set('menu', Vilma::getMenu('string')); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); + +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/main/main.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/vilma/domains/index.php b/vilma/domains/index.php new file mode 100644 index 000000000..5564137c9 --- /dev/null +++ b/vilma/domains/index.php @@ -0,0 +1,51 @@ + + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; + +/* Only admin should be using this. */ +if (!Vilma::hasPermission($domain)) { + Horde::authenticationFailureRedirect(); +} + +// Having a current domain doesn't make sense on this page +Vilma::setCurDomain(false); + +$domains = $vilma_driver->getDomains(); +if (is_a($domains, 'PEAR_Error')) { + $notification->push($domains, 'horde.error'); + $domains = array(); +} +foreach ($domains as $id => $domain) { + $url = Horde::applicationUrl('domains/edit.php'); + $domains[$id]['edit_url'] = Horde_Util::addParameter($url, 'domain_id', $domain['domain_id']); + $url = Horde::applicationUrl('domains/delete.php'); + $domains[$id]['del_url'] = Horde_Util::addParameter($url, 'domain_id', $domain['domain_id']); + $url = Horde::applicationUrl('users/index.php'); + $domains[$id]['view_url'] = Horde_Util::addParameter($url, 'domain_id', $domain['domain_id']); +} + +/* Set up the template fields. */ +$template->set('domains', $domains, true); +$template->set('menu', Vilma::getMenu('string')); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); + +/* Set up the field list. */ +$images = array('delete' => Horde::img('delete.png', _("Delete Domain"), '', $registry->getImageDir('horde')), + 'edit' => Horde::img('edit.png', _("Edit Domain"), '', $registry->getImageDir('horde'))); +$template->set('images', $images); + +/* Render the page. */ +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/domains/index.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/vilma/index.php b/vilma/index.php new file mode 100644 index 000000000..d3e8a868f --- /dev/null +++ b/vilma/index.php @@ -0,0 +1,24 @@ + + */ + +@define('VILMA_BASE', dirname(__FILE__)); +require_once VILMA_BASE . '/lib/base.php'; + +$vilma_configured = (@is_readable(VILMA_BASE . '/config/conf.php') && + @is_readable(VILMA_BASE . '/config/prefs.php')); + +if (!$vilma_configured) { + require VILMA_BASE . '/../lib/Test.php'; + Horde_Test::configFilesMissing('Vilma', VILMA_BASE, array('conf.php', 'prefs.php')); +} + +require VILMA_BASE . '/domains/index.php'; diff --git a/vilma/lib/Driver.php b/vilma/lib/Driver.php new file mode 100644 index 000000000..8868336cf --- /dev/null +++ b/vilma/lib/Driver.php @@ -0,0 +1,423 @@ + + * @package Vilma + */ +class Vilma_Driver { + + /** + * A hash containing any parameters for the current driver. + * + * @var array + */ + var $_params = array(); + + /** + * Constructor + * + * @param array $params Any parameters needed for this driver. + */ + function Vilma_Driver($params) + { + $this->_params = $params; + } + + /** + * Returns all the users sorted by domain and as arrays of each domain. + * + * @return array An array of domains then users for each domain. + */ + function getAllUsers() + { + /* Get all users from backend. */ + $users = &$this->getUsers(); + + /* Determine the domain for each user and plug into array by domain. */ + $users_by_domain = array(); + foreach ($users as $user) { + $domain_name = Vilma::stripDomain($user['user_name']); + $users_by_domain[$domain_name][] = $user; + } + + /* Sort by domain. */ + ksort($users_by_domain); + /* Sort each domain's users by user name. */ + require_once 'Horde/Array.php'; + foreach ($users_by_domain as $key => $val) { + Horde_Array::arraySort($users_by_domain[$key], 'user_name'); + } + + return $users_by_domain; + } + + /** + * Checks if the given domain is below the maximum allowed users. + * + * @param string $domain The domain name to check. + * + * @return boolean True if the domain does not have a maximum limit (0) or + * current number of users is below the maximum number + * allowed. Otherwise false. + */ + function isBelowMaxUsers($domain) + { + /* Get the maximum number of users for this domain. */ + $max_users = $this->getDomainMaxUsers($domain); + if ($max_users == '0') { + /* No maximum. */ + return true; + } + + /* Get the current number of users. */ + $num_users = $this->getDomainNumUsers($domain); + + return ($num_users < $max_users); + } + + /** + * Gets an array of information related to the address passed in. + * This method may be overridden by the backend driver if there is a more + * efficient way to do this than a linear array search + * + * @param string $address Address for which information will be pulled + * @param string $type Address type to request + * One of 'user', 'alias', 'grpfwd' or 'any' + * Defaults to 'any' + * + * @return mixed Array of user information on success, empty array + * if the user does not exist, PEAR_Error on failure + */ + function getAddressInfo($address, $type = 'all') + { + $domain = Vilma::stripDomain($address); + $addresses = $this->getAddresses($domain, $type); + foreach($addresses as $addrinfo) { + if ($addrinfo['id'] == $address) { + return $addrinfo; + } else if ($addrinfo['address'] == $address) { + return $addrinfo; + } + } + return PEAR::raiseError(sprintf(_("No such address %s of type %s found."), $address, $type)); + } + + /** + * Does a series of checks for a given user to determine the status. + * + * @param array $user The user's details in an array as returned by the + * getUser() function. + * + * @return array Either an array of error messages found during the checks + * or an array with a single element stating that the user + * is ready. + */ + function getUserStatus($user) + { + /* Some needed vars. */ + $no_error = true; + $status = array(); + $domain_name = Vilma::stripDomain($user['user_name']); + $user_name = Vilma::stripUser($user['user_name']); + + /* Check if user enabled. */ + if ($user['user_enabled'] !== 'active') { + $no_error = false; + $err_msg = _("User disabled."); + $status[] = Horde::img('alerts/error.png', $err_msg, 'align="middle"', $GLOBALS['registry']->getImageDir('horde')) . ' ' . $err_msg; + } + + /* Check if mailbox exists. */ + $mailboxes = &Vilma::getMailboxDriver(); + if (is_a($mailboxes, 'PEAR_Error')) { + $no_error = false; + $err_msg = $mailboxes->getMessage(); + $status[] = Horde::img('alerts/warning.png', $err_msg, 'align="middle"', $GLOBALS['registry']->getImageDir('horde')) . ' ' . $err_msg; + } + $result = $mailboxes->checkMailbox($user_name, $domain_name); + if (is_a($result, 'PEAR_Error')) { + $no_error = false; + $err_msg = $result->getMessage(); + $status[] = Horde::img('alerts/warning.png', $err_msg, 'align="middle"', $GLOBALS['registry']->getImageDir('horde')) . ' ' . $err_msg; + } + + /* TODO: Quota checking would be nice too. */ + + /* If no errors have been found output a success message for this + * user's status. */ + if ($no_error) { + $msg = _("User ready."); + $status = array(Horde::img('alerts/success.png', $msg, 'align="middle"', $GLOBALS['registry']->getImageDir('horde')) . ' ' . $msg); + } + return $status; + } + + function saveUser(&$info) + { + $create = false; + if (empty($info['user_id'])) { + $create = true; + } + + $result = $this->_saveUser($info); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + if ($create) { + $mailboxes = &Vilma::getMailboxDriver(); + if (is_a($mailboxes, 'PEAR_Error')) { + $this->_deleteUser($result['user_id']); + return $mailboxes; + } + + $mailbox = $mailboxes->createMailbox(Vilma::stripUser($info['user_name']), Vilma::stripDomain($info['user_name'])); + if (is_a($mailbox, 'PEAR_Error')) { + //echo $mailbox->getMessage() . '
'; + //No 'system_user' parameter specified to maildrop driver. + //$this->_deleteUser($result['user_id']); + return $mailbox; + } + } + + if (isset($GLOBALS['conf']['mta']['auth_update_script']) && + !empty($info['password'])) { + $cmd = sprintf('%s set %s %s 2>&1', + $GLOBALS['conf']['mta']['auth_update_script'], + escapeshellarg($info['user_name']), + escapeshellarg($info['password'])); + $msg = system($cmd, $ec); + if ($msg === false) { + return PEAR::raiseError(_("Error running authentication update script.")); + } + if ($ec != 0) { + if (empty($msg)) { + $msg = _("Unknown error running authentication update script."); + } + return PEAR::raiseError($msg); + } + } + + return true; + } + + function deleteUser($user_id) + { + return PEAR::raiseError(_("Vilma_Driver::deleteUser(): Method Not Implemented.")); + } + + /** + * Saves a given domain with the provided information. + * + * @param array $info Array of details to save the domain + * + * @return mixed True on success, or PEAR_Error on failure. + */ + function saveDomain(&$info) + { + $domain_id = $this->_saveDomain($info); + if (is_a($domain_id, 'PEAR_Error')) { + return $domain_id; + } + + $ret = Horde::callHook('_vilma_hook_savedomain', array($info), 'vilma'); + if (!$ret) { + return PEAR::raiseError(_("Domain added but an error was encountered while calling the configured hook. Contact your administrator for futher assistance.")); + } + + return $domain_id; + } + + /** + * Saves the domain record. + * + * @abstract + * @param array $info Information to save the domain + * + * @return mixed True on success, or PEAR_Error on failure. + */ + function _saveDomain(&$info) + { + return PEAR::raiseError(_("Not implemented.")); + } + + /** + * Deletes a given domain and all the users and virtuals under it. + * + * @param integer $domain_id The id of the domain to delete. + * + * @return mixed True on success, or PEAR_Error on failure. + */ + function deleteDomain($domain_id) + { + $domain_record = $this->getDomain($domain_id); + if (is_a($domain_record, 'PEAR_Error')) { + return $domain_record; + } + + $users = $this->getUsers($domain_record['domain_name']); + if (is_a($users, 'PEAR_Error')) { + return $users; + } + + foreach ($users as $user) { + $this->_deleteUser($user['user_id']); + } + + $ret = $this->_deleteDomain($domain_id); + if (is_a($ret, 'PEAR_Error')) { + return $ret; + } + + $ret = Horde::callHook('_vilma_hook_deletedomain', + array($domain_record['domain_name']), + 'vilma'); + if (!$ret) { + return PEAR::raiseError(_("Error while calling hook to delete domain.")); + } + } + + /** + * Deletes the domain record. + * + * @abstract + * @param integer $domain_id The ID of the domain to delete. + * + * @return mixed True on success, or PEAR_Error on failure. + */ + function _deleteDomain($domain_id) + { + return PEAR::raiseError(_("Not implemented.")); + } + + /** + * Get the user who is the domain admin. + * + * @todo This should be replaced by moving all permissions into Horde + * permissions. + */ + function getDomainAdmin($domain_name) + { + $domain = $this->getDomainByName($domain_name); + if (is_a($domain, 'PEAR_Error')) { + return $domain; + } + return $domain['domain_admin']; + } + + /** + * Returns the configured quota for this domain. + * + * @param string $domain_name The name of the domain for which to + * return the quota. + * + * @return integer The domain's quota. + */ + function getDomainQuota($domain_name) + { + $domain = $this->getDomainByName($domain_name); + if (is_a($domain, 'PEAR_Error')) { + return $domain; + } + return $domain['domain_quota']; + } + + /** + * Returns the maximum number of users allowed for a given domain. + * + * @param string $domain_name The name of the domain for which to + * return the maximum users. + * + * @return integer The maximum number of allowed users or PEAR_Error on + * failure. + */ + function getDomainMaxUsers($domain_name) + { + $domain = $this->getDomainByName($domain_name); + if (is_a($domain, 'PEAR_Error')) { + return $domain; + } + return $domain['max_users']; + } + + /** + * Attempts to return a concrete Vilma_Driver instance based on $driver. + * + * @param string $driver The type of concrete Vilma_Driver subclass to + * return. + * @param array $params A hash containing any additional configuration or + * connection parameters a subclass might need. + * + * @return Vilma_Driver The newly created concrete Vilma_Driver instance, + * or false on error. + */ + function factory($driver = null, $params = null) + { + if (is_null($driver)) { + $driver = $GLOBALS['conf']['storage']['driver']; + } + $driver = basename($driver); + + if (is_null($params)) { + $params = Horde::getDriverConfig('storage', $driver); + } + + include_once dirname(__FILE__) . '/Driver/' . $driver . '.php'; + $class = 'Vilma_Driver_' . $driver; + if (class_exists($class)) { + return new $class($params); + } else { + Horde::fatal(PEAR::raiseError(sprintf(_("No such backend \"%s\" found"), $driver)), __FILE__, __LINE__); + } + } + + /** + * Attempts to return a reference to a concrete Vilma_Driver instance + * based on $driver. + * + * It will only create a new instance if no Vilma_Driver instance with the + * same parameters currently exists. + * + * This should be used if multiple storage sources are required. + * + * This method must be invoked as: $var = &Vilma_Driver::singleton() + * + * @param string $driver The type of concrete Vilma_Driver subclass to + * return. + * @param array $params A hash containing any additional configuration or + * connection parameters a subclass might need. + * + * @return mixed The created concrete Vilma_Driver instance, or false on + * error. + */ + function &singleton($driver = null, $params = null) + { + static $instances; + + if (is_null($driver)) { + $driver = $GLOBALS['conf']['storage']['driver']; + } + + if (is_null($params)) { + $params = Horde::getDriverConfig('storage', $driver); + } + + if (!isset($instances)) { + $instances = array(); + } + + $signature = serialize(array($driver, $params)); + if (!isset($instances[$signature])) { + $instances[$signature] = Vilma_Driver::factory($driver, $params); + } + + return $instances[$signature]; + } + +} diff --git a/vilma/lib/Driver/qmailldap.php b/vilma/lib/Driver/qmailldap.php new file mode 100644 index 000000000..d3486133c --- /dev/null +++ b/vilma/lib/Driver/qmailldap.php @@ -0,0 +1,1044 @@ + + * + * See the enclosed file LICENSE for license information (BSD). If you did + * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE. + * + * $Horde: vilma/lib/Driver/qmailldap.php,v 1.26 2009/07/08 20:16:22 bklang Exp $ + * + * @author Ben Klang + * @author David Cummings + * @package Vilma + */ + +require_once 'Horde/SQL.php'; + +class Vilma_Driver_qmailldap extends Vilma_Driver { + + /** + * @var _LDAP Reference to initialized LDAP driver + */ + var $_ldap; + + /** + * @var _dbparams Configuration parameters for the LDAP driver + */ + var $_ldapparams; + + /** + * @var _db Reference to the initialized database driver + */ + var $_db; + + /** + * @var _dbparams Configuration parameters for the database driver + */ + var $_dbparams; + + function Vilma_Driver_qmailldap($params) + { + parent::Vilma_Driver($params); + $this->_ldapparams = $this->_params['ldap']; + $this->_sqlparams = Horde::getDriverConfig('storage', 'sql'); + $res = $this->_connect(); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + /* Connect to the backend for tracking domains. */ + $this->_dbinit(); + } + + /** + * Gets the list of domains from the backend. + * + * @return array All the domains and their data in an array. + */ + function getDomains() + { + $sql = 'SELECT domain_id, domain_name, domain_transport, ' . + 'domain_max_users, domain_quota FROM vilma_domains ' . + 'ORDER BY domain_name'; + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); + } + + /** + * Gets the specified domain information from the backend. + * + * @param integer $domain_id The id of the domain to fetch. + * + * @return array The domain's information in an array. + */ + function getDomain($domain_id) + { + $sql = 'SELECT domain_id, domain_name, domain_transport, ' . + 'domain_max_users, domain_quota FROM vilma_domains ' . + 'WHERE domain_id=? ORDER BY domain_name'; + $values = array($domain_id); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC); + } + + /** + * Given a domain name returns the information from the backend. + * + * @param string $name The name of the domain to fetch. + * + * @return array The domain's information in an array. + */ + function getDomainByName($domain_name) + { + $sql = 'SELECT domain_id, domain_name, domain_transport, ' . + 'domain_max_users, domain_quota FROM vilma_domains ' . + 'WHERE domain_name=?'; + $values = array($domain_name); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC); + } + + /** + * Returns a list of all users, aliases, or groups and forwards for a + * domain. + * + * @param string $domain Domain on which to search. + * @param string $type Only return a specific type. One of 'all', + * 'user', 'alias','forward', or 'group'. + * @param string $key Sort list by this key. + * @param integer $direction Sort direction. + * + * @return array Account information for this domain + */ + function getAddresses($domain, $type = 'all', $key = 'user_name', + $direction = 0) + { + $addresses = array(); + if ($type == 'all' || $type == 'user') { + $users = $this->_getUsers($domain); + $addresses = array_merge($addresses, $users); + } + if ($type == 'all' || $type == 'alias') { + $aliases = $this->_getAliases($domain); + $addresses = array_merge($addresses, $aliases); + } + if (($type == 'all') || ($type == 'forward')) { + $forwards = $this->_getGroupsAndForwards('forward',$domain); + $addresses = array_merge($addresses, $forwards); + } + if (($type == 'all') || ($type == 'group')) { + $groups = $this->_getGroupsAndForwards('group',$domain); + $addresses = array_merge($addresses, $groups); + } + // Sort the results + require_once 'Horde/Array.php'; + Horde_Array::arraySort($addresses, $key, $direction, true); + return $addresses; + } + + function getUser($user_id) { + $user = $this->getUserStatus($user_id); + + if (is_a($user, 'PEAR_Error')) { + return PEAR::raiseError(sprintf(_("Unable to qualify address: %s"), $user->getMessage())); + } + if(isset($user) && is_array($user)) { + return $user; + } else { + return PEAR::raiseError(_("Unable to qualify address.")); + } + } + + /** + * Returns an array of all users, aliases, groups and forwards for this + * domain. + * + * @param string $domain Domain on which to search + * @param optional string $type Only return a specific type + * + * @return array Account information for this domain + */ + function _getUsers($domain = null) + { + //$domain = $domain['domain_name']; + // Cache for multiple calls + static $users = array(); + if (is_null($domain) && isset($users['_all'])) { + return $users['_all']; + } + + if (!is_null($domain) + && isset($users[$domain])) { + return $users[$domain]; + } + + $filter = '(&'; + if (!is_null($domain)) { + $filter .= '(mail=*@' . $domain . ')'; + } else { + $domain = '_all'; + } + + // Make sure we don't get any forwards + $filter .= '(!(mailForwardingAddress=*))'; + + // FIXME: Check/add configured filter instead of objectclasses + foreach ($this->_ldapparams['objectclass'] as $objectclass) { + $filter .= '(objectClass=' . $objectclass . ')'; + } + $filter .= ')'; + + Horde::logMessage($filter, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $res = ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error in LDAP search: %s"), ldap_error($this->LDAP))); + } + + $res = ldap_get_entries($this->_ldap, $res); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error in LDAP search: %s"), ldap_error($this->LDAP))); + } + + $users[$domain] = array(); + $i = 0; + // Can't use foreach because of the array format returned by LDAP driver + while ($user = @$res[$i]) { + $users[$domain][$i]['id'] = $user['dn']; + $users[$domain][$i]['address'] = $user[$this->_getAttrByField('address')][0]; + $users[$domain][$i]['type'] = 'user'; + $users[$domain][$i]['user_name'] = + $user[$this->_getAttrByField('user_name')][0]; + // We likely don't have read permission on the crypted password so + // avoid any warnings/errors about missing array elements + if (isset($user[$this->_getAttrByField('user_crypt')])) { + $users[$domain][$i]['user_crypt'] = + $user[$this->_getAttrByField('user_crypt')][0]; + } else { + $users[$domain][$i]['user_crypt'] = ''; + } + $users[$domain][$i]['user_full_name'] = + $user[$this->_getAttrByField('user_full_name')][0]; + // Mute assignment errors on the following optional fields + // These may not be present if the mail is only forwarded + $users[$domain][$i]['user_uid'] = + @$user[$this->_getAttrByField('user_uid')][0]; + $users[$domain][$i]['user_gid'] = + @$user[$this->_getAttrByField('user_gid')][0]; + $users[$domain][$i]['user_home_dir'] = + @$user[$this->_getAttrByField('user_home_dir')][0]; + $users[$domain][$i]['user_mail_dir'] = + @$user[$this->_getAttrByField('user_mail_dir')][0]; + $users[$domain][$i]['user_mail_quota_bytes'] = + @$user[$this->_getAttrByField('user_mail_quota_bytes')][0]; + $users[$domain][$i]['user_mail_quota_count'] = + @$user[$this->_getAttrByField('user_mail_quota_count')][0]; + + // If accountStatus is blank it's the same as active + if (!isset($user[$this->_getAttrByField('user_enabled')][0]) || + ($user[$this->_getAttrByField('user_enabled')][0] == 'active')) { + $users[$domain][$i]['user_enabled'] = 'active'; + } else { + // accountStatus can also be: + // noaccess (receives but cannot pick up mail) + // disabled (bounce incoming and deny pickup) + // deleted (bounce incoming but allow pickup) + $users[$domain][$i]['user_enabled'] = + $user[$this->_getAttrByField('user_enabled')][0]; + } + + $i++; + } + + return $users[$domain]; + } + + function _getFields() + { + // LDAP attributes are always returned lower case! + static $fields = array( + 'address' => 'mail', + 'user_name' => 'uid', + 'user_crypt' => 'userpassword', + 'user_full_name' => 'cn', + 'user_uid' => 'qmailuid', + 'user_gid' => 'qmailgid', + 'user_home_dir' => 'homedirectory', + 'user_mail_dir' => 'mailmessagestore', + 'user_mail_quota_bytes' => 'mailquotasize', + 'user_mail_quota_count' => 'mailquotacount', + 'user_enabled' => 'accountstatus', + ); + + return $fields; + + } + + function _getAttrByField($field) { + $fields = $this->_getFields(); + return $fields[$field]; + } + + function _getFieldByAttr($attr) { + $attrs = array_flip($this->_getFields()); + return $attrs[$attr]; + } + + /** + * Returns available email address aliases. This method should not be + * called directly but rather by way of getAddresses(). + * + * @access private + * + * @param string $target If passed a domain then return all alias emails + * for the domain, otherwise if passed a user name + * return all virtual emails for that user. + * + * @return array The used email aliases + */ + function _getAliases($target = null) + { + // FIXME: Add static cache + + $filter = '(&'; // Begin filter (cumulative AND) + foreach ($this->_ldapparams['objectclass'] as $objectclass) { + // Add each objectClass from parameters + $filter .= '(objectClass=' . $objectclass . ')'; + } + // FIXME: Add preconfigured filter from $this->_ldapparams + + // Check if filtering only for domain. + if (($pos = strpos($target, '@')) === false && !empty($target)) { + $filter .= '(mailAlternateAddress=*@' . $target . ')'; + // Otherwise filter for all aliases + } else { + $filter .= '(mailAlternateAddress=*)'; + // Restrict the results to $target + if (!empty($target)) { + $filter .= '(mail=' . $target . ')'; // Add user's email + } + } + $filter .= ')'; // End filter + + Horde::logMessage($filter, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"), + @ldap_error($this->_ldap))); + } + + $res = @ldap_get_entries($this->_ldap, $res); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap))); + } + + $aliases = array(); + // Can't use foreach because of the array format returned by LDAP driver + $i = 0; // Virtual address index + $e = 0; // Entry counter + while ($entry = @$res[$e]) { + // If accountStatus is blank it's the same as active + if (!isset($entry[$this->_getAttrByField('user_enabled')][0]) || + ($entry[$this->_getAttrByField('user_enabled')][0] == 'active')) { + $curstatus = 'active'; + } else { + // accountStatus can also be: + // noaccess (receives but cannot pick up mail) + // disabled (bounce incoming and deny pickup) + // deleted (bounce incoming but allow pickup) + $curstatus = $entry[$this->_getAttrByField('user_enabled')][0]; + } + $a = 0; // Attribute counter + while ($mail = @$entry['mailalternateaddress'][$a]) { + $aliases[$i]['id'] = $mail; + $aliases[$i]['type'] = 'alias'; + $aliases[$i]['user_name'] = $mail; + $aliases[$i]['user_full_name'] = sprintf(_("Alias for %s"), $entry['mail'][0]); + $aliases[$i]['destination'] = $entry['mail'][0]; + $aliases[$i]['user_enabled'] = $curstatus; + $a++; + $i++; + } + $e++; + } + + return $aliases; + } + + /** + * Returns all available groups and forwards unless otherwise specified. + * If a domain name is passed then limit the results to groups or forwards + * in that domain. This method should not be called directly, but rather by + * way of getAddresses() + * + * @access private + * + * @param string $acquire The default behavior is to acquire both + * groups and forwards; a value of 'group' + * will return only groups and a value of + * 'forward' will return only forwards. + * @param string $domain The name of the domain from which to fetch + * + * @return array The available groups and forwards with details + */ + function _getGroupsAndForwards($acquire = null, $domain = null) + { + // Cache + static $grpfwds; + // TODO ? + /* + if (is_null($domain) && isset($grpfwds['_all'])) { + return $grpfwds['_all']; + } + if (!is_null($domain) && isset($grpfwds[$domain])) { + return $grpfwds[$domain]; + } + */ + $filter = '(&'; // Begin filter (cumulative AND) + foreach ($this->_ldapparams['objectclass'] as $objectclass) { + // Add each objectClass from parameters + $filter .= '(objectClass=' . $objectclass . ')'; + } + // FIXME: Add preconfigured filter from $this->_ldapparams + + // Only return results which have a forward configured + $filter .= '(mailForwardingAddress=*)'; + + if (!empty($domain)) { + $filter .= '(|'; // mail or mailAlternateAddress + $filter .= '(mail=*@' . $domain . ')'; + $filter .= '(mailAlternateAddress=*@' . $domain . ')'; + $filter .= ')'; // end mail or mailAlternateAddress + } else { + $domain = '_all'; + } + $filter .= ')'; // End filter + Horde::logMessage($filter, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"), + @ldap_error($this->_ldap))); + } + + $res = @ldap_get_entries($this->_ldap, $res); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap))); + } + + $grpfwds[$domain] = array(); + // Can't use foreach because of the array format returned by LDAP driver + $i = 0; // Address index + $e = 0; // Entry counter + + while ($entry = @$res[$e]) { + $targets = array(); + $a = 0; // Attribute counter + while ($attr = @$res[$e]['mailforwardingaddress'][$a]) { + $targets[] = $attr; + $a++; + } + $type = $entry['mailforwardingaddress']["count"]; + if($type > 1) { + $type = 'group'; + } else { + $type = 'forward'; + } + if(($acquire == 'all') || ($type == $acquire)) { + $grpfwds[$domain][$i] = array( + 'id' => $entry['dn'], + 'type' => $type, + 'address' => $entry[$this->_getAttrByField('address')][0], + 'targets' => $targets, + 'user_name' => $entry[$this->_getAttrByField('user_name')][0], + 'user_full_name' => @$entry[$this->_getAttrByField('user_name')][0], + ); + // If accountStatus is blank it's the same as active + if (!isset($entry[$this->_getAttrByField('user_enabled')][0]) || + ($entry[$this->_getAttrByField('user_enabled')][0] == 'active')) { + $grpfwds[$domain][$i]['user_enabled'] = 'active'; + } else { + // accountStatus can also be: + // noaccess (receives but cannot pick up mail) + // disabled (bounce incoming and deny pickup) + // deleted (bounce incoming but allow pickup) + $grpfwds[$domain][$i]['user_enabled'] = + $entry[$this->_getAttrByField('user_enabled')][0]; + } + } else { + $e++; + continue; + } + $e++; + $i++; + } + return $grpfwds[$domain]; + } + + /** + * Returns information for an email alias + * + * @param string $id The email alias id for which to return information. + * + * @return array The virtual email information. + */ + function getAddressInfo($address, $type = 'all') + { + if ($type != 'alias') { + return parent::getAddressInfo($address, $type); + } else { + // FIXME: Which is faster? A linear array search or an LDAP search? + // I think LDAP in this case because we can't assume the domain. + $filter = '(&'; // Begin filter (cumulative AND) + foreach ($this->_ldapparams['objectclass'] as $objectclass) { + // Add each objectClass from parameters + $filter .= '(objectClass=' . $objectclass . ')'; + } + $filter .= '(mailAlternateAddress= ' . $address . ')'; + $filter .= ')'; // End filter + Horde::logMessage($filter, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"), + @ldap_error($this->_ldap))); + } + $res = @ldap_get_entries($this->_ldap, $res); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap))); + } + + if ($res['count'] !== 1) { + return PEAR::raiseError(_("More than one DN returned for this alias. Please contact an administrator to resolve this error.")); + } + + return array( + 'id' => $res[0]['dn'], + 'address' => $address, + 'destination' => $res[0]['mail'][0], + ); + } + } + + /** + * Returns the current number of set up users for a domain. + * + * @param string $domain_name The name of the domain for which to + * get the current number of users. + * + * @return integer The current number of users. + */ + function getDomainNumUsers($domain_name) + { + return count($this->_getUsers($domain_name)); + } + + /** + * Saves a domain to the backend. + * + * @param array $info The domain information to save to the backend. + * + * @return mixed True on success or PEAR error otherwise. + */ + function _saveDomain(&$info) + { + // We store the records within Horde's configured SQL database for + // Vilma because LDAP has no mechanism for tracking domains + // that are valid for this system. + $values = array($info['name'], $info['transport'], + (int)$info['max_users'], (int)$info['quota']); + + if (empty($info['domain_id'])) { + $nextid = $this->_db->nextId('vilma_domains'); + $sql = 'INSERT INTO vilma_domains (domain_id, domain_name, ' . + 'domain_transport, domain_max_users, domain_quota) VALUES ' . + '(?, ?, ?, ?, ?)'; + array_unshift($values, $nextid); + } else { + $sql = 'UPDATE vilma_domains SET domain_name=?, ' . + 'domain_transport=?, domain_max_users=?, domain_quota=? ' . + 'WHERE domain_id=?'; + array_push($values, $info['domain_id']); + } + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->query($sql, $values); + } + + /** + * Deletes a given domain. + * + * @param string $domain_id The id of the domain to delete. + * + * @return mixed True on success or PEAR error otherwise. + */ + function _deleteDomain($domain_id) + { + $domain_record = $this->getDomain($domain_id); + if (is_a($domain_record, 'PEAR_Error')) { + return $domain_record; + } + + $domain_name = $domain_record['domain_name']; + + // FIXME: Add logic to remove all users, aliases, and grpfwds for this + // domain + + /* Finally delete the domain. */ + $sql = 'DELETE FROM vilma_domains WHERE domain_id=?'; + $values = array((int)$domain_id); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->query($sql, $values); + } + + /** + * Searchs for a given email account. + * + * @param string $email_id The id of the account to be searched for. + * + * @return Array of data for given email account on success or no + * information found; and for an error a PEAR::Error otherwise. + */ + function searchForAliases($email_id) { + // Get the user's DN + $filter = '(&'; // Begin filter (cumulative AND) + foreach ($this->_ldapparams['objectclass'] as $objectclass) { + // Add each objectClass from parameters + $filter .= '(objectClass=' . $objectclass . ')'; + } + /* + // Check if filtering only for domain. + if (($pos = strpos($target, '@')) === false && !empty($email_id)) { + $filter .= '(mailAlternateAddress=*@' . $email_id . ')'; + // Otherwise filter for all aliases + } else { + $filter .= '(mailAlternateAddress=*)'; + // Restrict the results to $target + if (!empty($email_id)) { + $filter .= '(mail=' . $email_id . ')'; // Add user's email + } + } + */ + $filter .= '(mailAlternateAddress=' . $email_id . ')'; + $filter .= ')'; // End filter + + //echo $filter; + Horde::logMessage($filter, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"), + @ldap_error($this->_ldap))); + } + $res = @ldap_get_entries($this->_ldap, $res); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap))); + } + + return $res; + } + + /** + * Searchs for a given email account. + * + * @param string $email_id The id of the account to be searched for. + * + * @return Array of data for given email account on success or no + * information found; and for an error a PEAR::Error otherwise. + */ + function searchForUser($email_id) + { + // Get the user's DN + $filter = '(&'; + foreach ($this->_ldapparams['objectclass'] as $objectclass) { + // Add each objectClass from parameters + $filter .= '(objectclass=' . $objectclass . ')'; + } + $filter .= '(mail=' . $email_id . '))'; + + Horde::logMessage($filter, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"), + @ldap_error($this->_ldap))); + } + $res = @ldap_get_entries($this->_ldap, $res); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap))); + } + + if ($res['count'] === 0) { + return PEAR::raiseError(_("Unable to acquire handle on DN. Aborting delete operation.")); + } else if($res['count'] !== 1) { + return PEAR::raiseError(_("More than one DN returned. Aborting delete operation.")); + } + return $res; + } + + /** + * Deletes a given email account. + * + * @param string $email_id The id of the account to delete (not an alias) + * + * @return mixed True on success or PEAR::Error otherwise. + */ + function deleteUser($email_id) + { + // Get the user's DN + $filter = '(&'; + foreach ($this->_ldapparams['objectclass'] as $objectclass) { + // Add each objectClass from parameters + $filter .= '(objectclass=' . $objectclass . ')'; + } + $filter .= '(mail=' . $email_id . ')'; + //echo $email_id . '
'; + $filter .= ')'; + Horde::logMessage($filter, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"), + @ldap_error($this->_ldap))); + } + $res = @ldap_get_entries($this->_ldap, $res); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap))); + } + + if ($res['count'] === 0) { + return PEAR::raiseError(_("Unable to acquire handle on DN. Aborting delete operation.")); + } else if($res['count'] !== 1) { + return PEAR::raiseError(_("More than one DN returned. Aborting delete operation.")); + } + // We now have one unique DN to delete. + $res = @ldap_delete($this->_ldap, $res[0]['dn']); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error deleting account from LDAP: %s"), @ldap_error($this->_ldap))); + } + + return true; + } + + /** + * Modifies alias data on the backend. + * + * @param mixed $info The alias, or an array containing the alias and supporting data. + * @param string $mode The operation requested: add, update, delete. + * + * @return mixed True on success or PEAR error otherwise. + */ + function _savealias($info,$mode = null) + { + if ($mode == 'delete') { + $address = $info; + + $user_info = $this->searchForAliases($address); + $aliasesList = $user_info[0]['mailalternateaddress']; + if (is_a($user_info, 'PEAR_Error') || ($res['count'] === 0) ) { + return PEAR::raiseError(_("Error reading address information from backend.")); + } + $addrinfo = $this->getAddressInfo($address); + if (is_a($addrinfo, 'PEAR_Error')) { + return $addrinfo; + } + $type = $addrinfo['type']; + $addrinfo = $this->getAddressInfo($address,$type); + if (is_a($addrinfo, 'PEAR_Error')) { + return $addrinfo; + } + $objectClassData = null; + if(isset($user_info[0]['objectclass'])) { + $objectClassData = $user_info[0]['objectclass']; + } + if ($this->_ldap) { + // bind with appropriate dn to give update access + $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'], + $this->_ldapparams['bindpw']); + if (!$res) { + return PEAR::raiseError(_("Unable to bind to the LDAP server. Check authentication credentials.")); + } + $tmp = array(); + $key = null; + foreach($aliasesList as $key => $val) { + if($val != $address) { + array_push($tmp,$val); + } + } + $entry["mailalternateaddress"] = $tmp; + + $rdn = 'mail=' . $addrinfo['destination']; + $dn = $rdn . ',' . $this->_ldapparams['basedn']; + $res = @ldap_modify($this->_ldap, $dn, $entry); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap))); + } else { + return TRUE; + } + } + } + + return PEAR::raiseError(_("Unable to save user information.")); + } + + function _saveUser(&$info) + { + if ($info['mode'] == 'edit') { + $address = $info['address']; + if(!isset($address) || empty($address)) { + $user_name = $info['user_name']; + $domain = $info['domain']; + if(!(!isset($user_name) || empty($user_name)) && !(!isset($user_name) || empty($user_name))) { + $address = $info['user_name'] . $info['domain']; + } else { + return PEAR::raiseError(_("Unable to acquire handle on address.")); + } + } + $addrinfo = $this->getAddressInfo($address); + if (is_a($addrinfo, 'PEAR_Error')) { + return $addrinfo; + } + $type = $addrinfo['type']; + if($type == 'user') { + //continue, this is a user. + } else { + //return PEAR::raiseError(_("Unable to save account of type " . $type)); + } + + $user_info = $this->searchForUser($address); + if (is_a($user_info, 'PEAR_Error') || ($res['count'] === 0) ) { + return PEAR::raiseError(_("Error reading address information from backend.")); + } + + $objectClassData = null; + if(isset($user_info[0]['objectclass'])) { + $objectClassData = $user_info[0]['objectclass']; + } + + unset($info['mode']); // Don't want to save this to LDAP + // Special case for the password: If it was provided, it needs + // to be crypted. Otherwise, ignore it. + if (isset($info['password'])) { + if (!empty($user['password'])) { + // FIXME: Allow choice of hash + $info['user_password'] = Horde_Auth::getCryptedPassowrd($info['password'], '', 'ssha', true); + } + unset($info['password']); + } + + $tmp['dn'] = $addrinfo['id']; + foreach ($info as $key => $val) { + $attr = $this->_getAttrByField($key); + $tmp[$attr] = $val; + } + + if ($this->_ldap) { + // bind with appropriate dn to give update access + $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'], + $this->_ldapparams['bindpw']); + if (!$res) { + return PEAR::raiseError(_("Unable to bind to the LDAP server. Check authentication credentials.")); + } + + // prepare data + $entry['cn'] = $info['user_full_name']; + // sn is not used operationally but we make an effort to be + // something sensical. No guarantees, though. + $entry['sn'] = array_pop(explode(' ', $info['user_full_name'])); +// The next two lines were reversed: which is right? + $entry['mail'] = $info['user_name'] . $info['domain']; + // $tmp['mail']; + $entry['uid'] = $entry['mail']; + $entry['homeDirectory'] = '/srv/vhost/mail/' . $info['domain'] .'/' . $info['user_name']; + if(($type != 'group') && ($type != 'forward')) { + $entry["qmailUID"] = 8; + $entry["qmailGID"] = 8; + } + $entry["accountstatus"] = $info["user_enabled"]; + if(isset($info['password']) && !empty($info['password'])) { + // FIXME: Allow choice of hash + $entry["userPassword"] = Horde_Auth::getCryptedPassword($info['password'], '', 'ssha', true); + } + if(isset($objectClassData)) { + array_shift($objectClassData); + $entry['objectclass'] = $objectClassData; + } else { + $entry['objectclass'] = array(); + $entry['objectclass'][] = 'top'; + $entry['objectclass'][] = 'person'; + $entry['objectclass'][] = 'organizationalPerson'; + $entry['objectclass'][] = 'inetOrgPerson'; + $entry['objectclass'][] = 'hordePerson'; + $entry['objectclass'][] = 'qmailUser'; + } + + // Stir in any site-local custom LDAP attributes + $entry = Horde::callHook('_vilma_hook_getldapattrs', + array($entry), 'vilma'); + + $rdn = 'mail=' . $entry['mail']; + $dn = $rdn . ',' . $this->_ldapparams['basedn']; + $res = @ldap_modify($this->_ldap, $dn, $entry); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap))); + } else { + return TRUE; + } + } + } else if($info['mode'] == 'new') { + if ($this->_ldap) { + // bind with appropriate dn to give update access + $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'], + $this->_ldapparams['bindpw']); + if (!$res) { + return PEAR::raiseError(_("Unable to bind to the LDAP server. Check authentication credentials.")); + } + + // prepare data + $entry['cn'] = $info['user_full_name']; + // sn is not used operationally but we make an effort to be + // something sensical. No guarantees, though. + $entry['sn'] = array_pop(explode(' ', $info['user_full_name'])); + $entry['mail'] = $info['user_name'] . '@' . $info['domain']; + // uid must match mail or SMTP auth fails + $entry['uid'] = $entry['mail']; + $entry['homeDirectory'] = '/srv/vhost/mail/' . $info['domain'] .'/' . $info['user_name']; + $entry['qmailUID'] = 8; + $entry['qmailGID'] = 8; + $entry['objectclass'] = array(); + $entry['objectclass'][] = 'top'; + $entry['objectclass'][] = 'person'; + $entry['objectclass'][] = 'organizationalPerson'; + $entry['objectclass'][] = 'inetOrgPerson'; + $entry['objectclass'][] = 'hordePerson'; + $entry['objectclass'][] = 'qmailUser'; + $entry["accountstatus"] = $info["user_enabled"]; + // FIXME: Allow choice of hash + $entry["userPassword"] = Horde_Auth::getCryptedPassword($info['password'], '', 'ssha', true); + + // Stir in any site-local custom LDAP attributes + $entry = Horde::callHook('_vilma_hook_getldapattrs', + array($entry), 'vilma'); + + $rdn = 'mail=' . $entry['mail']; + $dn = $rdn . ',' . $this->_ldapparams['basedn']; + $res = @ldap_add($this->_ldap, $dn, $entry); + if ($res === false) { + return PEAR::raiseError(sprintf(_("Error adding account to LDAP: %s"), @ldap_error($this->_ldap))); + } else { + return TRUE; + } + } else { + return PEAR::raiseError(_("Unable to connect to LDAP server")); + } + } + + return PEAR::raiseError(_("Unable to save user information.")); + } + + /** + * Deletes a virtual email. + * + * @param integer $virtual_id The id of the virtual email to delete. + */ + function deleteVirtual($virtual_id) + { + die("deleteVirtual()"); + } + + function getUserFormAttributes() + { + $attrs = array(); + $attrs[] = array( + 'label' => _("Account Status"), + 'name' => 'user_enabled', + 'type' => 'enum', + 'required' => true, + 'readonly' => false, + 'description' => null, + 'params' => array( + array( + 'active' => _("Account is active"), + 'noaccess' => _("Disable Delivery Only"), + 'disabled' => _("Bounce Incoming Only"), + 'deleted' => _("Account is disabled"), + ), + ), + 'default' => 'active', + ); + + return $attrs; + } + + function _connect() + { + if (!is_null($this->_ldap)) { + return true; + } + + Horde::assertDriverConfig($this->_ldapparams, 'storage', + array('ldaphost', 'basedn', 'binddn', 'dn')); + + if (!isset($this->_ldapparams['bindpw'])) { + $this->_ldapparams['bindpw'] = ''; + } + + $port = (isset($this->_ldapparams['port'])) ? + $this->_ldapparams['port'] : 389; + + $this->_ldap = ldap_connect($this->_ldapparams['ldaphost'], $port); + if (!$this->_ldap) { + Horde::fatal("Unable to connect to LDAP server $hostname on $port", + __FILE__, __LINE__); + } + $res = ldap_set_option($this->_ldap, LDAP_OPT_PROTOCOL_VERSION, + $this->_ldapparams['version']); + if (!$res) { + return PEAR::raiseError(_("Unable to set LDAP protocol version")); + } + $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'], + $this->_ldapparams['bindpw']); + if (!$res) { + return PEAR::raiseError(_("Unable to bind to the LDAP server. Check authentication credentials.")); + } + + } + + /** + * Initialise this backend, connect to the SQL database. + * + * @return mixed True on success or PEAR error otherwise. + */ + function _dbinit() + { + global $registry; + + Horde::assertDriverConfig($this->_sqlparams, 'storage', + array('phptype')); + + if (!isset($this->_sqlparams['database'])) { + $this->_sqlparams['database'] = ''; + } + if (!isset($this->_sqlparams['username'])) { + $this->_sqlparams['username'] = ''; + } + if (!isset($this->_sqlparams['hostspec'])) { + $this->_sqlparams['hostspec'] = ''; + } + + /* Connect to the SQL server using the supplied parameters. */ + require_once 'DB.php'; + $this->_db = &DB::connect($this->_sqlparams, + array('persistent' => !empty($this->_sqlparams['persistent']))); + if (is_a($this->_db, 'PEAR_Error')) { + return $this->_db; + } + + // Set DB portability options. + switch ($this->_db->phptype) { + case 'mssql': + $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM); + break; + + default: + $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS); + } + } +} diff --git a/vilma/lib/Driver/sql.php b/vilma/lib/Driver/sql.php new file mode 100644 index 000000000..e4468d014 --- /dev/null +++ b/vilma/lib/Driver/sql.php @@ -0,0 +1,640 @@ + + * @package Vilma + */ +class Vilma_Driver_sql extends Vilma_Driver { + + /** + * @var DB + */ + var $_db; + + function Vilma_Driver_sql($params) + { + parent::Vilma_Driver($params); + $this->initialise(); + } + + /** + * Construct an SQL WHERE fragment to filter domains by domain key. + * + * @access private + * + * @param string $join Keyword to join expression to rest of SQL statement + * (e.g. 'WHERE' or 'AND'). Default: 'WHERE'. + * + * @return array An SQL fragment and a list of values suitable for + * binding. + */ + function _getDomainKeyFilter($join = 'WHERE') + { + if (empty($this->_params['tables']['domainkey'])) { + return array('', array()); + } + + return array(' ' . $join . ' domain_key = ?', + array($this->_params['tables']['domainkey'])); + } + + /** + * Construct an SQL WHERE fragment to filter users by domain key. + * + * @access private + * + * @param string $join Keyword to join expression to rest of SQL statement + * (e.g. 'WHERE' or 'AND'). Default: 'WHERE'. + * + * @return array An SQL fragment and a list of values suitable for + * binding. + */ + function _getUserKeyFilter($join = 'WHERE') + { + if (empty($this->_params['tables']['domainkey'])) { + return array('', array()); + } + $binds = $this->_getDomainKeyFilter('AND'); + + return array(' ' . $join . ' EXISTS (SELECT domain_name' . + ' FROM ' . $this->_params['tables']['domains'] . + ' WHERE ' . $this->_getTableField('users', 'user_name') . + ' LIKE ? || ' . $this->_getTableField('domains', 'domain_name') . + ' ' . $binds[0] . ' )', + array_unshift($binds[1], '%@')); + } + + /** + * Construct an SQL WHERE fragment to filter virtuals by domain key. + * + * @access private + * + * @param string $join Keyword to join expression to rest of SQL statement + * (e.g. 'WHERE' or 'AND'). Default: 'WHERE'. + * + * @return string An SQL fragment. + */ + function _getVirtualKeyFilter($join = 'WHERE') + { + if (empty($this->_params['tables']['domainkey'])) { + return array('', array()); + } + $binds = $this->_getDomainKeyFilter('AND'); + + return array(' ' . $join . ' EXISTS (SELECT domain_name' . + ' FROM ' . $this->_params['tables']['domains'] . + ' WHERE ' . $this->_getTableField('virtuals', 'virtual_email') . + ' LIKE ? || ' . $this->_getTableField('domains', 'domain_name') . + ' ' . $binds[0] . ' )', + array_unshift($binds[1], '%@')); + } + + /** + * Gets the list of fields from specific table for sql statement. + * + * @return string + */ + function _getTableFields($table) + { + if (empty($this->_params['tables'][$table . '_fields'])){ + return '*'; + } + + $domainsFields = $this->_params['tables'][$table . '_fields']; + foreach ($domainsFields as $defaultName => $customName) { + $fields[] = $customName . ' as ' . $defaultName; + } + return implode(', ', $fields); + } + + /** + * Gets the real name of the field from specific table for sql statement. + * + * @return string + */ + function _getTableField($table, $field) + { + if (empty($this->_params['tables'][$table . '_fields'])) { + return $field; + } else { + return $this->_params['tables'][$table . '_fields'][$field]; + } + } + + /** + * + * + * @return array + */ + function _prepareRecord($table, $record) + { + if (empty($this->_params['tables'][$table . '_fields'])){ + return $record; + } + + $domainsFields = $this->_params['tables'][$table . '_fields']; + $newRecord = array(); + foreach ($record as $defaultName => $value) { + $newRecord[$domainsFields[$defaultName]] = $record[$defaultName]; + } + return $newRecord; + } + + /** + * Gets the list of domains from the backend. + * + * @return array All the domains and their data in an array. + */ + function getDomains() + { + $binds = $this->_getDomainKeyFilter(); + $sql = 'SELECT '. $this->_getTableFields('domains') . ' FROM ' . $this->_params['tables']['domains'] . + $binds[0] . ' ORDER BY domain_name'; + $values = $binds[1]; + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); + } + + /** + * Gets the specified domain information from the backend. + * + * @param integer $domain_id The id of the domain to fetch. + * + * @return array The domain's information in an array. + */ + function getDomain($domain_id) + { + $binds = $this->_getDomainKeyFilter('AND'); + $sql = 'SELECT '. $this->_getTableFields('domains') . ' FROM ' . $this->_params['tables']['domains'] . + ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?' . $binds[0]; + array_unshift($binds[1], (int)$domain_id); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC); + } + + /** + * Given a domain name returns the information from the backend. + * + * @param string $name The name of the domain to fetch. + * + * @return array The domain's information in an array. + */ + function getDomainByName($domain_name) + { + $binds = $this->_getDomainKeyFilter('AND'); + $sql = 'SELECT '. $this->_getTableFields('domains') . ' FROM ' . $this->_params['tables']['domains'] . + ' WHERE ' . $this->_getTableField('domains', 'domain_name') . ' = ?' . $binds[0]; + array_unshift($binds[1], $domain_name); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC); + } + + /** + * Returns all available users, if a domain name is passed then limit the + * list of users only to those users. + * + * @param string $domain The name of the domain for which to fetch the + * users. + * + * @return array The available users and their stored information. + */ + function getUsers($domain = null) + { + /* Put together the SQL statement. */ + if (is_null($domain)) { + /* Fetch all users. */ + $binds = $this->_getUserKeyFilter(); + $sql = 'SELECT '. $this->_getTableFields('users') . ' FROM ' . $this->_params['tables']['users'] . + $binds[0]; + $values = $binds[1]; + } else { + /* Fetch only users for a domain. */ + $binds = $this->_getUserKeyFilter('AND'); + $sql = 'SELECT '. $this->_getTableFields('users') . ' FROM ' . $this->_params['tables']['users'] . + ' WHERE ' . $this->_getTableField('users', 'user_name') . ' LIKE ?' . $binds[0] . + ' ORDER BY user_name'; + array_unshift($binds[1], '%@' . $domain); + $values = $binds[1]; + } + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); + } + + /** + * Returns the user information for a given user id. + * + * @param integer $user_id The id of the user for which to fetch + * information. + * + * @return array The user information. + */ + function getUser($user_id) + { + $binds = $this->_getUserKeyFilter('AND'); + $sql = 'SELECT '. $this->_getTableFields('users') . ' FROM ' . $this->_params['tables']['users'] . + ' WHERE ' . $this->_getTableField('users', 'user_id') . ' = ?' . $binds[0]; + array_unshift($binds[1], (int)$user_id); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC); + } + + /** + * Returns available virtual emails. + * + * @param string $filter If passed a domain then return all virtual emails + * for the domain, otherwise if passed a user name + * return all virtual emails for that user. + * + * @return array The available virtual emails. + */ + function getVirtuals($filter) + { + /* Check if filtering only for domain. */ + if (($pos = strpos($filter, '@')) === false) { + $where = $this->_getTableField('virtuals', 'virtual_email') . ' LIKE ?'; + $values = array('%@' . $filter); + } else { + $where = $this->_getTableField('virtuals', 'virtual_destination') . ' = ?'; + $values = array($filter); + } + + $binds = $this->_getVirtualKeyFilter('AND'); + $sql = 'SELECT '. $this->_getTableFields('virtuals') . ' FROM ' . $this->_params['tables']['virtuals'] . + ' WHERE ' . $where . $binds[0] . + ' ORDER BY virtual_destination, virtual_email'; + $values = array_merge($values, $binds[1]); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC); + } + + /** + * Returns information for a virtual id. + * + * @param integer $virtual_id The virtual id for which to return + * information. + * + * @return array The virtual email information. + */ + function getVirtual($virtual_id) + { + $binds = $this->_getVirtualKeyFilter('AND'); + $sql = 'SELECT '. $this->_getTableFields('virtuals') . ' FROM ' . $this->_params['tables']['virtuals'] . + ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?' . $binds[0]; + array_unshift($binds[1], (int)$virtual_id); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $virtual = $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC); + $virtual['stripped_email'] = Vilma::stripUser($virtual['virtual_email']); + + return $virtual; + } + + /** + * Returns the current number of set up users for a domain. + * + * @param string $domain_name The name of the domain for which to + * get the current number of users. + * + * @return integer The current number of users. + */ + function getDomainNumUsers($domain_name) + { + $binds = $this->_getUserKeyFilter('AND'); + $sql = 'SELECT count(' . $this->_getTableField('users', 'user_name') . ')' . + ' FROM ' . $this->_params['tables']['users'] . + ' WHERE ' . $this->_getTableField('users', 'user_name') . ' LIKE ?' . $binds[0]; + array_unshift($binds[1], '%@' . $domain_name); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->getOne($sql, $binds[1]); + } + + /** + * Saves a domain to the backend. + * + * @param array $info The domain information to save to the backend. + * + * @return mixed True on success or PEAR error otherwise. + */ + function _saveDomain($info) + { + require_once 'Horde/SQL.php'; + + $record = array('domain_name' => $info['name'], + 'domain_transport' => $info['transport'], + 'domain_max_users' => (int)$info['max_users'], + 'domain_quota' => (int)$info['quota']); + + if (empty($info['domain_id'])) { + $record['domain_id'] = $this->_db->nextId($this->_params['tables']['domains']); + if (!empty($this->_params['tables']['domainkey'])) { + $record['domain_key'] = $this->_params['tables']['domainkey']; + } + + $sql = 'INSERT INTO ' . $this->_params['tables']['domains'] . + ' ' . Horde_SQL::insertValues($this->_db, $this->_prepareRecord('domains', $record)); + $values = array(); + } else { + $binds = $this->_getDomainKeyFilter('AND'); + $sql = 'UPDATE ' . $this->_params['tables']['domains'] . + ' SET ' . Horde_SQL::updateValues($this->_db, $this->_prepareRecord('domains', $record)) . + ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?' . $binds[0]; + array_unshift($binds[1], $info['domain_id']); + $values = $binds[1]; + } + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->query($sql, $values); + } + + /** + * Deletes a given domain. + * + * @param integer $domain_id The id of the domain to delete. + * + * @return mixed True on success or PEAR error otherwise. + */ + function _deleteDomain($domain_id) + { + $domain_record = $this->getDomain($domain_id); + if (is_a($domain_record, 'PEAR_Error')) { + return $domain_record; + } + + $domain_name = $domain_record['domain_name']; + + /* Delete all virtual emails for this domain. */ + $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals'] . + ' WHERE ' . $this->_getTableField('virtuals', 'virtual_email') . ' LIKE ?'; + $values = array('%@' . $domain_name); + $delete = $this->_db->query($sql, $values); + if (is_a($delete, 'PEAR_Error')) { + return $delete; + } + + /* Delete all users for this domain. */ + $sql = 'DELETE FROM ' . $this->_params['tables']['users'] . + ' WHERE ' . $this->_getTableField('users', 'user_name') . ' LIKE ?'; + $values = array('%@' . $domain_name); + $delete = $this->_db->query($sql, $values); + if (is_a($delete, 'PEAR_Error')) { + return $delete; + } + + /* Finally delete the domain. */ + $sql = 'DELETE FROM ' . $this->_params['tables']['domains'] . + ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?'; + $values = array((int)$domain_id); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->query($sql, $values); + } + + /** + * Saves a user to the backend. + * + * @param array $info The user information to save. + * + * @return array The user information. + */ + function _saveUser($info) + { + global $conf; + + require_once 'Horde/SQL.php'; + + /* Access check (for domainkey). */ + $res = $this->getDomainByName(Vilma::stripDomain($info['user_name'])); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + $mailboxes = &Vilma::getMailboxDriver(); + if (is_a($mailboxes, 'PEAR_Error')) { + return $mailboxes; + } + + if (empty($info['user_id'])) { + $info['user_id'] = $this->_db->nextId($this->_params['tables']['users']); + $create = true; + } else { + $create = false; + } + + // Slightly hackish. + $mail_dir_base = isset($mailboxes->_params['mail_dir_base']) ? + $mailboxes->_params['mail_dir_base'] : '?'; + + $tuple = array('user_id' => (int)$info['user_id'], + 'user_name' => $info['user_name'], + 'user_full_name' => $info['user_full_name'], + 'user_home_dir' => $mail_dir_base, + 'user_mail_dir' => Vilma::stripDomain($info['user_name']) . '/' . Vilma::stripUser($info['user_name']) . '/', + 'user_mail_quota' => $this->getDomainQuota(Vilma::stripDomain($info['user_name'])) * 1024 * 1024, + 'user_enabled' => (int)$info['user_enabled']); + + // UID and GID are slightly hackish (specific to maildrop driver), too + if (!isset($mailboxes->_params['uid'])) { + $tuple['user_uid'] = -1; + } else { + $tuple['user_uid'] = $mailboxes->_params['uid']; + } + if (!isset($mailboxes->_params['gid'])) { + $tuple['user_gid'] = -1; + } else { + $tuple['user_gid'] = $mailboxes->_params['gid']; + } + + if (!empty($info['password'])) { + $tuple['user_clear'] = $info['password']; + $tuple['user_crypt'] = crypt($info['password'], + substr($info['password'], 0, 2)); + } elseif ($create) { + return PEAR::raiseError(_("Password must be supplied when creating a new user.")); + } + + if ($create) { + $sql = 'INSERT INTO ' . + $this->_params['tables']['users'] . ' ' . + Horde_SQL::insertValues($this->_db, $this->_prepareRecord('users', $tuple)); + } else { + $sql = sprintf('UPDATE %s SET %s WHERE ' . $this->_getTableField('users', 'user_id') . ' = %d', + $this->_params['tables']['users'], + Horde_SQL::updateValues($this->_db, $this->_prepareRecord('users', $tuple)), + (int)$info['user_id']); + } + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $result = $this->_db->query($sql); + if (is_a($result, 'PEAR_Error')) { + Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR); + return $result; + } + + return $info; + } + + /** + * Deletes a requested user. + * + * @param integer $user_id The id of the user to delete. + * + * @return mixed True, or PEAR_Error on failure. + */ + function _deleteUser($user_id) + { + $user = $this->getUser($user_id); + if (is_a($user, 'PEAR_Error')) { + return $user; + } + + /* Delete all virtual emails for this user. */ + $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals'] . + ' WHERE ' . $this->_getTableField('virtuals', 'virtual_destination') . ' = ?'; + $values = array($user['user_name']); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $delete = $this->_db->query($sql, $values); + if (is_a($delete, 'PEAR_Error')) { + return $delete; + } + + /* Delete the actual user. */ + $sql = 'DELETE FROM ' . $this->_params['tables']['users'] . + ' WHERE ' . $this->_getTableField('users', 'user_id') . ' = ?'; + $values = array((int)$user_id); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + $result = $this->_db->query($sql, $values); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + $mailboxes = &Vilma::getMailboxDriver(); + if (is_a($mailboxes, 'PEAR_Error')) { + return $mailboxes; + } + + return $mailboxes->deleteMailbox(Vilma::stripUser($user['user_name']), + Vilma::stripDomain($user['user_name'])); + } + + /** + * Saves virtual email address to the backend. + * + * @param array $info The virtual email data. + * @param string $domain The name of the domain for this virtual email. + * + * @return mixed True on success or PEAR error otherwise. + */ + function saveVirtual(&$info, $domain) + { + /* Access check (for domainkey) */ + $res = $this->getDomainByName($domain); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + if (empty($info['virtual_id'])) { + $info['virtual_id'] = $this->_db->nextId($this->_params['tables']['virtuals']); + $sql = 'INSERT INTO ' . $this->_params['tables']['virtuals'] . + ' (' . $this->_getTableField('virtuals', 'virtual_email') . ', ' . + $this->_getTableField('virtuals', 'virtual_destination') . ', ' . + $this->_getTableField('virtuals', 'virtual_id') . ') VALUES (?, ?, ?)'; + } else { + $sql = 'UPDATE ' . $this->_params['tables']['virtuals'] . + ' SET ' . $this->_getTableField('virtuals', 'virtual_email') . ' = ?, '. + $this->_getTableField('virtuals', 'virtual_destination') . ' = ?' . + ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?'; + } + $values = array($info['stripped_email'] . '@' . $domain, + $info['virtual_destination'], + $info['virtual_id']); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->query($sql, $values); + } + + /** + * Deletes a virtual email. + * + * @param integer $virtual_id The id of the virtual email to delete. + */ + function deleteVirtual($virtual_id) + { + $binds = $this->_getVirtualKeyFilter('AND'); + $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals'] . + ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?' . $binds[0]; + array_unshift($binds[1], $virtual_id); + + Horde::logMessage($sql, __FILE__, __LINE__, PEAR_LOG_DEBUG); + return $this->_db->query($sql, $binds[1]); + } + + /** + * Initialise this backend, connect to the SQL database. + * + * @return mixed True on success or PEAR error otherwise. + */ + function initialise() + { + global $registry; + + Horde::assertDriverConfig($this->_params, 'storage', + array('phptype')); + + if (!isset($this->_params['database'])) { + $this->_params['database'] = ''; + } + if (!isset($this->_params['username'])) { + $this->_params['username'] = ''; + } + if (!isset($this->_params['hostspec'])) { + $this->_params['hostspec'] = ''; + } + + /* Use default table names if these are not set. */ + if (!isset($this->_params['tables']['domains'])) { + $this->_params['tables']['domains'] = 'vilma_domains'; + } + if (!isset($this->_params['tables']['users'])) { + $this->_params['tables']['users'] = 'vilma_users'; + } + if (!isset($this->_params['tables']['virtuals'])) { + $this->_params['tables']['virtuals'] = 'vilma_virtuals'; + } + + /* Connect to the SQL server using the supplied parameters. */ + require_once 'DB.php'; + $this->_db = &DB::connect($this->_params, + array('persistent' => !empty($this->_params['persistent']))); + if (is_a($this->_db, 'PEAR_Error')) { + return $this->_db; + } + + // Set DB portability options. + switch ($this->_db->phptype) { + case 'mssql': + $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM); + break; + + default: + $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS); + } + + return true; + } + +} diff --git a/vilma/lib/Forms/DeleteDomainForm.php b/vilma/lib/Forms/DeleteDomainForm.php new file mode 100644 index 000000000..4601cceab --- /dev/null +++ b/vilma/lib/Forms/DeleteDomainForm.php @@ -0,0 +1,31 @@ + + * + * See the enclosed file LICENSE for license information (BSD). If you did + * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE. + * + * $Horde: vilma/lib/Forms/DeleteDomainForm.php,v 1.1 2008/03/12 02:52:34 bklang Exp $ + * + * @author Ben Klang + * @package Vilma + */ +class DeleteDomainForm extends Horde_Form { + + function DeleteDomainForm(&$vars) + { + parent::Horde_Form($vars, _("Delete Domain")); + + $domain_record = $GLOBALS['vilma_driver']->getDomain($vars->get('domain_id')); + if (is_a($domain_record, 'PEAR_Error')) { + return $domain_record; + } + + $domain = $domain_record['domain_name']; + + /* Set up the form. */ + $this->setButtons(array(_("Delete"), _("Do not delete"))); + $this->addHidden('', 'domain_id', 'text', false); + $this->addVariable(sprintf(_("Delete domain \"%s\" and all associated email addresses?"), $domain), 'description', 'description', false); + } +} diff --git a/vilma/lib/Forms/EditDomainForm.php b/vilma/lib/Forms/EditDomainForm.php new file mode 100644 index 000000000..79fccba32 --- /dev/null +++ b/vilma/lib/Forms/EditDomainForm.php @@ -0,0 +1,43 @@ + + * + * See the enclosed file LICENSE for license information (BSD). If you did + * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE. + * + * $Horde: vilma/lib/Forms/EditDomainForm.php,v 1.10 2009/07/14 18:43:46 selsky Exp $ + * + * @author Ben Klang + * @package Vilma + */ + +class EditDomainForm extends Horde_Form { + + function EditDomainForm(&$vars) + { + /* Check if a form is being edited. */ + $editing = $vars->exists('domain_id'); + $domain = $_SESSION['vilma']['domain']; + parent::Horde_Form($vars, $editing ? _("Edit Domain") : _("New Domain")); + if ($editing && !$this->isSubmitted()) { + $domain = $GLOBALS['vilma_driver']->getDomain($vars->get('domain_id')); + if (is_a($domain, 'PEAR_Error')) { + return $domain; + } + $vars = new Horde_Variables($domain); + } + $vars->add('name', $domain['domain_name']); + $vars->add('transport', $domain['domain_transport']); + $vars->add('max_users', $domain['domain_max_users']); + $vars->add('quota', $domain['domain_quota']); + /* Set up the form. */ + $this->setButtons(true, true); + $this->addHidden('', 'domain_id', 'text', false); + $this->addVariable(_("Domain"), 'name', 'text', true); + require_once 'Horde/Array.php'; + $this->addVariable(_("Transport"), 'transport', 'enum', false, false, null, array(Horde_Array::valuesToKeys($GLOBALS['conf']['mta']['transports']))); + $this->addVariable(_("Max users"), 'max_users', 'int', false); + $this->addVariable(_("Quota"), 'quota', 'int', false, false, _("Value in MB")); + } + +} diff --git a/vilma/lib/Forms/EditUserForm.php b/vilma/lib/Forms/EditUserForm.php new file mode 100644 index 000000000..65792528f --- /dev/null +++ b/vilma/lib/Forms/EditUserForm.php @@ -0,0 +1,72 @@ + + * + * See the enclosed file LICENSE for license information (BSD). If you did + * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE. + * + * $Horde: vilma/lib/Forms/EditUserForm.php,v 1.6 2009/05/27 23:57:32 bklang Exp $ + * + * @author Ben Klang + * @package Vilma + */ + +class EditUserForm extends Horde_Form { + + function EditUserForm(&$vars) + { + global $vilma_driver; + + $type = $vars->get('type'); + $editing = ($vars->get('mode') == 'edit'); + if ($editing) { + if($type == 'group') { + $title = sprintf(_("Edit Group for \"%s\""), $vars->get('domain')); + } else if($type == 'forward') { + $title = sprintf(_("Edit Forward for \"%s\""), $vars->get('domain')); + } else { + $title = sprintf(_("Edit User for \"%s\""), $vars->get('domain')); + } + } else { + $title = sprintf(_("New User @%s"), $vars->get('domain')); + } + parent::Horde_Form($vars, $title); + + /* Set up the form. */ + $this->setButtons(true, true); + $this->addHidden('', 'address', 'text', false); + $this->addHidden('', 'mode', 'text', false); + $this->addHidden('', 'domain', 'text', false); + $this->addHidden('', 'id', 'text', false); + if ($editing) { + $this->addHidden('', 'user_name', 'text', false); + } + $name = "User Name"; + $type = $vars->get('type'); + if($type == 'group') { + $name = "Group Name"; + } else if($type == 'forward') { + $name = "Forward Name"; + } + $this->addVariable(_($name), 'user_name', 'text', true, $editing, _("Name must begin with an alphanumeric character, must contain only alphanumeric and '._-' characters, and must end with an alphanumeric character."), array('~^[a-zA-Z0-9]{1,1}[a-zA-Z0-9._-]*[a-zA-Z0-9]$~')); + if ($editing) { + $this->addVariable(_("Password"), 'password', 'passwordconfirm', false, false, _("Only enter a password if you wish to change this user's password")); + } else { + $this->addVariable(_("Password"), 'password', 'passwordconfirm', true); + } + $this->addVariable(_("Full Name"), 'user_full_name', 'text', true); + $attrs = $vilma_driver->getUserFormAttributes(); + foreach ($attrs as $attr) { + $v = &$this->addVariable($attr['label'], $attr['name'], + $attr['type'], $attr['required'], + $attr['readonly'], $attr['description'], + $attr['params']); + + if (!isset($attr['default'])) { + $v->setDefault($attr['default']); + } + } + //$this->addVariable(_("Target(s)"), 'target', 'text', false); + } + +} diff --git a/vilma/lib/MailboxDriver.php b/vilma/lib/MailboxDriver.php new file mode 100644 index 000000000..dff110ea3 --- /dev/null +++ b/vilma/lib/MailboxDriver.php @@ -0,0 +1,110 @@ + + * @package Vilma + */ +class Vilma_MailboxDriver { + + var $_params; + + /** + * Constructor. + * + * @access private + */ + function Vilma_MailboxDriver($params = array()) + { + $this->_params = $params; + } + + /** + * Creates a new mailbox driver instance. + * + * @param string $driver The name of the driver to create an instance of. + * @param array $params Driver-specific parameters. + * + * @return Vilma_MailboxDriver The new driver instance or a PEAR_Error. + */ + function &factory($driver, $params = array()) + { + require_once VILMA_BASE . '/lib/MailboxDriver/' . $driver . '.php'; + $class = 'Vilma_MailboxDriver_' . $driver; + $mailbox = &new $class($params); + return $mailbox; + } + + /** + * Returns a mailbox driver instance with the specified params, creating + * it if necessary. + * + * @param string $driver The name of the driver to create an instance of. + * @param array $params Driver-specific parameters. + * + * @return Vilma_MailboxDriver The new driver instance or a PEAR_Error. + */ + function &singleton($driver, $params = array()) + { + static $cache; + $key = serialize(array($driver, $params)); + if (!isset($cache[$key])) { + $ret = &Vilma_MailboxDriver::factory($driver, $params); + if (is_a($ret, 'PEAR_Error')) { + return $ret; + } + $cache[$key] = &$ret; + } + return $cache[$key]; + } + + /** + * Creates a new mailbox. + * + * This default implementation only returns an error. + * + * @param string $user The name of the mailbox to create + * @param string $domain The name of the domain in which to create the + * mailbox + * @return mixed True or PEAR_Error:: instance. + */ + function createMailbox($user, $domain) + { + return PEAR::raiseError(_("This driver cannot create mailboxes.")); + } + + /** + * Deletes an existing mailbox. + * + * This default implementation only returns an error. + * + * @param string $user The name of the mailbox to delete + * @param string $domain The name of the domain in which to delete the + * mailbox + * + * @return mixed True or PEAR_Error:: instance. + */ + function deleteMailbox($user, $domain) + { + return PEAR::raiseError(_("This driver cannot delete mailboxes.")); + } + + /** + * Checks whether a mailbox exists and is set up properly. + * + * @param string $user The name of the mailbox to check + * @param string $domain The mailbox's domain + * + * @return mixed True or PEAR_Error:: instance. + */ + function checkMailbox($user, $domain) + { + return true; + } + +} diff --git a/vilma/lib/MailboxDriver/hooks.php b/vilma/lib/MailboxDriver/hooks.php new file mode 100644 index 000000000..253fe8c99 --- /dev/null +++ b/vilma/lib/MailboxDriver/hooks.php @@ -0,0 +1,49 @@ + + * + * See the enclosed file LICENSE for license information (BSD). If you did not + * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE. + * + * $Horde: vilma/lib/MailboxDriver/hooks.php,v 1.7 2007/09/10 22:28:57 jan Exp $ + * + * @author Ben Klang + * @package Vilma + */ + +class Vilma_MailboxDriver_hooks extends Vilma_MailboxDriver { + + function Vilma_MailboxDriver_hooks($params) + { + Horde::loadConfiguration('hooks.php', null, 'vilma'); + } + + + function checkMailbox($user, $domain) + { + if (function_exists('_vilma_hook_checkMailbox')) { + return call_user_func('_vilma_hook_checkMailbox', $user, $domain); + } else { + return true; + } + } + + function createMailbox($user, $domain) + { + if (function_exists('_vilma_hook_createMailbox')) { + return call_user_func('_vilma_hook_createMailbox', $user, $domain); + } else { + return true; + } + } + + function deleteMailbox($user, $domain) + { + if (function_exists('_vilma_hook_deleteMailbox')) { + return call_user_func('_vilma_hook_deleteMailbox', $user, $domain); + } else { + return true; + } + } + +} diff --git a/vilma/lib/MailboxDriver/imap.php b/vilma/lib/MailboxDriver/imap.php new file mode 100644 index 000000000..e7ada119d --- /dev/null +++ b/vilma/lib/MailboxDriver/imap.php @@ -0,0 +1,81 @@ + + * @package Vilma + */ +class Vilma_MailboxDriver_imap extends Vilma_MailboxDriver { + + var $_imapAdmin = null; + + function _connect() + { + if (!is_null($this->_imapAdmin)) { + return false; + } + + // Catch c-client errors. + register_shutdown_function('imap_errors'); + register_shutdown_function('imap_alerts'); + + require_once 'Horde/IMAP/Admin.php'; + $admin = &new IMAP_Admin($this->_params); + if (is_a($admin, 'PEAR_Error')) { + return $admin; + } + + $this->_imapAdmin = $admin; + return true; + } + + function checkMailbox($user, $domain) + { + $res = $this->_connect(); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + if (!$this->_imapAdmin->mailboxExists($user . '@' . $domain)) { + return PEAR::raiseError(sprintf(_("Mailbox '%s@%s' does not exist."), $user, $domain)); + } + } + + function createMailbox($user, $domain) + { + $res = $this->_connect(); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + $mbox = $user . '@' . $domain; + + $res = $this->_imapAdmin->addMailbox($mbox); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + return true; + } + + function deleteMailbox($user, $domain) + { + $res = $this->_connect(); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + $res = $this->_imapAdmin->removeMailbox($user . '@' . $domain); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + return true; + } + +} diff --git a/vilma/lib/MailboxDriver/maildrop.php b/vilma/lib/MailboxDriver/maildrop.php new file mode 100644 index 000000000..b9e557c2e --- /dev/null +++ b/vilma/lib/MailboxDriver/maildrop.php @@ -0,0 +1,77 @@ + + * @package Vilma + */ +class Vilma_MailboxDriver_maildrop extends Vilma_MailboxDriver { + + function _getMailboxDir($user, $domain) + { + if (empty($this->_params['mail_dir_base'])) { + require_once 'PEAR.php'; + return PEAR::raiseError(_("No 'mail_dir_base' parameter specified to maildrop driver.")); + } + $dir = $this->_params['mail_dir_base']; + $usedomain = isset($this->_params['usedomain']) ? $this->_params['usedomain'] : false; + if ($usedomain) { + $dir .= '/' . $domain; + } + + return $dir . '/' . $user; + } + + function checkMailbox($user, $domain) + { + static $exists; + + $dir = $this->_getMailboxDir($user, $domain); + if (is_a($dir, 'PEAR_Error')) { + return $dir; + } + + if (!isset($exists[$dir])) { + $exists[$dir] = is_dir($dir); + } + + if (!$exists[$dir]) { + require_once 'PEAR.php'; + return PEAR::raiseError(sprintf(_("Maildrop directory \"%s\" does not exist."), $dir)); + } + + return true; + } + + function createMailbox($user, $domain) + { + $dir = $this->_getMailboxDir($user, $domain); + if (is_a($dir, 'PEAR_Error')) { + return $dir; + } + if (empty($this->_params['system_user'])) { + require_once 'PEAR.php'; + return PEAR::raiseError(_("No 'system_user' parameter specified to maildrop driver.")); + } + + $create_function = sprintf('sudo -u %s maildirmake %s', + escapeshellarg($this->_params['system_user']), + escapeshellarg($dir)); + exec($create_function); + return true; + } + + /** + * @TODO: Implement + */ + function deleteMailbox($user, $domain) + { + return true; + } + +} diff --git a/vilma/lib/MailboxDriver/null.php b/vilma/lib/MailboxDriver/null.php new file mode 100644 index 000000000..32557dab5 --- /dev/null +++ b/vilma/lib/MailboxDriver/null.php @@ -0,0 +1,81 @@ + + * @package Vilma + */ +class Vilma_MailboxDriver_null extends Vilma_MailboxDriver { + + function _getMailboxDir($user, $domain) + { + /* + if (empty($this->_params['mail_dir_base'])) { + require_once 'PEAR.php'; + return PEAR::raiseError(_("No 'mail_dir_base' parameter specified to maildrop driver.")); + } + $dir = $this->_params['mail_dir_base']; + $usedomain = isset($this->_params['usedomain']) ? $this->_params['usedomain'] : false; + if ($usedomain) { + $dir .= '/' . $domain; + } + + return $dir . '/' . $user; + */ + } + + function checkMailbox($user, $domain) + { + /* + static $exists; + + $dir = $this->_getMailboxDir($user, $domain); + if (is_a($dir, 'PEAR_Error')) { + return $dir; + } + + if (!isset($exists[$dir])) { + $exists[$dir] = is_dir($dir); + } + + if (!$exists[$dir]) { + require_once 'PEAR.php'; + return PEAR::raiseError(sprintf(_("Maildrop directory \"%s\" does not exist."), $dir)); + } + */ + + return true; + } + + function createMailbox($user, $domain) + { + $dir = $this->_getMailboxDir($user, $domain); + if (is_a($dir, 'PEAR_Error')) { + return $dir; + } + if (empty($this->_params['system_user'])) { + require_once 'PEAR.php'; + return PEAR::raiseError(_("No 'system_user' parameter specified to maildrop driver.")); + } + + $create_function = sprintf('sudo -u %s maildirmake %s', + escapeshellarg($this->_params['system_user']), + escapeshellarg($dir)); + exec($create_function); + return true; + } + + /** + * @TODO: Implement + */ + function deleteMailbox($user, $domain) + { + return true; + } + +} diff --git a/vilma/lib/Vilma.php b/vilma/lib/Vilma.php new file mode 100644 index 000000000..442b5ceba --- /dev/null +++ b/vilma/lib/Vilma.php @@ -0,0 +1,192 @@ + + * @author David Cummings + * @package Vilma + */ +class Vilma { + + /** + * Check whether the current user has administrative permissions over + * the requested domain at the given permissions level. + * Also checks to see if the user is a Vilma superadmin. + * If the user is a Horde admin they automatically have permission. + * + * @param string $domain Domain for which to check permissions + * @param int $permmask Permissions that must be set for the user + * + * @return boolean True if the user has the requested permission + */ + function hasPermission($domain, $permmask = null) + { + // FIXME Should this really be the case? Superadmin is more granular + if (Horde_Auth::isAdmin()) { + return true; + } + + if ($permmask === null) { + $permmask = PERMS_SHOW|PERMS_READ; + } + + # Default deny all permissions + $user = 0; + $superadmin = 0; + + $superadmin = $GLOBALS['perms']->hasPermission('vilma:domains', + Horde_Auth::getAuth(), $permmask); + + $user = $GLOBALS['perms']->hasPermission($permname, Horde_Auth::getAuth(), + $permmask); + + return ($superadmin | $user); + } + + function getUserMgrTypes() + { + return array( + 'all' => array( + 'singular' => _("All"), + 'plural' => _("All") ), + 'user' => array( + 'singular' => _("User"), + 'plural' => _("Users"), ), + 'alias' => array( + 'singular' => _("Alias"), + 'plural' => _("Aliases"), ), + //'grpfwd' => array( + // 'singular' => _("Group/Forward"), + // 'plural' => _("Groups and Forwards"), ), ); + 'group' => array( + 'singular' => _("Group"), + 'plural' => _("Groups"), ), + 'forward' => array( + 'singular' => _("Forward"), + 'plural' => _("Forwards"),), ); + } + + /** + * Create tabs to navigate the user manager area + * + * return object Horde_UI_Tabs object + */ + function getUserMgrTabs(&$vars) + { + $url = Horde::applicationUrl('users/index.php'); + $tabs = &new Horde_UI_Tabs('section', $vars); + foreach (Vilma::getUserMgrTypes() as $section => $desc) { + $tabs->addTab($desc['plural'], $url, $section); + } + return $tabs; + } + + /** + * Attempt to determine the current domain name based on current user or + * a domain_id passed in by form. + * + * @return mixed string domain on success, false on failure, PEAR::Error on error + */ + function getCurDomain() + { + // Domain is passed in by ID, which may or may not be the + // the same as the actual DNS domain name + $domain_id = Horde_Util::getFormData('domain_id'); + + if (!empty($domain_id)) { + // FIXME: Make sure this only runs once per page-load + $domain = $GLOBALS['vilma_driver']->getDomain($domain_id); + if (is_a($domain, 'PEAR_Error')) { + return $domain; + } + if (empty($domain['domain_name'])) { + $domain = false; + } + Vilma::setCurDomain($domain); + } elseif (isset($_SESSION['vilma']['domain'])) { + $domain = $_SESSION['vilma']['domain']; + } + + return $domain; + } + + /** + * Set the current domain + */ + function setCurDomain($domain) + { + $_SESSION['vilma']['domain'] = $domain; + } + + /** + * Strip the domain from an email address (leaving the Username) + * + * @param string $email Email address to strip (leaving the Username) + * + * @return string Username portion of supplied email address + */ + function stripUser($email) + { + list($user, $domain) = explode('@', $email); + return $user; + } + + /** + * Strip the username from an email address (leaving the domain) + * + * @param string $email Email address to strip (leaving the domain) + * + * @return string Domain portion of supplied email address + */ + function stripDomain($email) + { + $parts = explode('@', $email); + if (count($parts) == 2) { + $parts = explode(',', $parts[1]); + return $parts[0]; + } + return null; + } + + function &getMailboxDriver() + { + global $conf; + + require_once VILMA_BASE . '/lib/MailboxDriver.php'; + $driver = &Vilma_MailboxDriver::singleton($conf['mailboxes']['driver'], + $conf['mailboxes']['params']); + return $driver; + } + + /** + * Build Vilma's list of menu items. + */ + function getMenu($returnType = 'object') + { + $menu = new Horde_Menu(); + + $menu->add(Horde::applicationUrl('domains/index.php'), _("_Domains"), 'domain.png'); + + if (Vilma::getCurDomain()) { + $domain = $_SESSION['vilma']['domain']; + $url = Horde::applicationUrl('users/index.php'); + $tmp = Horde_Util::addParameter($url, 'domain_id', $domain['domain_id']); + $menu->add(Horde::applicationUrl($tmp), _($domain['domain_name']), 'domain.png'); + $menu->add(Horde::applicationUrl('users/edit.php'), _("New _Address"), 'user.png', $GLOBALS['registry']->getImageDir('horde')); + } else { + $menu->add(Horde::applicationUrl('domains/edit.php'), _("_New Domain"), 'domain.png'); + } + + if ($returnType == 'object') { + return $menu; + } else { + return $menu->render(); + } + } + +} diff --git a/vilma/lib/api.php b/vilma/lib/api.php new file mode 100644 index 000000000..e03c30f01 --- /dev/null +++ b/vilma/lib/api.php @@ -0,0 +1,68 @@ + + * + * See the enclosed file LICENSE for license information (BSD). If you did not + * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE. + * + * $Horde: vilma/lib/api.php,v 1.10 2007/06/27 17:24:16 jan Exp $ + * + * See the enclosed file COPYING for license information (GPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/gpl.html. + * + * @author Ben Klang + * @package Vilma + */ +@define('VILMA_BASE', dirname(__FILE__) . '/..'); + +$_services['perms'] = array( + 'args' => array(), + 'type' => '{urn:horde}stringArray'); + + +$_services['listDomains'] = array( + 'args' => array(), + 'type' => '{urn:horde}stringArray'); + +function _vilma_perms() +{ + static $perms = array(); + if (!empty($perms)) { + return $perms; + } + + require_once VILMA_BASE . '/lib/base.php'; + global $vilma_driver; + + $perms['tree']['vilma']['superadmin'] = false; + $perms['title']['vilma:superadmin'] = _("Super Administrator"); + + $domains = $vilma_driver->getDomains(); + + // Run through every domain + foreach ($domains as $domain) { + $d = $domain['domain_id']; + $perms['tree']['vilma']['domains'][$d] = false; + $perms['title']['vilma:domains:' . $d] = $domain['name']; + } + + return $perms; +} + +function _vilma_listDomains() +{ + require_once VILMA_BASE . '/lib/base.php'; + global $vilma_driver; + + return $vilma_driver->getDomains(); + $domains = array(); + foreach ($vilma_driver->getDomains() as $domain) { + $domains[] = $domain['domain_name']; + } + return $domains; +} \ No newline at end of file diff --git a/vilma/lib/base.php b/vilma/lib/base.php new file mode 100644 index 000000000..ca709481d --- /dev/null +++ b/vilma/lib/base.php @@ -0,0 +1,58 @@ + + * @author Ben Klang + * @package Vilma + */ + +/* Check for a prior definition of HORDE_BASE (perhaps by an auto_prepend_file + * definition for site customization). */ +if (!defined('HORDE_BASE')) { + @define('HORDE_BASE', dirname(__FILE__) . '/../..'); +} + +/* Load the Horde Framework core, and set up inclusion paths. */ +require_once HORDE_BASE . '/lib/core.php'; + +/* Registry. */ +$registry = Horde_Registry::singleton(); +try { + $registry->pushApp('vilma', !defined('AUTH_HANDLER')); +} catch (Horde_Exception $e) { + if ($e->getCode() == 'permission_denied') { + Horde::authenticationFailureRedirect(); + } + Horde::fatal($e, __FILE__, __LINE__, false); +} +$conf = &$GLOBALS['conf']; +@define('VILMA_TEMPLATES', $registry->get('templates')); + +/* Find the base file path of Vilma */ +@define('VILMA_BASE', dirname(__FILE__) . '/..'); + +/* Vilma base library */ +require_once VILMA_BASE . '/lib/Vilma.php'; +require_once VILMA_BASE . '/lib/Driver.php'; + +/* Templates */ +$template = &new Horde_Template(); + +/* Notification system. */ +$notification = &Horde_Notification::singleton(); +$notification->attach('status'); + +/* Navigation Tabs */ +require_once 'Horde/UI/Tabs.php'; + +/* Vilma driver. */ +$GLOBALS['vilma_driver'] = &Vilma_Driver::singleton(); + +// Get the currently active domain, possibly storing a change into the session +$curdomain = Vilma::getCurDomain(); diff --git a/vilma/lib/tests/driver.phpt b/vilma/lib/tests/driver.phpt new file mode 100644 index 000000000..7b830a994 --- /dev/null +++ b/vilma/lib/tests/driver.phpt @@ -0,0 +1,155 @@ +--TEST-- +Vilma_Driver_sql:: +--FILE-- +getMessage()); + return; + } + + $filtered_params = $conf['storage']['params']; + $filtered_params['tables']['domainkey'] = '__FOO'; + + $GLOBALS['filtered'] = &Vilma_Driver::singleton('sql', $filtered_params); + if (is_a($GLOBALS['filtered'], 'PEAR_Error')) { + printf(_("ERROR(2): %s\n"), $GLOBALS['filtered']->getMessage()); + return; + } + + echo "ok\n"; +} + +function checkSaveDomain() +{ + global $filtered, $unfiltered; + + echo "Checking saveDomain()... "; + + $domain = array('domain_name' => 'filtered.example.com', + 'domain_transport' => 'cyrus', + 'domain_admin' => 'test@filtered.example.com', + 'domain_max_users' => 15, + 'domain_quota' => 0); + + $res = $filtered->saveDomain($domain); + if (is_a($res, 'PEAR_Error')) { + var_dump($res); + printf(_("ERROR(1): %s\n"), $res->getMessage()); + return; + } + + $res = $filtered->getDomainByName('filtered.example.com'); + if (is_a($res, 'PEAR_Error')) { + printf(_("ERROR(2): %s\n"), $res->getMessage()); + return; + } + + if ($res['domain_name'] != 'filtered.example.com') { + echo _("ERROR(3): got wrong domain.\n"); + return; + } + if ($res['domain_transport'] != $domain['domain_transport'] || + $res['domain_admin'] != $domain['domain_admin'] || + $res['domain_max_users'] != $domain['domain_max_users'] || + $res['domain_quota'] != $domain['domain_quota']) { + echo _("ERROR(4): got some wrong info.\n"); + return; + } + + $domain['domain_name'] = 'unfiltered.example.com'; + $res = $unfiltered->saveDomain($domain); + if (is_a($res, 'PEAR_Error')) { + printf(_("ERROR(5): %s\n"), $res->getMessage()); + return; + } + + $res = $unfiltered->getDomainByName('unfiltered.example.com'); + if (is_a($res, 'PEAR_Error')) { + printf(_("ERROR(6): %s\n"), $res->getMessage()); + return; + } + + if ($res['domain_name'] != 'unfiltered.example.com') { + echo _("ERROR(7): got wrong domain.\n"); + return; + } + if ($res['domain_transport'] != $domain['domain_transport'] || + $res['domain_admin'] != $domain['domain_admin'] || + $res['domain_max_users'] != $domain['domain_max_users'] || + $res['domain_quota'] != $domain['domain_quota']) { + echo _("ERROR(8): got some wrong info.\n"); + return; + } + + echo "ok\n"; +} + +function checkDeleteDomain() +{ + global $filtered, $unfiltered; + + echo "Checking deleteDomain()... "; + + $domain = $filtered->getDomainByName('filtered.example.com'); + if (is_a($domain, 'PEAR_Error')) { + printf(_("ERROR(1): %s\n"), $domain->getMessage()); + return; + } + + $res = $filtered->deleteDomain($domain['domain_id']); + if (is_a($res, 'PEAR_Error')) { + printf(_("ERROR(2): %s\n"), $res->getMessage()); + return; + } + + $domain = $unfiltered->getDomainByName('unfiltered.example.com'); + if (is_a($domain, 'PEAR_Error')) { + printf(_("ERROR(3): %s\n"), $domain->getMessage()); + return; + } + + $res = $unfiltered->deleteDomain($domain['domain_id']); + if (is_a($res, 'PEAR_Error')) { + printf(_("ERROR(4): %s\n"), $res->getMessage()); + return; + } + + echo "ok\n"; +} + +--EXPECT-- +Load... ok +Checking construction... ok +Checking saveDomain()... ok +Checking deleteDomain()... ok diff --git a/vilma/lib/version.php b/vilma/lib/version.php new file mode 100644 index 000000000..9749581fa --- /dev/null +++ b/vilma/lib/version.php @@ -0,0 +1 @@ + diff --git a/vilma/locale/de_DE/LC_MESSAGES/vilma.mo b/vilma/locale/de_DE/LC_MESSAGES/vilma.mo new file mode 100644 index 000000000..f74eec636 Binary files /dev/null and b/vilma/locale/de_DE/LC_MESSAGES/vilma.mo differ diff --git a/vilma/locale/es_ES/LC_MESSAGES/vilma.mo b/vilma/locale/es_ES/LC_MESSAGES/vilma.mo new file mode 100644 index 000000000..0b2a99869 Binary files /dev/null and b/vilma/locale/es_ES/LC_MESSAGES/vilma.mo differ diff --git a/vilma/locale/it_IT/LC_MESSAGES/vilma.mo b/vilma/locale/it_IT/LC_MESSAGES/vilma.mo new file mode 100644 index 000000000..cbd21bdda Binary files /dev/null and b/vilma/locale/it_IT/LC_MESSAGES/vilma.mo differ diff --git a/vilma/locale/lt_LT/LC_MESSAGES/vilma.mo b/vilma/locale/lt_LT/LC_MESSAGES/vilma.mo new file mode 100644 index 000000000..fe6e86987 Binary files /dev/null and b/vilma/locale/lt_LT/LC_MESSAGES/vilma.mo differ diff --git a/vilma/po/.cvsignore b/vilma/po/.cvsignore new file mode 100644 index 000000000..fd8854c89 --- /dev/null +++ b/vilma/po/.cvsignore @@ -0,0 +1 @@ +messages.po diff --git a/vilma/po/README b/vilma/po/README new file mode 100644 index 000000000..a985e94aa --- /dev/null +++ b/vilma/po/README @@ -0,0 +1 @@ +see horde/po/README diff --git a/vilma/po/de_DE.po b/vilma/po/de_DE.po new file mode 100644 index 000000000..15b3d98fe --- /dev/null +++ b/vilma/po/de_DE.po @@ -0,0 +1,500 @@ +# German translations for Vilma. +# Copyright 2004-2009 The Horde Project +# This file is distributed under the same license as the Vilma package. +# Jan Schneider , 2004-2008. +# +msgid "" +msgstr "" +"Project-Id-Version: Vilma 0.1-cvs\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2008-04-01 14:58+0200\n" +"PO-Revision-Date: 2008-04-01 15:15+0200\n" +"Last-Translator: Jan Schneider \n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: users/edit.php:53 +#, php-format +msgid "\"%s\" already has the maximum number of users allowed." +msgstr "\"%s\" hat bereits die maximale Benutzerzahl erreicht." + +#: lib/Driver/qmailldap.php:647 +msgid "Account Status" +msgstr "Kontostatus" + +#: lib/Driver/qmailldap.php:655 +msgid "Account is active" +msgstr "Konto ist aktiviert" + +#: lib/Driver/qmailldap.php:658 +msgid "Account is disabled" +msgstr "Konto ist deaktiviert" + +#: templates/users/index.html:13 +msgid "Address" +msgstr "Adresse" + +#: lib/Vilma.php:60 +msgid "Alias" +msgstr "Spitzname" + +#: lib/Driver/qmailldap.php:332 +#, php-format +msgid "Alias for %s" +msgstr "Alias für %s" + +#: lib/Vilma.php:61 +msgid "Aliases" +msgstr "Aliase" + +#: lib/Vilma.php:54 lib/Vilma.php:55 +msgid "All" +msgstr "Alle" + +#: lib/Driver/qmailldap.php:657 +msgid "Bounce Incoming Only" +msgstr "Nur Eingehendes abweisen" + +#: domains/delete.php:27 users/delete.php:34 users/delete.php:38 +#: virtuals/delete.php:34 virtuals/delete.php:38 +#: lib/Forms/DeleteDomainForm.php:27 +msgid "Delete" +msgstr "Löschen" + +#: domains/index.php:44 lib/Forms/DeleteDomainForm.php:17 +msgid "Delete Domain" +msgstr "Domain löschen" + +#: users/index.php:83 users/delete.php:31 virtuals/index.php:55 +msgid "Delete User" +msgstr "Benutzer löschen" + +#: virtuals/delete.php:31 +msgid "Delete Virtual Email Address" +msgstr "Virtuelle E-Mail-Adresse löschen" + +#: lib/Forms/DeleteDomainForm.php:29 +#, php-format +msgid "Delete domain \"%s\" and all associated email addresses?" +msgstr "Domain \"%s\" und alle dazugehörigen E-Mail-Adressen löschen?" + +#: virtuals/delete.php:36 +#, php-format +msgid "Delete the virtual email address \"%s\" => \"%s\"?" +msgstr "Virtuelle E-Mail-Adresse \"%s\" => \"%s\" löschen?" + +#: users/delete.php:36 +#, php-format +msgid "Delete user \"%s\" and all associated virtual email addresses?" +msgstr "" +"Benutzer \"%s\" und alle dazugehörigen virtuellen E-Mail-Adressen löschen?" + +#: virtuals/edit.php:64 templates/virtuals/index.html:20 +msgid "Destination" +msgstr "Ziel" + +#: virtuals/edit.php:54 +msgid "Destination type" +msgstr "Zieltyp" + +#: lib/Driver/qmailldap.php:656 +msgid "Disable Delivery Only" +msgstr "Nur Ausgehendes abweisen" + +#: config/prefs.php.dist:10 +msgid "Display details" +msgstr "Anzeigedetails" + +#: config/prefs.php.dist:9 +msgid "Display listings" +msgstr "Anzeigelisten" + +#: domains/delete.php:41 users/delete.php:34 users/delete.php:52 +#: virtuals/delete.php:34 virtuals/delete.php:52 +#: lib/Forms/DeleteDomainForm.php:27 +msgid "Do not delete" +msgstr "Nicht löschen" + +#: lib/Forms/EditDomainForm.php:32 templates/domains/index.html:16 +msgid "Domain" +msgstr "Domain" + +#: lib/Driver.php:229 +msgid "" +"Domain added but an error was encountered while calling the configured " +"hook. Contact your administrator for futher assistance." +msgstr "" +"Die Domain wurde hinzugefügt, aber beim Aufruf des konfigurierten Hooks ist " +"ein Fehler aufgetreten. Bitte wenden Sie sich an Ihren Systemadministrator " +"für weitere Hilfe." + +#: domains/delete.php:35 +msgid "Domain deleted." +msgstr "Domain gelöscht." + +#: domains/delete.php:42 +msgid "Domain not deleted." +msgstr "Domain nicht gelöscht." + +#: domains/edit.php:35 +msgid "Domain saved." +msgstr "Domain gespeichert." + +#: domains/index.php:45 lib/Forms/EditDomainForm.php:20 +msgid "Edit Domain" +msgstr "Domain bearbeiten" + +#: users/index.php:84 virtuals/index.php:56 +msgid "Edit User" +msgstr "Benutzer bearbeiten" + +#: lib/Forms/EditUserForm.php:22 +#, php-format +msgid "Edit User for \"%s\"" +msgstr "Benutzer von \"%s\" bearbeiten" + +#: virtuals/edit.php:47 +msgid "Edit Virtual Email Address" +msgstr "Virtuelle E-Mail-Adresse bearbeiten" + +#: virtuals/edit.php:53 +#, php-format +msgid "" +"Enter a virtual email address @%s and then indicate below where mail sent to " +"that address is to be delivered. The address must begin with an " +"alphanumerical character, it must contain only alphanumerical and '._-' " +"characters, and must end with an alphanumerical character." +msgstr "" +"Geben Sie eine virtuelle E-Mail-Adresse für die \"@%s\" Domain an und tragen " +"Sie unten ein, wohin Nachrichten, die an diese Adresse geschickt werden, " +"ausgeliefert werden sollen. E-Mail-Adressen müssen mit einem " +"alphanumerischen Zeichen beginnen und enden und dürfen nur alphanumerische " +"und die Zeichen \"._-\" enthalten." + +#: lib/Driver/qmailldap.php:593 +#, php-format +msgid "Error deleting account from LDAP: %s" +msgstr "Fehler beim Löschen des Kontos in LDAP: %s" + +#: domains/delete.php:33 +#, php-format +msgid "Error deleting domain. %s." +msgstr "Fehler beim Löschen der Domain. %s." + +#: users/delete.php:44 +#, php-format +msgid "Error deleting user. %s." +msgstr "Fehler beim Löschen des Benutzers. %s." + +#: virtuals/delete.php:44 +#, php-format +msgid "Error deleting virtual email. %s." +msgstr "Fehler beim Löschen der virtuellen E-Mail-Adresse. %s." + +#: lib/Driver/qmailldap.php:170 lib/Driver/qmailldap.php:175 +#, php-format +msgid "Error in LDAP search: %s" +msgstr "Fehler bei LDAP-Suche: %s" + +#: users/edit.php:35 +#, php-format +msgid "Error reading address information from backend: %s" +msgstr "Fehler beim Lesen der der Adressinformationen vom Backend: %s" + +#: lib/Driver/qmailldap.php:583 +#, php-format +msgid "Error retrieving LDAP results: %s" +msgstr "Fehler beim Lesen LDAP-Ergebnisse: %s" + +#: lib/Driver/qmailldap.php:308 lib/Driver/qmailldap.php:396 +#: lib/Driver/qmailldap.php:468 +#, php-format +msgid "Error returning LDAP results: %s" +msgstr "Fehler bei der Rückgabe der LDAP-Ergebnisse: %s" + +#: lib/Driver.php:195 +msgid "Error running authentication update script." +msgstr "Fehler beim Ausführen des Update-Skripts." + +#: domains/edit.php:33 +#, php-format +msgid "Error saving domain: %s." +msgstr "Fehler beim Speichern der Domain: %s." + +#: users/edit.php:64 +#, php-format +msgid "Error saving user. %s" +msgstr "Fehler beim Speichern des Benutzers. %s" + +#: virtuals/edit.php:77 +#, php-format +msgid "Error saving virtual email. %s." +msgstr "Fehler beim Speichern der virtuellen E-Mail-Adresse. %s." + +#: lib/Driver/qmailldap.php:302 lib/Driver/qmailldap.php:390 +#: lib/Driver/qmailldap.php:462 lib/Driver/qmailldap.php:577 +#, php-format +msgid "Error searching LDAP: %s" +msgstr "Fehler bei der LDAP-Suche: %s" + +#: lib/Driver.php:280 +msgid "Error while calling hook to delete domain." +msgstr "Fehler beim Aufruf des Hooks zum Löschen der Domain." + +#: lib/Forms/EditUserForm.php:41 templates/users/index.html:16 +msgid "Full Name" +msgstr "Vollständiger Name" + +#: lib/Vilma.php:63 +msgid "Group/Forward" +msgstr "Gruppe/Weiterleitung" + +#: lib/Vilma.php:64 +msgid "Groups and Forwards" +msgstr "Gruppen und Weiterleitungen" + +#: config/prefs.php.dist:20 +msgid "How many domain to display per page." +msgstr "Anzahl der Domains pro Seite." + +#: virtuals/edit.php:56 +msgid "Local user" +msgstr "Lokaler Benutzer" + +#: lib/MailboxDriver/imap.php:45 +#, php-format +msgid "Mailbox '%s@%s' does not exist." +msgstr "Die Mailbox '%s@%s' existiert nicht." + +#: lib/MailboxDriver/maildrop.php:45 +#, php-format +msgid "Maildrop directory \"%s\" does not exist." +msgstr "Das Maildrop-Verzeichnis \"%s\" existiert nicht." + +#: templates/domains/index.html:19 +msgid "Max Users" +msgstr "Maximale Benutzerzahl" + +#: lib/Forms/EditDomainForm.php:35 +msgid "Max users" +msgstr "Maximale Benutzerzahl" + +#: users/index.php:70 +msgid "Maximum Users" +msgstr "Maximale Benutzerzahl" + +#: lib/Driver/qmailldap.php:472 +msgid "" +"More than one DN returned for this alias. Please contact an administrator " +"to resolve this error." +msgstr "" +"Mehr als eine DN für diesen Alias gefunden. Bitte wenden Sie sich an einen " +"Administrator, um diesen Fehler zu beheben." + +#: lib/Driver/qmailldap.php:587 +msgid "More than one DN returned. Aborting delete operation." +msgstr "Mehr als eine DN zurückgeliefert. Löschvorgang abgebrochen." + +#: lib/Forms/EditUserForm.php:35 +msgid "" +"Name must begin with an alphanumeric character, must contain only " +"alphanumeric and '._-' characters, and must end with an alphanumeric " +"character." +msgstr "" +"Der Name muss mit einem alphanumerischen Zeichen beginnen und enden und darf " +"nur alphanumerische und die Zeichen \"._-\" enthalten." + +#: lib/Forms/EditDomainForm.php:20 +msgid "New Domain" +msgstr "Neue Domain" + +#: lib/Forms/EditUserForm.php:24 +#, php-format +msgid "New User @%s" +msgstr "Neuer Benutzer für Domain @%s" + +#: virtuals/index.php:48 +msgid "New Virtual Email" +msgstr "Neue virtuelle E-Mail-Adresse" + +#: virtuals/edit.php:47 +msgid "New Virtual Email Address" +msgstr "Neue virtuelle E-Mail-Adresse" + +#: lib/Vilma.php:169 +msgid "New _Address" +msgstr "Neue _Adresse" + +#: lib/MailboxDriver/maildrop.php:19 +msgid "No 'mail_dir_base' parameter specified to maildrop driver." +msgstr "" +"Kein 'mail_dir_base' Parameter in der Maildrop-Treiber-Konfiguration " +"angegeben." + +#: lib/MailboxDriver/maildrop.php:60 +msgid "No 'system_user' parameter specified to maildrop driver." +msgstr "" +"Kein 'system_user' Parameter in der Maildrop-Treiber-Konfiguration angegeben." +"<" + +#: lib/Driver.php:108 +#, php-format +msgid "No such address %s of type %s found." +msgstr "Adresse %s vom Typ %s nicht gefunden." + +#: lib/Driver.php:374 +#, php-format +msgid "No such backend \"%s\" found" +msgstr "Ein Backend namens \"%s\" konnte nicht gefunden werden" + +#: users/edit.php:74 +msgid "" +"No virtual email address set up for this user. You should set up at least " +"one virtual email address if this user is to receive any emails." +msgstr "" +"Für diesen Benutzer wurden keine virtuellen E-Mail-Adressen eingerichtet. " +"Sie sollten mindestens eine E-Mail-Adresse einrichten, wenn dieser Benutzer " +"E-Mails empfangen können soll." + +#: lib/Driver.php:245 lib/Driver.php:294 +msgid "Not implemented." +msgstr "Nicht implementiert." + +#: lib/Forms/EditUserForm.php:37 +msgid "Only enter a password if you wish to change this user's password" +msgstr "" +"Geben Sie nur ein Passwort ein, wenn Sie das Passwort dieses Benutzers " +"ändern möchten" + +#: lib/Forms/EditUserForm.php:37 lib/Forms/EditUserForm.php:39 +msgid "Password" +msgstr "Passwort" + +#: lib/Driver/sql.php:465 +msgid "Password must be supplied when creating a new user." +msgstr "Passwort muss beim Erstellen eines neuen Benutzers angegeben werden." + +#: lib/Forms/EditDomainForm.php:36 +msgid "Quota" +msgstr "Speicherplatz-Kontingent" + +#: virtuals/edit.php:57 +msgid "Remote address" +msgstr "Externe Adresse" + +#: virtuals/edit.php:61 +msgid "Remote e-mail address" +msgstr "Externe E-Mail-Adresse" + +#: config/prefs.php.dist:11 +msgid "Set default display parameters." +msgstr "Legen Sie Ihre Standard-Anzeigeeinstellungen fest." + +#: templates/users/index.html:22 +msgid "Status" +msgstr "Status" + +#: lib/api.php:43 +msgid "Super Administrator" +msgstr "Super-Administrator" + +#: lib/MailboxDriver.php:78 +msgid "This driver cannot create mailboxes." +msgstr "Dieses Treiber kann keine Mailboxen anlegen." + +#: lib/MailboxDriver.php:94 +msgid "This driver cannot delete mailboxes." +msgstr "Dieser Treiber kann keine Mailboxen löschen." + +#: lib/Forms/EditDomainForm.php:34 +msgid "Transport" +msgstr "Transport" + +#: templates/users/index.html:19 +msgid "Type" +msgstr "Typ" + +#: lib/Driver/qmailldap.php:696 +msgid "Unable to bind to the LDAP server. Check authentication credentials." +msgstr "" +"Anbindung an LDAP-Server fehlgeschlagen. Überprüfen Sie die " +"Authentifizierungsdaten." + +#: lib/Driver/qmailldap.php:691 +msgid "Unable to set LDAP protocol version" +msgstr "Die LDAP-Protokollversion konnte nicht gesetzt werden" + +#: lib/Driver.php:199 +msgid "Unknown error running authentication update script." +msgstr "Unbekannter Fehler beim Ausführen des Update-Skripts." + +#: lib/Vilma.php:57 +msgid "User" +msgstr "Benutzer" + +#: lib/Forms/EditUserForm.php:35 +msgid "User Name" +msgstr "Benutzername" + +#: users/delete.php:46 +msgid "User deleted." +msgstr "Benutzer gelöscht." + +#: users/edit.php:66 +msgid "User details saved." +msgstr "Benutzerdetails gespeichert." + +#: lib/Driver.php:132 +msgid "User disabled." +msgstr "Benutzer deaktiviert." + +#: users/delete.php:53 +msgid "User not deleted." +msgstr "Benutzer wurde nicht gelöscht." + +#: lib/Driver.php:155 +msgid "User ready." +msgstr "Benutzer bereit." + +#: virtuals/index.php:51 lib/Vilma.php:58 +msgid "Users" +msgstr "Benutzer" + +#: lib/Forms/EditDomainForm.php:36 +msgid "Value in MB" +msgstr "Wert in MB" + +#: lib/Driver.php:210 +msgid "Vilma_Driver::deleteUser(): Method Not Implemented." +msgstr "Vilma_Driver::deleteUser(): Methode nicht implementiert." + +#: virtuals/edit.php:53 +msgid "Virtual Email" +msgstr "Virtuelle E-Mail-Adresse" + +#: templates/virtuals/index.html:17 +msgid "Virtual Email Address" +msgstr "Virtuelle E-Mail-Adresse" + +#: virtuals/delete.php:46 +msgid "Virtual email deleted." +msgstr "Virtuelle E-Mail-Adresse gelöscht." + +#: virtuals/delete.php:53 +msgid "Virtual email not deleted." +msgstr "Virtuelle E-Mail-Adresse nicht gelöscht." + +#: virtuals/edit.php:79 +msgid "Virtual email saved." +msgstr "Virtuelle E-Mail-Adresse gespeichert." + +#: lib/Vilma.php:166 +msgid "_Domains" +msgstr "_Domains" + +#: lib/Vilma.php:171 +msgid "_New Domain" +msgstr "_Neue Domain" diff --git a/vilma/po/es_ES.po b/vilma/po/es_ES.po new file mode 100644 index 000000000..5fea8dfae --- /dev/null +++ b/vilma/po/es_ES.po @@ -0,0 +1,501 @@ +# Spanish translations for vilma package +# Traducciones al español para el paquete vilma. +# Copyright 2008-2009 The Horde Project +# This file is distributed under the same license as the vilma package. +# Automatically generated, 2008. +# +msgid "" +msgstr "" +"Project-Id-Version: Vilma 0.2-cvs\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2008-03-20 09:49+0100\n" +"PO-Revision-Date: 2008-03-20 09:49+0100\n" +"Last-Translator: Manuel P. Ayala \n" +"Language-Team: i18n@lists.horde.org\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: users/edit.php:53 +#, php-format +msgid "\"%s\" already has the maximum number of users allowed." +msgstr "\"%s\" ha alcanzado ya el número máximo de usuarios permitidos." + +#: lib/Driver/qmailldap.php:647 +msgid "Account Status" +msgstr "Estado de la cuenta" + +#: lib/Driver/qmailldap.php:655 +msgid "Account is active" +msgstr "La cuenta está activa" + +#: lib/Driver/qmailldap.php:658 +msgid "Account is disabled" +msgstr "La cuenta está deshabilitada" + +#: templates/users/index.html:13 +msgid "Address" +msgstr "Dirección" + +#: lib/Vilma.php:60 +msgid "Alias" +msgstr "Apodo" + +#: lib/Driver/qmailldap.php:332 +#, php-format +msgid "Alias for %s" +msgstr "Apodo de %s" + +#: lib/Vilma.php:61 +msgid "Aliases" +msgstr "Apodos" + +#: lib/Vilma.php:54 lib/Vilma.php:55 +msgid "All" +msgstr "Todos" + +#: lib/Driver/qmailldap.php:657 +msgid "Bounce Incoming Only" +msgstr "Rebotar sólo entrantes" + +#: virtuals/delete.php:34 virtuals/delete.php:38 users/delete.php:34 +#: users/delete.php:38 domains/delete.php:27 lib/Forms/DeleteDomainForm.php:27 +msgid "Delete" +msgstr "Eliminar" + +#: domains/index.php:44 lib/Forms/DeleteDomainForm.php:17 +msgid "Delete Domain" +msgstr "Eliminar dominio" + +#: virtuals/index.php:55 users/index.php:83 users/delete.php:31 +msgid "Delete User" +msgstr "Eliminar usuario" + +#: virtuals/delete.php:31 +msgid "Delete Virtual Email Address" +msgstr "Eliminar dirección electrónica virtual" + +#: lib/Forms/DeleteDomainForm.php:29 +#, php-format +msgid "Delete domain \"%s\" and all associated email addresses?" +msgstr "" +"¿Eliminar el dominio \"%s\" y todas las direcciones electrónicas asociadas?" + +#: virtuals/delete.php:36 +#, php-format +msgid "Delete the virtual email address \"%s\" => \"%s\"?" +msgstr "¿Eliminar la dirección electrónica virtual \"%s\" => \"%s\"?" + +#: users/delete.php:36 +#, php-format +msgid "Delete user \"%s\" and all associated virtual email addresses?" +msgstr "" +"¿Eliminar el usuario \"%s\" y todas sus direcciones electrónicas virtuales " +"asociadas?" + +#: virtuals/edit.php:64 templates/virtuals/index.html:20 +msgid "Destination" +msgstr "Destinatario" + +#: virtuals/edit.php:54 +msgid "Destination type" +msgstr "Tipo de destinatario" + +#: lib/Driver/qmailldap.php:656 +msgid "Disable Delivery Only" +msgstr "Desactivar sólo la distribución" + +#: config/.bak/prefs.php.dist:10 +msgid "Display details" +msgstr "Mostrar detalles" + +#: config/.bak/prefs.php.dist:9 +msgid "Display listings" +msgstr "Mostrar listados" + +#: virtuals/delete.php:34 virtuals/delete.php:52 users/delete.php:34 +#: users/delete.php:52 domains/delete.php:41 lib/Forms/DeleteDomainForm.php:27 +msgid "Do not delete" +msgstr "No eliminar" + +#: lib/Forms/EditDomainForm.php:32 templates/domains/index.html:16 +msgid "Domain" +msgstr "Dominio" + +#: lib/Driver.php:229 +msgid "" +"Domain added but an error was encountered while calling the configured " +"hook. Contact your administrator for futher assistance." +msgstr "" +"Se añadió el dominio pero se produjo un error al llamar al gancho " +"configurado. Para más información póngase en contacto con el administrador." + +#: domains/delete.php:35 +msgid "Domain deleted." +msgstr "Se ha eliminado el dominio." + +#: domains/delete.php:42 +msgid "Domain not deleted." +msgstr "No se ha eliminado el dominio." + +#: domains/edit.php:35 +msgid "Domain saved." +msgstr "Se ha guardado el dominio." + +#: domains/index.php:45 lib/Forms/EditDomainForm.php:20 +msgid "Edit Domain" +msgstr "Modificar dominio" + +#: virtuals/index.php:56 users/index.php:84 +msgid "Edit User" +msgstr "Modificar usuario" + +#: lib/Forms/EditUserForm.php:22 +#, php-format +msgid "Edit User for \"%s\"" +msgstr "Modificar usuario de \"%s\"" + +#: virtuals/edit.php:47 +msgid "Edit Virtual Email Address" +msgstr "Modificar dirección electrónica virtual" + +#: virtuals/edit.php:53 +#, php-format +msgid "" +"Enter a virtual email address @%s and then indicate below where mail sent to " +"that address is to be delivered. The address must begin with an " +"alphanumerical character, it must contain only alphanumerical and '._-' " +"characters, and must end with an alphanumerical character." +msgstr "" +"Introduzca una dirección de correo virtual @%s e indique a continuación a " +"dónde enviar el correo de esa dirección. Las direcciones tienen que empezar " +"por un carácter alfanumérico, sólo pueden contener caracteres alfanuméricos " +"y '._-' , y tienen que acabar por un carácter alfanumérico." + +#: lib/Driver/qmailldap.php:593 +#, php-format +msgid "Error deleting account from LDAP: %s" +msgstr "Error al eliminar la cuenta de LDAP: %s" + +#: domains/delete.php:33 +#, php-format +msgid "Error deleting domain. %s." +msgstr "Error al eliminar el dominio. %s." + +#: users/delete.php:44 +#, php-format +msgid "Error deleting user. %s." +msgstr "Error al eliminar el usuario. %s." + +#: virtuals/delete.php:44 +#, php-format +msgid "Error deleting virtual email. %s." +msgstr "Error al eliminar la dirección de correo virtual. %s." + +#: lib/Driver/qmailldap.php:170 lib/Driver/qmailldap.php:175 +#, php-format +msgid "Error in LDAP search: %s" +msgstr "Error en la búsqueda LDAP: %s" + +#: users/edit.php:35 +#, php-format +msgid "Error reading address information from backend: %s" +msgstr "Error leyendo la información de la dirección desde el motor: %s" + +#: lib/Driver/qmailldap.php:583 +#, php-format +msgid "Error retrieving LDAP results: %s" +msgstr "Error recuperando los resultados LDAP: %s" + +#: lib/Driver/qmailldap.php:308 lib/Driver/qmailldap.php:396 +#: lib/Driver/qmailldap.php:468 +#, php-format +msgid "Error returning LDAP results: %s" +msgstr "Error en la devolución de los resultados LDAP: %s" + +#: lib/Driver.php:195 +msgid "Error running authentication update script." +msgstr "Error al ejecutar el guión de actualización de autentificación." + +#: domains/edit.php:33 +#, php-format +msgid "Error saving domain: %s." +msgstr "Error al guardar el dominio: %s." + +#: users/edit.php:64 +#, php-format +msgid "Error saving user. %s" +msgstr "Error al guardar el usuario. %s" + +#: virtuals/edit.php:77 +#, php-format +msgid "Error saving virtual email. %s." +msgstr "Error al guardar la dirección electrónica virtual. %s." + +#: lib/Driver/qmailldap.php:302 lib/Driver/qmailldap.php:390 +#: lib/Driver/qmailldap.php:462 lib/Driver/qmailldap.php:577 +#, php-format +msgid "Error searching LDAP: %s" +msgstr "Error buscando en LDAP: %s" + +#: lib/Driver.php:280 +msgid "Error while calling hook to delete domain." +msgstr "Error al llamar al gancho de eliminación del dominio." + +#: lib/Forms/EditUserForm.php:41 templates/users/index.html:16 +msgid "Full Name" +msgstr "Nombre completo" + +#: lib/Vilma.php:63 +msgid "Group/Forward" +msgstr "Grupo/Reenvío" + +#: lib/Vilma.php:64 +msgid "Groups and Forwards" +msgstr "Grupos y reenvíos" + +#: config/.bak/prefs.php.dist:20 +msgid "How many domain to display per page." +msgstr "Cuántos dominios mostrar por página." + +#: virtuals/edit.php:56 +msgid "Local user" +msgstr "Usuario local" + +#: lib/MailboxDriver/imap.php:45 +#, php-format +msgid "Mailbox '%s@%s' does not exist." +msgstr "No existe el buzón '%s@%s'." + +#: lib/MailboxDriver/maildrop.php:45 +#, php-format +msgid "Maildrop directory \"%s\" does not exist." +msgstr "No existe el directorio maildrop \"%s\"." + +#: templates/domains/index.html:19 +msgid "Max Users" +msgstr "Número máximo de usuarios" + +#: lib/Forms/EditDomainForm.php:35 +msgid "Max users" +msgstr "Número máximo de usuarios" + +#: users/index.php:70 +msgid "Maximum Users" +msgstr "Número máximo de usuarios" + +#: lib/Driver/qmailldap.php:472 +msgid "" +"More than one DN returned for this alias. Please contact an administrator " +"to resolve this error." +msgstr "" +"Este apodo devolvió más de un DN. Póngase en contacto con el administrador " +"para resolver este error." + +#: lib/Driver/qmailldap.php:587 +msgid "More than one DN returned. Aborting delete operation." +msgstr "Se ha devuelto más de un DN. Anulando la operación de eliminación." + +#: lib/Forms/EditUserForm.php:35 +msgid "" +"Name must begin with an alphanumeric character, must contain only " +"alphanumeric and '._-' characters, and must end with an alphanumeric " +"character." +msgstr "" +"El nombre tiene que empezar por un carácter alfanumérico, tiene que contener " +"sólo caracteres alfanuméricos o '._-' y tiene que terminar por un carácter " +"alfanumérico." + +#: lib/Forms/EditDomainForm.php:20 +msgid "New Domain" +msgstr "Añadir dominio" + +#: lib/Forms/EditUserForm.php:24 +#, php-format +msgid "New User @%s" +msgstr "Añadir usuario @%s" + +#: virtuals/index.php:48 +msgid "New Virtual Email" +msgstr "Añadir correo virtual" + +#: virtuals/edit.php:47 +msgid "New Virtual Email Address" +msgstr "Añadir dirección de correo virtual" + +#: lib/Vilma.php:169 +msgid "New _Address" +msgstr "Añadir _dirección" + +#: lib/MailboxDriver/maildrop.php:19 +msgid "No 'mail_dir_base' parameter specified to maildrop driver." +msgstr "" +"No se ha especificado el parámetro 'mail_dir_base' en el controlador de " +"descarga de correo." + +#: lib/MailboxDriver/maildrop.php:60 +msgid "No 'system_user' parameter specified to maildrop driver." +msgstr "" +"No se ha especificado el parámetro 'system_user' en el controlador de " +"descarga de correo." + +#: lib/Driver.php:108 +#, php-format +msgid "No such address %s of type %s found." +msgstr "No se encontró una dirección %s de tipo %s." + +#: lib/Driver.php:374 +#, php-format +msgid "No such backend \"%s\" found" +msgstr "No se encontró el motor \"%s\"" + +#: users/edit.php:74 +msgid "" +"No virtual email address set up for this user. You should set up at least " +"one virtual email address if this user is to receive any emails." +msgstr "" +"A este usuario no se le ha configurado una dirección de correo vitual. Tiene " +"que configurar al menos una si este usuario va a recibir correo." + +#: lib/Driver.php:245 lib/Driver.php:294 +msgid "Not implemented." +msgstr "Sin desarrollar." + +#: lib/Forms/EditUserForm.php:37 +msgid "Only enter a password if you wish to change this user's password" +msgstr "" +"Introduzca un a contraseña sólo si desea cambiar la contraseña de este " +"usuario" + +#: lib/Forms/EditUserForm.php:37 lib/Forms/EditUserForm.php:39 +msgid "Password" +msgstr "Contraseña" + +#: lib/Driver/sql.php:465 +msgid "Password must be supplied when creating a new user." +msgstr "Al crear un usuario hay que introducir una contraseña." + +#: lib/Forms/EditDomainForm.php:36 +msgid "Quota" +msgstr "Espacio asignado" + +#: virtuals/edit.php:57 +msgid "Remote address" +msgstr "Dirección remota" + +#: virtuals/edit.php:61 +msgid "Remote e-mail address" +msgstr "Dirección electrónica remota" + +#: config/.bak/prefs.php.dist:11 +msgid "Set default display parameters." +msgstr "Define parámetros de visualización por omisión." + +#: templates/users/index.html:22 +msgid "Status" +msgstr "Estado" + +#: lib/api.php:43 +msgid "Super Administrator" +msgstr "Super administrador" + +#: lib/MailboxDriver.php:78 +msgid "This driver cannot create mailboxes." +msgstr "Este controlador no puede crear buzones." + +#: lib/MailboxDriver.php:94 +msgid "This driver cannot delete mailboxes." +msgstr "Este controlador no puede eliminar buzones." + +#: lib/Forms/EditDomainForm.php:34 +msgid "Transport" +msgstr "Transporte" + +#: templates/users/index.html:19 +msgid "Type" +msgstr "Tipo" + +#: lib/Driver/qmailldap.php:696 +msgid "Unable to bind to the LDAP server. Check authentication credentials." +msgstr "" +"No se pudo vincular al servidor LDAP. Compruebe las credenciales de " +"autentificación." + +#: lib/Driver/qmailldap.php:691 +msgid "Unable to set LDAP protocol version" +msgstr "No se puede establecer la versión del protocolo LDAP" + +#: lib/Driver.php:199 +msgid "Unknown error running authentication update script." +msgstr "" +"Se ha producido un error desconocido al ejecutar el guión de actualización " +"de autentificación." + +#: lib/Vilma.php:57 +msgid "User" +msgstr "Usuario" + +#: lib/Forms/EditUserForm.php:35 +msgid "User Name" +msgstr "Nombre del usuario" + +#: users/delete.php:46 +msgid "User deleted." +msgstr "Se ha eliminado el usuario." + +#: users/edit.php:66 +msgid "User details saved." +msgstr "Se han guardado los detalles del usuario." + +#: lib/Driver.php:132 +msgid "User disabled." +msgstr "Usuario deshabilitado." + +#: users/delete.php:53 +msgid "User not deleted." +msgstr "No se ha eliminado el usuario" + +#: lib/Driver.php:155 +msgid "User ready." +msgstr "El usuario está listo." + +#: virtuals/index.php:51 lib/Vilma.php:58 +msgid "Users" +msgstr "Usuarios" + +#: lib/Forms/EditDomainForm.php:36 +msgid "Value in MB" +msgstr "Valor en MB" + +#: lib/Driver.php:210 +msgid "Vilma_Driver::deleteUser(): Method Not Implemented." +msgstr "Vilma_Driver::deleteUser(): Método no desarrollado." + +#: virtuals/edit.php:53 +msgid "Virtual Email" +msgstr "Correo virtual" + +#: templates/virtuals/index.html:17 +msgid "Virtual Email Address" +msgstr "Dirección de correo virtual" + +#: virtuals/delete.php:46 +msgid "Virtual email deleted." +msgstr "Dirección virtual eliminada." + +#: virtuals/delete.php:53 +msgid "Virtual email not deleted." +msgstr "No se ha eliminado la dirección virtual." + +#: virtuals/edit.php:79 +msgid "Virtual email saved." +msgstr "Se ha guardado la dirección virtual." + +#: lib/Vilma.php:166 +msgid "_Domains" +msgstr "_Dominios" + +#: lib/Vilma.php:171 +msgid "_New Domain" +msgstr "_Añadir dominio" diff --git a/vilma/po/it_IT.po b/vilma/po/it_IT.po new file mode 100644 index 000000000..05482885f --- /dev/null +++ b/vilma/po/it_IT.po @@ -0,0 +1,367 @@ +# Italian translations for Mailadmin package. +# Copyright 2003-2009 The Horde Project +# This file is distributed under the same license as the Mailadmin package. +# Automatically generated, 2003. +# +msgid "" +msgstr "" +"Project-Id-Version: Mailadmin 0.1-cvs\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2004-08-30 14:11+0200\n" +"PO-Revision-Date: 2004-02-11 18:15-0100\n" +"Last-Translator: Marko Djukic \n" +"Language-Team: Italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: users/edit.php:47 +#, php-format +msgid "'%s' already has the maximum number of users allowed." +msgstr "'%s' gia' ha il numero massimo di utenti permessi." + +#: templates/domains/index.html:35 +msgid "Admin" +msgstr "Admin" + +#: users/index.php:53 +msgid "All Virtual Emails" +msgstr "Tutti gli Indirizzi Email Virtuali" + +#: virtuals/delete.php:37 virtuals/delete.php:41 users/delete.php:33 +#: users/delete.php:37 domains/delete.php:28 domains/delete.php:32 +msgid "Delete" +msgstr "Elimina" + +#: domains/delete.php:25 domains/index.php:48 +msgid "Delete Domain" +msgstr "Elimina Dominio" + +#: virtuals/index.php:52 users/delete.php:30 users/index.php:63 +msgid "Delete User" +msgstr "Elimina Utente" + +#: virtuals/delete.php:34 +msgid "Delete Virtual Email Address" +msgstr "Elimina Indirizzo Email Virtuale" + +#: domains/delete.php:30 +#, php-format +msgid "Delete domain '%s', all the users and virtual email addresses?" +msgstr "Elimina dominio '%s', tutti gli utenti e gli indirizzi email virtuali?" + +#: virtuals/delete.php:39 +#, php-format +msgid "Delete the virtual email address '%s' => '%s'?" +msgstr "Elimina l'indirizzo email virtuale '%s' => '%s'?" + +#: users/delete.php:35 +#, php-format +msgid "Delete user '%s' and all associated virtual email addresses?" +msgstr "Elimina l'utente '%s' e tutti i relativi indirizzi email virtuali?" + +#: templates/virtuals/index.html:37 +msgid "Destination" +msgstr "Destinazione" + +#: virtuals/edit.php:55 +msgid "Destination user" +msgstr "Utente di destinazione" + +#: virtuals/delete.php:37 virtuals/delete.php:55 users/delete.php:33 +#: users/delete.php:51 domains/delete.php:28 domains/delete.php:46 +msgid "Do not delete" +msgstr "Non eliminare" + +#: domains/edit.php:40 templates/domains/index.html:33 +msgid "Domain" +msgstr "Dominio" + +#: domains/edit.php:43 +msgid "Domain admin" +msgstr "Amministratore dominio" + +#: domains/delete.php:40 +msgid "Domain deleted." +msgstr "Dominio eliminato." + +#: domains/delete.php:47 +msgid "Domain not deleted." +msgstr "Dominio non eliminato." + +#: domains/edit.php:54 +msgid "Domain saved." +msgstr "Dominio salvato." + +#: domains/edit.php:34 domains/index.php:49 +msgid "Edit Domain" +msgstr "Modifica Dominio" + +#: virtuals/index.php:53 users/index.php:64 +msgid "Edit User" +msgstr "Modifica Utente" + +#: users/edit.php:52 +#, php-format +msgid "Edit User for '%s'" +msgstr "Modifica Utente per '%s'" + +#: virtuals/edit.php:48 +msgid "Edit Virtual Email Address" +msgstr "Modifica Indirizzo Email Virtuale" + +#: virtuals/edit.php:54 templates/virtuals/index.html:35 +msgid "Email" +msgstr "Email" + +#: users/edit.php:66 +msgid "Enabled?" +msgstr "Attivato?" + +#: virtuals/edit.php:54 +#, php-format +msgid "" +"Enter a virtual email address for the '@%s' domain. Address must begin with " +"an alphanumerical character, it must contain only alphanumerical and '._-' " +"characters, and must end with an alphanumerical character." +msgstr "" +"Inserisci un indirizzo email virtuale per il '@%s' dominio. L'indirizzo deve " +"iniziare con un carattere alfanumerico, deve avere solo caratteri " +"alfanumerici e '._-' caratteri, e deve finire con un carattere alfanumerico." + +#: domains/delete.php:38 +#, php-format +msgid "Error deleting domain. %s." +msgstr "Errore durante l'eliminazione del dominio. %s." + +#: users/delete.php:43 +#, php-format +msgid "Error deleting user. %s." +msgstr "Errore durante l'eliminazione dell'utente. %s." + +#: virtuals/delete.php:47 +#, php-format +msgid "Error deleting virtual email. %s." +msgstr "Errore durante l'eliminazione del indirizzo email virtuale. %s." + +#: lib/Driver.php:254 lib/Driver.php:288 +msgid "Error running authentication update script." +msgstr "" + +#: domains/edit.php:52 +#, php-format +msgid "Error saving domain. %s." +msgstr "Errore durante il salvataggio del dominio. %s." + +#: users/edit.php:76 +#, fuzzy, php-format +msgid "Error saving user. %s" +msgstr "Errore durante il salvataggio dell'utente. %s." + +#: virtuals/edit.php:62 +#, php-format +msgid "Error saving virtual email. %s." +msgstr "Errore durante il salvataggio indirizzo email virtuale. %s." + +#: templates/users/index.html:39 +msgid "Full Name" +msgstr "Nome Completo" + +#: lib/MailboxDriver/imap.php:42 +#, fuzzy, php-format +msgid "Mailbox '%s@%s' does not exist." +msgstr "Messaggio inesistente." + +#: lib/MailboxDriver/maildrop.php:49 +#, fuzzy, php-format +msgid "Maildrop directory '%s' does not exist." +msgstr "Cartella VFS non esiste." + +#: templates/domains/index.html:37 +#, fuzzy +msgid "Max Users" +msgstr "Utenti max" + +#: domains/edit.php:44 +msgid "Max users" +msgstr "Utenti max" + +#: users/index.php:46 +msgid "Maximum Users" +msgstr "Utenti massimi" + +#: users/edit.php:65 +msgid "Name" +msgstr "Nome" + +#: users/edit.php:59 +msgid "" +"Name must begin with an alphanumerical character, it must contain only " +"alphanumerical and '._-' characters, and must end with an alphanumerical " +"character." +msgstr "" +"Il nome deve iniziare con un carattere alfanumerico, deve avere solo " +"caratteri alfanumerici e '._-' caratteri, e deve finire con un carattere " +"alfanumerico." + +#: domains/edit.php:34 domains/index.php:44 +msgid "New Domain" +msgstr "Nuovo Dominio" + +#: users/index.php:43 +msgid "New User" +msgstr "Nuovo Utente" + +#: users/edit.php:52 +#, php-format +msgid "New User for '%s'" +msgstr "Nuovo Utente per '%s'" + +#: virtuals/index.php:45 users/index.php:50 +msgid "New Virtual Email" +msgstr "Dettagli Email Virtuale" + +#: virtuals/edit.php:48 +msgid "New Virtual Email Address" +msgstr "Nuovo Indirizzo Email Virtuale" + +#: lib/MailboxDriver/maildrop.php:20 +msgid "No 'mail_dir_base' parameter specified to maildrop driver." +msgstr "" + +#: lib/MailboxDriver/maildrop.php:64 +msgid "No 'system_user' parameter specified to maildrop driver." +msgstr "" + +#: lib/Driver.php:172 +#, php-format +msgid "No such backend '%s' found" +msgstr "Nessun backend '%s' trovato" + +#: users/edit.php:86 +msgid "" +"No virtual email address set up for this user. You should set up at least " +"one virtual email address if this user is to receive any emails." +msgstr "" +"Nessun indirizzo email virtuale impostato per questo utente. Dovresti " +"impostare al meno un indirizzo email virtuale se questo utente e' da " +"ricevere gli email." + +#: lib/Driver.php:114 +msgid "No virtual emails set." +msgstr "Nessun indirizzo email virtuale inserito." + +#: users/edit.php:61 +msgid "Only enter a password if you wish to change this user's password" +msgstr "" +"Inserisci una password solo nel caso in cui vuoi cambiare la password di " +"questo utente." + +#: users/edit.php:61 users/edit.php:63 +msgid "Password" +msgstr "Password" + +#: lib/Driver/sql.php:337 +msgid "Password must be supplied when creating a new user." +msgstr "" + +#: domains/edit.php:45 templates/users/index.html:41 +msgid "Quota" +msgstr "Quota" + +#: templates/index/notconfigured.inc:39 +#, fuzzy +msgid "Some of Vilma's configuration files are missing:" +msgstr "Mancano alcuni file di configurazione di Nag:" + +#: templates/users/index.html:43 +msgid "Status" +msgstr "Statis" + +#: lib/MailboxDriver.php:77 +msgid "This driver cannot create mailboxes." +msgstr "" + +#: lib/MailboxDriver.php:93 +#, fuzzy +msgid "This driver cannot delete mailboxes." +msgstr "Non era possibile eliminare il file:" + +#: templates/index/notconfigured.inc:44 +#, fuzzy +msgid "" +"This is the main Vilma configuration file. It contains options for all Vilma " +"scripts." +msgstr "" +"Questo è il file principale di configurazione di Nag. Contiene le opzioni " +"per tutti gli scripts di Nag." + +#: domains/edit.php:42 +msgid "Transport" +msgstr "Trasporto" + +#: lib/Driver.php:258 lib/Driver.php:292 +msgid "Unknown error running authentication update script." +msgstr "" + +#: users/edit.php:59 +msgid "User" +msgstr "Utente" + +#: templates/users/index.html:37 +#, fuzzy +msgid "User Name" +msgstr "Nome Utente" + +#: users/delete.php:45 +msgid "User deleted." +msgstr "Utente eliminato." + +#: users/edit.php:78 +msgid "User details saved." +msgstr "Dettagli utente salvati." + +#: lib/Driver.php:107 +msgid "User disabled." +msgstr "Utente disattivato." + +#: users/edit.php:67 +msgid "User is disabled" +msgstr "L'utente e' disattivato." + +#: users/edit.php:66 +msgid "User is enabled" +msgstr "L'utente e' attivato." + +#: users/delete.php:52 +msgid "User not deleted." +msgstr "Utente non eliminato." + +#: lib/Driver.php:137 +msgid "User ready." +msgstr "Utente pronto." + +#: virtuals/index.php:48 +msgid "Users" +msgstr "Utenti" + +#: domains/edit.php:45 +msgid "Value in MB" +msgstr "Valore in MB" + +#: templates/index/notconfigured.inc:4 +#, fuzzy +msgid "Vilma is not properly configured" +msgstr "Nag non è configurato correttamente." + +#: virtuals/delete.php:49 +msgid "Virtual email deleted." +msgstr "Indirizzo email virtuale eliminato." + +#: virtuals/delete.php:56 +msgid "Virtual email not deleted." +msgstr "Indirizzo email virtuale non eliminato." + +#: virtuals/edit.php:64 +msgid "Virtual email saved." +msgstr "Indirizzo email virtuale salvato." diff --git a/vilma/po/lt_LT.po b/vilma/po/lt_LT.po new file mode 100644 index 000000000..6eb3034a3 --- /dev/null +++ b/vilma/po/lt_LT.po @@ -0,0 +1,484 @@ +# Lithuanian translations for Vilma package. +# Copyright 2007-2009 The Horde Project +# This file is distributed under the same license as the Vilma package. +# Vilius Sumskas , 2004, 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: Vilma 0.2-cvs\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2007-11-02 15:40+0200\n" +"PO-Revision-Date: 2007-11-11 20:02+0200\n" +"Last-Translator: Vilius Sumskas \n" +"Language-Team: Lithuanian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-13\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%" +"100<10 || n%100>=20) ? 1 : 2);\n" + +#: users/edit.php:53 +#, php-format +msgid "\"%s\" already has the maximum number of users allowed." +msgstr "\"%s\" jau pasiekë maksimalø vartotojø skaièiø." + +#: lib/Driver/qmailldap.php:670 +msgid "Account Status" +msgstr "Paðto dëþutës bûsena" + +#: lib/Driver/qmailldap.php:678 +msgid "Account is active" +msgstr "Paðto dëþutë ájungta" + +#: lib/Driver/qmailldap.php:681 +msgid "Account is disabled" +msgstr "Paðto dëþutë iðjungta" + +#: templates/users/index.html:13 +msgid "Address" +msgstr "Adresas" + +#: lib/Vilma.php:60 +msgid "Alias" +msgstr "Pravardë" + +#: lib/Driver/qmailldap.php:371 +#, php-format +msgid "Alias for %s" +msgstr "Su %s susieti adresai" + +#: lib/Vilma.php:61 +msgid "Aliases" +msgstr "Susieti adresai" + +#: lib/Vilma.php:54 lib/Vilma.php:55 +msgid "All" +msgstr "Viskà" + +#: lib/Driver/qmailldap.php:680 +msgid "Bounce Incoming Only" +msgstr "Tik persiøsti gaunamus" + +#: domains/delete.php:29 domains/delete.php:33 users/delete.php:34 +#: users/delete.php:38 virtuals/delete.php:34 virtuals/delete.php:38 +msgid "Delete" +msgstr "Iðtrinti" + +#: domains/index.php:44 domains/delete.php:26 +msgid "Delete Domain" +msgstr "Iðtrinti domenà" + +#: users/index.php:82 users/delete.php:31 virtuals/index.php:55 +msgid "Delete User" +msgstr "Iðtrinti vartotojà" + +#: virtuals/delete.php:31 +msgid "Delete Virtual Email Address" +msgstr "Iðtrinti virtualø el. paðto adresà" + +#: domains/delete.php:31 +#, php-format +msgid "Delete domain \"%s\", all the users and virtual email addresses?" +msgstr "" +"Iðtrinti domenà \"%s\", visus vartotojus ir virtualius el. paðto adresus?" + +#: virtuals/delete.php:36 +#, php-format +msgid "Delete the virtual email address \"%s\" => \"%s\"?" +msgstr "Iðtrinti virtualø el. paðto adresà \"%s\" => \"%s\"?" + +#: users/delete.php:36 +#, php-format +msgid "Delete user \"%s\" and all associated virtual email addresses?" +msgstr "" +"Iðtrinti vartotojà \"%s\" ir visus susijusius virtualius el. paðto adresus?" + +#: virtuals/edit.php:64 templates/virtuals/index.html:20 +msgid "Destination" +msgstr "Gavëjas" + +#: virtuals/edit.php:54 +msgid "Destination type" +msgstr "Gavëjo tipas" + +#: lib/Driver/qmailldap.php:679 +msgid "Disable Delivery Only" +msgstr "Tik iðjungti pristatymà" + +#: config/prefs.php.dist:10 +msgid "Display details" +msgstr "Vaizdavimo nustatymai" + +#: config/prefs.php.dist:9 +msgid "Display listings" +msgstr "Sàraðo rodymas" + +#: domains/delete.php:29 domains/delete.php:47 users/delete.php:34 +#: users/delete.php:52 virtuals/delete.php:34 virtuals/delete.php:52 +msgid "Do not delete" +msgstr "Netrinti" + +#: lib/Forms/EditDomainForm.php:32 templates/domains/index.html:16 +msgid "Domain" +msgstr "Domenas" + +#: domains/delete.php:41 +msgid "Domain deleted." +msgstr "Domenas iðtrintas." + +#: domains/delete.php:48 +msgid "Domain not deleted." +msgstr "Domenas neiðtrintas." + +#: domains/edit.php:35 +msgid "Domain saved." +msgstr "Domenas iðsaugotas." + +#: domains/index.php:45 lib/Forms/EditDomainForm.php:20 +msgid "Edit Domain" +msgstr "Redaguoti domenà" + +#: users/index.php:83 virtuals/index.php:56 +msgid "Edit User" +msgstr "Redaguoti vartotojà" + +#: lib/Forms/EditUserForm.php:22 +#, php-format +msgid "Edit User for \"%s\"" +msgstr "Redaguoti \"%s\" vartotojà" + +#: virtuals/edit.php:47 +msgid "Edit Virtual Email Address" +msgstr "Redaguoti virtualius el. paðto adresus" + +#: virtuals/edit.php:53 +#, php-format +msgid "" +"Enter a virtual email address @%s and then indicate below where mail sent to " +"that address is to be delivered. The address must begin with an " +"alphanumerical character, it must contain only alphanumerical and '._-' " +"characters, and must end with an alphanumerical character." +msgstr "" +"Áraðykite virtualø el. paðto adresà domenui @%s. Adresas turi prasidëti " +"skaièiais arba raidëm, viduje gali turëti skaièius, raides arba '._-' " +"simbolius, ir turi baigtis skaièiais arba raidëmis." + +#: lib/Driver/qmailldap.php:616 +#, php-format +msgid "Error deleting account from LDAP: %s" +msgstr "Klaida trinant vartotojo vardà ið LDAP: %s" + +#: domains/delete.php:39 +#, php-format +msgid "Error deleting domain. %s." +msgstr "Klaida trinant domenà. %s." + +#: users/delete.php:44 +#, php-format +msgid "Error deleting user. %s." +msgstr "Klaida trinant vartotojà. %s." + +#: virtuals/delete.php:44 +#, php-format +msgid "Error deleting virtual email. %s." +msgstr "Klaida trinant virtualø el. paðto adresà. %s." + +#: lib/Driver/qmailldap.php:210 lib/Driver/qmailldap.php:215 +#, php-format +msgid "Error in LDAP search: %s" +msgstr "Klaida atliekant LDAP paieðkà: %s" + +#: users/edit.php:35 +#, php-format +msgid "Error reading address information from backend: %s" +msgstr "Klaida ið posistemës skaitant adresø informacijà: %s" + +#: lib/Driver/qmailldap.php:606 +#, php-format +msgid "Error retrieving LDAP results: %s" +msgstr "Klaida gaunant LDAP rezultatus: %s" + +#: lib/Driver/qmailldap.php:347 lib/Driver/qmailldap.php:435 +#: lib/Driver/qmailldap.php:507 +#, php-format +msgid "Error returning LDAP results: %s" +msgstr "Klaida graþinant LDAP rezultatus: %s" + +#: lib/Driver.php:195 +msgid "Error running authentication update script." +msgstr "Klaida leidþiant autentifikacijos atnaujinimo skriptà." + +#: domains/edit.php:33 +#, php-format +msgid "Error saving domain: %s." +msgstr "Klaida iðsaugant domenà: %s." + +#: users/edit.php:64 +#, php-format +msgid "Error saving user. %s" +msgstr "Klaida iðsaugant vartotojà. %s" + +#: virtuals/edit.php:77 +#, php-format +msgid "Error saving virtual email. %s." +msgstr "Klaida iðsaugant virtualø el. paðto adresà. %s." + +#: lib/Driver/qmailldap.php:341 lib/Driver/qmailldap.php:429 +#: lib/Driver/qmailldap.php:501 lib/Driver/qmailldap.php:600 +#, php-format +msgid "Error searching LDAP: %s" +msgstr "Klaida atliekant LDAP paieðkà: %s" + +#: lib/Forms/EditUserForm.php:41 templates/users/index.html:16 +msgid "Full Name" +msgstr "Pilnas vardas" + +#: lib/Vilma.php:63 +msgid "Group/Forward" +msgstr "Grupë/Persiuntimas" + +#: lib/Vilma.php:64 +msgid "Groups and Forwards" +msgstr "Grupës ir persiuntimai" + +#: config/prefs.php.dist:20 +msgid "How many domain to display per page." +msgstr "Kiek domenø rodyti viename puslapyje." + +#: virtuals/edit.php:56 +msgid "Local user" +msgstr "Vietinis vartotojas" + +#: lib/MailboxDriver/imap.php:45 +#, php-format +msgid "Mailbox '%s@%s' does not exist." +msgstr "Paðto dëþutë '%s@%s' neegzistuoja." + +#: lib/MailboxDriver/maildrop.php:45 +#, php-format +msgid "Maildrop directory \"%s\" does not exist." +msgstr "Maildrop katalogas \"%s\" neegzistuoja." + +#: templates/domains/index.html:19 +msgid "Max Users" +msgstr "Maks. vartotojø skaièius" + +#: lib/Forms/EditDomainForm.php:35 +msgid "Max users" +msgstr "Maks. vartotojø skaièius" + +#: users/index.php:69 +msgid "Maximum Users" +msgstr "Maks. vartotojø skaièius" + +#: lib/Driver/qmailldap.php:511 +msgid "" +"More than one DN returned for this alias. Please contact an administrator " +"to resolve this error." +msgstr "" +"Rastas daugiau nei vienas DN atitinkantis ðá vartotojà. Susisiekite su " +"administratoriumi." + +#: lib/Driver/qmailldap.php:610 +msgid "More than one DN returned. Aborting delete operation." +msgstr "Rastas daugiau nei vienas DN. Trynimo operacija nutraukiama." + +#: lib/Forms/EditUserForm.php:35 +msgid "" +"Name must begin with an alphanumeric character, must contain only " +"alphanumeric and '._-' characters, and must end with an alphanumeric " +"character." +msgstr "" +"Vardas turi prasidëti skaièiais arba raidëm, viduje gali turëti skaièius, " +"raides arba simbolius '._-', ir turi baigtis skaièiais arba raidëmis." + +#: lib/Forms/EditDomainForm.php:20 +msgid "New Domain" +msgstr "Naujas domenas" + +#: lib/Forms/EditUserForm.php:24 +#, php-format +msgid "New User @%s" +msgstr "Naujas @%s vartotojas" + +#: virtuals/index.php:48 +msgid "New Virtual Email" +msgstr "Naujas virtualus el. paðtas" + +#: virtuals/edit.php:47 +msgid "New Virtual Email Address" +msgstr "Naujas virtualus el. paðto adresas" + +#: lib/Vilma.php:169 +msgid "New _Address" +msgstr "Naujas adresas" + +#: lib/MailboxDriver/maildrop.php:19 +msgid "No 'mail_dir_base' parameter specified to maildrop driver." +msgstr "Maildrop tvarkyklëje neáraðytas 'mail_dir_base' parametras." + +#: lib/MailboxDriver/maildrop.php:60 +msgid "No 'system_user' parameter specified to maildrop driver." +msgstr "Maildrop tvarkyklëje neáraðytas 'system_user' parametras." + +#: lib/Driver.php:108 +#, php-format +msgid "No such address %s of type %s found." +msgstr "Adresas %s, kurio tipas %s, nerastas." + +#: lib/Driver.php:329 +#, php-format +msgid "No such backend \"%s\" found" +msgstr "Posistemë \"%s\" nerasta" + +#: users/edit.php:74 +msgid "" +"No virtual email address set up for this user. You should set up at least " +"one virtual email address if this user is to receive any emails." +msgstr "" +"Ðis vartotojas neturi virtualiø el. paðto adresø. Jeigu ðis vartotojas gauna " +"el. laiðkus, turëtumëte nurodyti bent vienà virtualø el. paðto adresà." + +#: lib/Driver.php:249 +msgid "Not implemented." +msgstr "Nerealizuota." + +#: lib/Forms/EditUserForm.php:37 +msgid "Only enter a password if you wish to change this user's password" +msgstr "Slaptaþodá áraðykite tik tada, jeigu já keièiate" + +#: lib/Forms/EditUserForm.php:37 lib/Forms/EditUserForm.php:39 +msgid "Password" +msgstr "Slaptaþodis" + +#: lib/Driver/sql.php:465 +msgid "Password must be supplied when creating a new user." +msgstr "Kurdami naujà vartotojà, privalote áraðyti slaptaþodá." + +#: lib/Forms/EditDomainForm.php:36 +msgid "Quota" +msgstr "Vieta serveryje" + +#: virtuals/edit.php:57 +msgid "Remote address" +msgstr "Iðoriniai adresai" + +#: virtuals/edit.php:61 +msgid "Remote e-mail address" +msgstr "Iðorinis el. paðto adresas" + +#: config/prefs.php.dist:11 +msgid "Set default display parameters." +msgstr "Standartinio vaizdavimo parametrø nustatymas." + +#: templates/users/index.html:22 +msgid "Status" +msgstr "Bûsena" + +#: lib/api.php:43 +msgid "Super Administrator" +msgstr "Super administratorius" + +#: lib/MailboxDriver.php:78 +msgid "This driver cannot create mailboxes." +msgstr "Ði tvarkyklë negali kurti paðto dëþuèiø." + +#: lib/MailboxDriver.php:94 +msgid "This driver cannot delete mailboxes." +msgstr "Ði tvarkyklë negali trinti paðto dëþuèiø." + +#: lib/Forms/EditDomainForm.php:34 +msgid "Transport" +msgstr "Transportas" + +#: templates/users/index.html:19 +msgid "Type" +msgstr "Tipas" + +#: lib/Driver/qmailldap.php:715 +msgid "Unable to bind to the LDAP server. Check authentication credentials." +msgstr "" +"Nepavyko autentifikuotis á LDAP serverá. Patikrinkite vartotojo vardà bei " +"slaptaþodá." + +#: lib/Driver/qmailldap.php:710 +msgid "Unable to set LDAP protocol version" +msgstr "Klaida keièiant LDAP protokolo versijà" + +#: lib/Driver.php:199 +msgid "Unknown error running authentication update script." +msgstr "Bevykdant autentifikacijos atnaujinimo skriptà ávyko neþinoma klaida." + +#: lib/Vilma.php:57 +msgid "User" +msgstr "Vartotojas" + +#: lib/Forms/EditUserForm.php:35 +msgid "User Name" +msgstr "Vartotojo vardas" + +#: users/delete.php:46 +msgid "User deleted." +msgstr "Vartotojas iðtrintas." + +#: users/edit.php:66 +msgid "User details saved." +msgstr "Vartotojo apraðymas iðsaugotas." + +#: lib/Driver.php:132 +msgid "User disabled." +msgstr "Vartotojas iðjungtas" + +#: users/delete.php:53 +msgid "User not deleted." +msgstr "Vartotojas neiðtrintas." + +#: lib/Driver.php:155 +msgid "User ready." +msgstr "Vartotojas paruoðtas." + +#: lib/Vilma.php:58 virtuals/index.php:51 +msgid "Users" +msgstr "Vartotojai" + +#: lib/Forms/EditDomainForm.php:36 +msgid "Value in MB" +msgstr "Reikðmë MB" + +#: lib/Driver.php:210 +msgid "Vilma_Driver::deleteUser(): Method Not Implemented." +msgstr "Vilma_Driver::deleteUser(): metodas nerealizuotas." + +#: virtuals/edit.php:53 +msgid "Virtual Email" +msgstr "Virtualus el. paðtas" + +#: templates/virtuals/index.html:17 +msgid "Virtual Email Address" +msgstr "Virtualus el. paðto adresas" + +#: virtuals/delete.php:46 +msgid "Virtual email deleted." +msgstr "Virtualus el. paðto adresas iðtrintas." + +#: virtuals/delete.php:53 +msgid "Virtual email not deleted." +msgstr "Virtualus el. paðto adresas neiðtrintas." + +#: virtuals/edit.php:79 +msgid "Virtual email saved." +msgstr "Virtualus el. paðto adresas iðsaugotas." + +#: lib/Driver/qmailldap.php:35 +msgid "You must configure a Horde DataTree backend to use Vilma." +msgstr "" +"Norëdami naugotis paðto valdymo sistema, turite sukonfigûruoti duomenø " +"medþio posistemæ." + +#: lib/Vilma.php:166 +msgid "_Domains" +msgstr "Domenai" + +#: lib/Vilma.php:171 +msgid "_New Domain" +msgstr "Naujas domenas" diff --git a/vilma/po/vilma.pot b/vilma/po/vilma.pot new file mode 100644 index 000000000..be999fd0e --- /dev/null +++ b/vilma/po/vilma.pot @@ -0,0 +1,476 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright YEAR Horde Project +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: dev@lists.horde.org\n" +"POT-Creation-Date: 2008-04-01 14:58+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: users/edit.php:53 +#, php-format +msgid "\"%s\" already has the maximum number of users allowed." +msgstr "" + +#: lib/Driver/qmailldap.php:647 +msgid "Account Status" +msgstr "" + +#: lib/Driver/qmailldap.php:655 +msgid "Account is active" +msgstr "" + +#: lib/Driver/qmailldap.php:658 +msgid "Account is disabled" +msgstr "" + +#: templates/users/index.html:13 +msgid "Address" +msgstr "" + +#: lib/Vilma.php:60 +msgid "Alias" +msgstr "" + +#: lib/Driver/qmailldap.php:332 +#, php-format +msgid "Alias for %s" +msgstr "" + +#: lib/Vilma.php:61 +msgid "Aliases" +msgstr "" + +#: lib/Vilma.php:54 lib/Vilma.php:55 +msgid "All" +msgstr "" + +#: lib/Driver/qmailldap.php:657 +msgid "Bounce Incoming Only" +msgstr "" + +#: domains/delete.php:27 users/delete.php:34 users/delete.php:38 +#: virtuals/delete.php:34 virtuals/delete.php:38 +#: lib/Forms/DeleteDomainForm.php:27 +msgid "Delete" +msgstr "" + +#: domains/index.php:44 lib/Forms/DeleteDomainForm.php:17 +msgid "Delete Domain" +msgstr "" + +#: users/index.php:83 users/delete.php:31 virtuals/index.php:55 +msgid "Delete User" +msgstr "" + +#: virtuals/delete.php:31 +msgid "Delete Virtual Email Address" +msgstr "" + +#: lib/Forms/DeleteDomainForm.php:29 +#, php-format +msgid "Delete domain \"%s\" and all associated email addresses?" +msgstr "" + +#: virtuals/delete.php:36 +#, php-format +msgid "Delete the virtual email address \"%s\" => \"%s\"?" +msgstr "" + +#: users/delete.php:36 +#, php-format +msgid "Delete user \"%s\" and all associated virtual email addresses?" +msgstr "" + +#: virtuals/edit.php:64 templates/virtuals/index.html:20 +msgid "Destination" +msgstr "" + +#: virtuals/edit.php:54 +msgid "Destination type" +msgstr "" + +#: lib/Driver/qmailldap.php:656 +msgid "Disable Delivery Only" +msgstr "" + +#: config/prefs.php.dist:10 +msgid "Display details" +msgstr "" + +#: config/prefs.php.dist:9 +msgid "Display listings" +msgstr "" + +#: domains/delete.php:41 users/delete.php:34 users/delete.php:52 +#: virtuals/delete.php:34 virtuals/delete.php:52 +#: lib/Forms/DeleteDomainForm.php:27 +msgid "Do not delete" +msgstr "" + +#: lib/Forms/EditDomainForm.php:32 templates/domains/index.html:16 +msgid "Domain" +msgstr "" + +#: lib/Driver.php:229 +msgid "" +"Domain added but an error was encountered while calling the configured " +"hook. Contact your administrator for futher assistance." +msgstr "" + +#: domains/delete.php:35 +msgid "Domain deleted." +msgstr "" + +#: domains/delete.php:42 +msgid "Domain not deleted." +msgstr "" + +#: domains/edit.php:35 +msgid "Domain saved." +msgstr "" + +#: domains/index.php:45 lib/Forms/EditDomainForm.php:20 +msgid "Edit Domain" +msgstr "" + +#: users/index.php:84 virtuals/index.php:56 +msgid "Edit User" +msgstr "" + +#: lib/Forms/EditUserForm.php:22 +#, php-format +msgid "Edit User for \"%s\"" +msgstr "" + +#: virtuals/edit.php:47 +msgid "Edit Virtual Email Address" +msgstr "" + +#: virtuals/edit.php:53 +#, php-format +msgid "" +"Enter a virtual email address @%s and then indicate below where mail sent to " +"that address is to be delivered. The address must begin with an " +"alphanumerical character, it must contain only alphanumerical and '._-' " +"characters, and must end with an alphanumerical character." +msgstr "" + +#: lib/Driver/qmailldap.php:593 +#, php-format +msgid "Error deleting account from LDAP: %s" +msgstr "" + +#: domains/delete.php:33 +#, php-format +msgid "Error deleting domain. %s." +msgstr "" + +#: users/delete.php:44 +#, php-format +msgid "Error deleting user. %s." +msgstr "" + +#: virtuals/delete.php:44 +#, php-format +msgid "Error deleting virtual email. %s." +msgstr "" + +#: lib/Driver/qmailldap.php:170 lib/Driver/qmailldap.php:175 +#, php-format +msgid "Error in LDAP search: %s" +msgstr "" + +#: users/edit.php:35 +#, php-format +msgid "Error reading address information from backend: %s" +msgstr "" + +#: lib/Driver/qmailldap.php:583 +#, php-format +msgid "Error retrieving LDAP results: %s" +msgstr "" + +#: lib/Driver/qmailldap.php:308 lib/Driver/qmailldap.php:396 +#: lib/Driver/qmailldap.php:468 +#, php-format +msgid "Error returning LDAP results: %s" +msgstr "" + +#: lib/Driver.php:195 +msgid "Error running authentication update script." +msgstr "" + +#: domains/edit.php:33 +#, php-format +msgid "Error saving domain: %s." +msgstr "" + +#: users/edit.php:64 +#, php-format +msgid "Error saving user. %s" +msgstr "" + +#: virtuals/edit.php:77 +#, php-format +msgid "Error saving virtual email. %s." +msgstr "" + +#: lib/Driver/qmailldap.php:302 lib/Driver/qmailldap.php:390 +#: lib/Driver/qmailldap.php:462 lib/Driver/qmailldap.php:577 +#, php-format +msgid "Error searching LDAP: %s" +msgstr "" + +#: lib/Driver.php:280 +msgid "Error while calling hook to delete domain." +msgstr "" + +#: lib/Forms/EditUserForm.php:41 templates/users/index.html:16 +msgid "Full Name" +msgstr "" + +#: lib/Vilma.php:63 +msgid "Group/Forward" +msgstr "" + +#: lib/Vilma.php:64 +msgid "Groups and Forwards" +msgstr "" + +#: config/prefs.php.dist:20 +msgid "How many domain to display per page." +msgstr "" + +#: virtuals/edit.php:56 +msgid "Local user" +msgstr "" + +#: lib/MailboxDriver/imap.php:45 +#, php-format +msgid "Mailbox '%s@%s' does not exist." +msgstr "" + +#: lib/MailboxDriver/maildrop.php:45 +#, php-format +msgid "Maildrop directory \"%s\" does not exist." +msgstr "" + +#: templates/domains/index.html:19 +msgid "Max Users" +msgstr "" + +#: lib/Forms/EditDomainForm.php:35 +msgid "Max users" +msgstr "" + +#: users/index.php:70 +msgid "Maximum Users" +msgstr "" + +#: lib/Driver/qmailldap.php:472 +msgid "" +"More than one DN returned for this alias. Please contact an administrator " +"to resolve this error." +msgstr "" + +#: lib/Driver/qmailldap.php:587 +msgid "More than one DN returned. Aborting delete operation." +msgstr "" + +#: lib/Forms/EditUserForm.php:35 +msgid "" +"Name must begin with an alphanumeric character, must contain only " +"alphanumeric and '._-' characters, and must end with an alphanumeric " +"character." +msgstr "" + +#: lib/Forms/EditDomainForm.php:20 +msgid "New Domain" +msgstr "" + +#: lib/Forms/EditUserForm.php:24 +#, php-format +msgid "New User @%s" +msgstr "" + +#: virtuals/index.php:48 +msgid "New Virtual Email" +msgstr "" + +#: virtuals/edit.php:47 +msgid "New Virtual Email Address" +msgstr "" + +#: lib/Vilma.php:169 +msgid "New _Address" +msgstr "" + +#: lib/MailboxDriver/maildrop.php:19 +msgid "No 'mail_dir_base' parameter specified to maildrop driver." +msgstr "" + +#: lib/MailboxDriver/maildrop.php:60 +msgid "No 'system_user' parameter specified to maildrop driver." +msgstr "" + +#: lib/Driver.php:108 +#, php-format +msgid "No such address %s of type %s found." +msgstr "" + +#: lib/Driver.php:374 +#, php-format +msgid "No such backend \"%s\" found" +msgstr "" + +#: users/edit.php:74 +msgid "" +"No virtual email address set up for this user. You should set up at least " +"one virtual email address if this user is to receive any emails." +msgstr "" + +#: lib/Driver.php:245 lib/Driver.php:294 +msgid "Not implemented." +msgstr "" + +#: lib/Forms/EditUserForm.php:37 +msgid "Only enter a password if you wish to change this user's password" +msgstr "" + +#: lib/Forms/EditUserForm.php:37 lib/Forms/EditUserForm.php:39 +msgid "Password" +msgstr "" + +#: lib/Driver/sql.php:465 +msgid "Password must be supplied when creating a new user." +msgstr "" + +#: lib/Forms/EditDomainForm.php:36 +msgid "Quota" +msgstr "" + +#: virtuals/edit.php:57 +msgid "Remote address" +msgstr "" + +#: virtuals/edit.php:61 +msgid "Remote e-mail address" +msgstr "" + +#: config/prefs.php.dist:11 +msgid "Set default display parameters." +msgstr "" + +#: templates/users/index.html:22 +msgid "Status" +msgstr "" + +#: lib/api.php:43 +msgid "Super Administrator" +msgstr "" + +#: lib/MailboxDriver.php:78 +msgid "This driver cannot create mailboxes." +msgstr "" + +#: lib/MailboxDriver.php:94 +msgid "This driver cannot delete mailboxes." +msgstr "" + +#: lib/Forms/EditDomainForm.php:34 +msgid "Transport" +msgstr "" + +#: templates/users/index.html:19 +msgid "Type" +msgstr "" + +#: lib/Driver/qmailldap.php:696 +msgid "Unable to bind to the LDAP server. Check authentication credentials." +msgstr "" + +#: lib/Driver/qmailldap.php:691 +msgid "Unable to set LDAP protocol version" +msgstr "" + +#: lib/Driver.php:199 +msgid "Unknown error running authentication update script." +msgstr "" + +#: lib/Vilma.php:57 +msgid "User" +msgstr "" + +#: lib/Forms/EditUserForm.php:35 +msgid "User Name" +msgstr "" + +#: users/delete.php:46 +msgid "User deleted." +msgstr "" + +#: users/edit.php:66 +msgid "User details saved." +msgstr "" + +#: lib/Driver.php:132 +msgid "User disabled." +msgstr "" + +#: users/delete.php:53 +msgid "User not deleted." +msgstr "" + +#: lib/Driver.php:155 +msgid "User ready." +msgstr "" + +#: virtuals/index.php:51 lib/Vilma.php:58 +msgid "Users" +msgstr "" + +#: lib/Forms/EditDomainForm.php:36 +msgid "Value in MB" +msgstr "" + +#: lib/Driver.php:210 +msgid "Vilma_Driver::deleteUser(): Method Not Implemented." +msgstr "" + +#: virtuals/edit.php:53 +msgid "Virtual Email" +msgstr "" + +#: templates/virtuals/index.html:17 +msgid "Virtual Email Address" +msgstr "" + +#: virtuals/delete.php:46 +msgid "Virtual email deleted." +msgstr "" + +#: virtuals/delete.php:53 +msgid "Virtual email not deleted." +msgstr "" + +#: virtuals/edit.php:79 +msgid "Virtual email saved." +msgstr "" + +#: lib/Vilma.php:166 +msgid "_Domains" +msgstr "" + +#: lib/Vilma.php:171 +msgid "_New Domain" +msgstr "" diff --git a/vilma/scripts/.htaccess b/vilma/scripts/.htaccess new file mode 100644 index 000000000..3a4288278 --- /dev/null +++ b/vilma/scripts/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/vilma/scripts/create_mailboxes.php b/vilma/scripts/create_mailboxes.php new file mode 100644 index 000000000..03ce19b4e --- /dev/null +++ b/vilma/scripts/create_mailboxes.php @@ -0,0 +1,53 @@ +#!/usr/bin/php +getAllUsers(); + +foreach ($users_by_domain as $domain => $users) { + foreach ($users as $user) { + /* Check for user's home dir. */ + if (!file_exists($user['user_home_dir'])) { + /* Try to make the user_home_dir, if false skip. */ + if (!mkdir($user['user_home_dir'])) { + continue; + } + } + /* Check for the domain's dir. */ + $domain_dir = $user['user_home_dir'] . '/' . $domain; + if (!file_exists($domain_dir)) { + /* Try to make the user_home_dir, if false skip. */ + if (!mkdir($domain_dir)) { + continue; + } + } + /* Check for user's mailbox directory and if missing create it. */ + $mailbox_dir = $user['user_home_dir'] . '/' . $user['user_mail_dir']; + if (!file_exists($mailbox_dir)) { + system('maildirmake ' . $mailbox_dir); + } + } +} diff --git a/vilma/scripts/sql/vilma.sql b/vilma/scripts/sql/vilma.sql new file mode 100644 index 000000000..c41ad9db9 --- /dev/null +++ b/vilma/scripts/sql/vilma.sql @@ -0,0 +1,41 @@ +--$Horde: vilma/scripts/sql/vilma.sql,v 1.8 2007/04/17 12:44:06 jan Exp $ +-- SQL scripts. + +CREATE TABLE vilma_domains ( + domain_id INT DEFAULT 0 NOT NULL, + domain_name VARCHAR(128) DEFAULT '' NOT NULL, + domain_transport VARCHAR(128) DEFAULT '' NOT NULL, + domain_max_users INT DEFAULT 0 NOT NULL, + domain_quota INT DEFAULT 0 NOT NULL, + domain_key VARCHAR(64), +-- + PRIMARY KEY (domain_id), + UNIQUE (domain_name) +); + +CREATE TABLE vilma_users ( + user_id INT DEFAULT 0 NOT NULL, + user_name VARCHAR(255) DEFAULT '' NOT NULL, + user_clear VARCHAR(255) DEFAULT '' NOT NULL, + user_crypt VARCHAR(255) DEFAULT '' NOT NULL, + user_full_name VARCHAR(255) DEFAULT '' NOT NULL, + user_uid INT NOT NULL, + user_gid INT NOT NULL, + user_home_dir VARCHAR(255) DEFAULT '' NOT NULL, + user_mail_dir VARCHAR(255) DEFAULT '' NOT NULL, + user_mail_quota INT DEFAULT 0 NOT NULL, + user_ftp_dir VARCHAR(255) DEFAULT NULL, + user_ftp_quota INT DEFAULT NULL, + user_enabled SMALLINT DEFAULT 1 NOT NULL, +-- + PRIMARY KEY (user_id), + UNIQUE (user_name) +); + +CREATE TABLE vilma_virtuals ( + virtual_id INT DEFAULT 0 NOT NULL, + virtual_email VARCHAR(128) DEFAULT '' NOT NULL, + virtual_destination VARCHAR(128) DEFAULT '' NOT NULL, +-- + PRIMARY KEY (virtual_id) +); diff --git a/vilma/templates/common-header.inc b/vilma/templates/common-header.inc new file mode 100644 index 000000000..55130fc97 --- /dev/null +++ b/vilma/templates/common-header.inc @@ -0,0 +1,29 @@ + + + + + +' : '' ?> + +get('name'); +if (!empty($title)) $page_title .= ' :: ' . $title; +if (!empty($refresh_time) && ($refresh_time > 0) && !empty($refresh_url)) { + echo "\n"; +} + +Horde::includeScriptFiles(); + +?> +<?php echo htmlspecialchars($page_title) ?> + + + + +> diff --git a/vilma/templates/domains/index.html b/vilma/templates/domains/index.html new file mode 100644 index 000000000..6bef877c3 --- /dev/null +++ b/vilma/templates/domains/index.html @@ -0,0 +1,37 @@ + + + + +

+ +

+ + + + + + + + + + + + + + + +
  + Domain + + Max Users +
+ + + + + + +
+
diff --git a/vilma/templates/main/main.html b/vilma/templates/main/main.html new file mode 100644 index 000000000..5c3c6ce57 --- /dev/null +++ b/vilma/templates/main/main.html @@ -0,0 +1,5 @@ + + + diff --git a/vilma/templates/users/index.html b/vilma/templates/users/index.html new file mode 100644 index 000000000..f4dad378d --- /dev/null +++ b/vilma/templates/users/index.html @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + +
  + Address + + Full Name + + Type + + Status +
+ + + + + + + + + +   + + + <> + + + + + + + + + + +
+
+
+
+ diff --git a/vilma/templates/virtuals/index.html b/vilma/templates/virtuals/index.html new file mode 100644 index 000000000..88294f7ab --- /dev/null +++ b/vilma/templates/virtuals/index.html @@ -0,0 +1,38 @@ + + + + +

+   | +   +

+ + + + + + + + + + + + + + + +
  + Virtual Email Address + + Destination +
+ + + + + + +
+
diff --git a/vilma/test.php b/vilma/test.php new file mode 100644 index 000000000..9da22200b --- /dev/null +++ b/vilma/test.php @@ -0,0 +1,50 @@ + + * @package Vilma + */ + +require_once './lib/version.php'; +@define('CONFIG_DIR', dirname(__FILE__) . '/config/'); + +$setup_ok = true; + +$config_files = array('conf.php', 'prefs.php'); + +?> + + + + +Vilma: System Capabilities Test + + + + +

Vilma Version

+
    +
  • Vilma:
  • +
+ +

Vilma Configuration Files

+
    +
  • - Yes
  • - No +
+ + diff --git a/vilma/themes/graphics/display.png b/vilma/themes/graphics/display.png new file mode 100644 index 000000000..3fd0567e2 Binary files /dev/null and b/vilma/themes/graphics/display.png differ diff --git a/vilma/themes/graphics/domain.png b/vilma/themes/graphics/domain.png new file mode 100644 index 000000000..7020eb990 Binary files /dev/null and b/vilma/themes/graphics/domain.png differ diff --git a/vilma/themes/graphics/favicon.ico b/vilma/themes/graphics/favicon.ico new file mode 100644 index 000000000..66d7b86ef Binary files /dev/null and b/vilma/themes/graphics/favicon.ico differ diff --git a/vilma/themes/graphics/sort.png b/vilma/themes/graphics/sort.png new file mode 100644 index 000000000..a93519005 Binary files /dev/null and b/vilma/themes/graphics/sort.png differ diff --git a/vilma/themes/graphics/vilma.png b/vilma/themes/graphics/vilma.png new file mode 100644 index 000000000..3c419166c Binary files /dev/null and b/vilma/themes/graphics/vilma.png differ diff --git a/vilma/users/delete.php b/vilma/users/delete.php new file mode 100644 index 000000000..aaab597d8 --- /dev/null +++ b/vilma/users/delete.php @@ -0,0 +1,165 @@ + + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; +require_once 'Horde/Form.php'; + +/* Only admin should be using this. */ +if (!Vilma::hasPermission($domain)) { + Horde::authenticationFailureRedirect(); +} + +$vars = Horde_Variables::getDefaultVariables(); +$address = $vars->get('address'); +$section = Horde_Util::getFormData('section','all'); + +//$addrInfo = $vilma_driver->getAddressInfo($address, 'all'); +/* +$user_id = $vars->get('address'); +$formname = $vars->get('formname'); +$user = $vilma_driver->getUser($user_id); +print_r($vars) . '
'; +echo $user_id . '
'; +echo $fromname . '
'; +print_r($user) . '
'; +$domain = Vilma::stripDomain($user['name']); +$domain = $vilma_driver->getDomainByName($domain); +*/ +$address = $vilma_driver->getAddressInfo($address); +$type = $address['type']; +if(($section == 'all') && ($type == 'alias')) { + $address = $vilma_driver->getAddressInfo($vars->get('address'),$type); +} +$user_id = $vars->get('address'); +$user = $vilma_driver->getUser($user_id); +$aliases = $vilma_driver->_getAliases($user_id); +$aliasesCount = 0; +if(is_array($aliases)) { + $aliasesCount = sizeof($aliases); +} +$domain = Vilma::stripDomain($user_id); +$forwards = $vilma_driver->_getGroupsAndForwards('forwards',$domain); +$forwardsCount = 0; +foreach($forwards as $entry) { + foreach($entry['targets'] as $target) { + if($user_id === $target) { + $forwardsCount++; + } + } +} +$groups = $vilma_driver->_getGroupsAndForwards('groups',$domain); +$groupsCount = 0; +foreach($groups as $entry) { + foreach($entry['targets'] as $target) { + if($user_id === $target) { + $groupsCount++; + } + } +} +if (is_a($address, 'PEAR_Error')) { + $notification->push(sprintf(_("Error reading address information from backend: %s"), $address->getMessage()), 'horde.error'); + $url = '/users/index.php'; + require VILMA_BASE . $url; + exit; +} +$user_name = $address['user_name']; +if(!isset($user_name) || empty($user_name)) { + $user_name = $address['address']; +} +$vars->set('user_name', Vilma::stripUser($user_name)); +$domain = Vilma::stripDomain($address); +$domain = $vilma_driver->getDomainByName($domain); +$vars->set('domain', $domain); +$vars->set('mode', 'edit'); + +$form = new Horde_Form($vars, _("Delete User")); +/* Set up the form. */ +$form->setButtons(array(_("Delete"), _("Do not delete"))); +//$form->addHidden($user_id, 'user_id', 'text', false); +$form->addHidden($address['address'], 'address', 'text', false); +$form->addHidden($section, 'section', 'text', false); + +$desc = "Delete user \"%s\""; +$sub = " and all dependencies?"; +$tot = $aliasesCount + $groupsCount + $forwardsCount; +if($tot > 0) { + $desc .= $sub; +} else { + $desc .= "?"; +} +if($aliasesCount > 0) { + $desc .= " Account has " . $aliasesCount . " aliases."; +} +if($forwardsCount > 0) { + $desc .= " Account is the target of " . $forwardsCount . " forward(s)."; +} +if($groupsCount > 0) { + $desc .= " Account belongs to " . $groupsCount . " group(s)."; +} +$form->addVariable(sprintf(_($desc), $user_name), 'description', 'description', false); +if ($vars->get('submitbutton') == _("Delete")) { + if($type == 'alias') { + if ($form->validate($vars)) { + $form->getInfo($vars, $info); + $delete = $vilma_driver->_savealias($address['address'],'delete'); + if (is_a($delete, 'PEAR_Error')) { + Horde::logMessage($delete, __FILE__, __LINE__, PEAR_LOG_ERR); + $notification->push(sprintf(_("Error deleting user. %s."), $delete->getMessage()), 'horde.error'); + $url = Horde_Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false); + header('Location: ' . $url); + exit; + } else { + $notification->push(_("User deleted."), 'horde.success'); + $url = Horde_Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false); + header('Location: ' . $url); + exit; + } + } + } else { + if ($form->validate($vars)) { + $form->getInfo($vars, $info); + //$delete = $vilma_driver->deleteUser($info['user_id']); + $delete = $vilma_driver->deleteUser($address['address']); + if (is_a($delete, 'PEAR_Error')) { + Horde::logMessage($delete, __FILE__, __LINE__, PEAR_LOG_ERR); + $notification->push(sprintf(_("Error deleting user. %s."), $delete->getMessage()), 'horde.error'); + $url = Horde_Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false); + header('Location: ' . $url); + exit; + } else { + $notification->push(_("User deleted."), 'horde.success'); + $url = Horde_Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false); + header('Location: ' . $url); + exit; + } + } + } +} elseif ($vars->get('submitbutton') == _("Do not delete")) { + $notification->push(_("User not deleted."), 'horde.message'); + $url = Horde_Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['domain_id'], false); + header('Location: ' . $url); + exit; +} + +/* Render the form. */ +require_once 'Horde/Form/Renderer.php'; +$renderer = &new Horde_Form_Renderer(); +$main = Horde_Util::bufferOutput(array($form, 'renderActive'), $renderer, $vars, 'delete.php', 'post'); + +$template->set('main', $main); +$template->set('menu', Vilma::getMenu('string')); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); + +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/main/main.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/vilma/users/edit.php b/vilma/users/edit.php new file mode 100644 index 000000000..16d56dd14 --- /dev/null +++ b/vilma/users/edit.php @@ -0,0 +1,113 @@ + + * @author David Cummings + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; +require_once 'Horde/Form.php'; + +require_once VILMA_BASE . '/lib/Forms/EditUserForm.php'; + +/* Only admin should be using this. */ +if (!Vilma::hasPermission($domain)) { + Horde::authenticationFailureRedirect(); +} +$vars = Horde_Variables::getDefaultVariables(); +$address = $vars->get('address'); +$section = Horde_Util::getFormData('section','all'); + +//$addrInfo = $vilma_driver->getAddressInfo($address, 'all'); +$domain = Vilma::stripDomain($address); + +/* Check if a form is being edited. */ +if (!$vars->exists('mode')) { + if ($address) { + $address = $vilma_driver->getAddressInfo($address,$section); + if (is_a($address, 'PEAR_Error')) { + $notification->push(sprintf(_("Error reading address information from backend: %s"), $address->getMessage()), 'horde.error'); + $url = '/users/index.php'; + require VILMA_BASE . $url; + exit; + } + $vars = new Horde_Variables($address); + $user_name = //$vars->get('address'); + $vars->get('user_name'); + $vars->set('user_name', Vilma::stripUser($user_name)); + $domain = Vilma::stripDomain($user_name); + $vars->set('domain', $domain); + $vars->set('type', $address['type']); + $vars->set('target', 'test'); //$address['target']); + $vars->set('mode', 'edit'); + } else { + $vars->set('mode', 'new'); + $domain_info = $_SESSION['vilma']['domain']; + $domain = $domain_info['domain_name']; + $domain_id = $domain_info['domain_id']; + $vars->set('domain', $domain); + $vars->set('id', $domain_id); + $vars->add('user_name', Horde_Util::getFormData('user_name','')); + } +} + +$domain = Vilma::stripDomain($address['address']); +$tmp = $vars->get('domain'); +if(!isset($tmp)) { + $vars->set('domain', $domain); +} +$form = &new EditUserForm($vars); +if (!$vars->exists('id') && !$vilma_driver->isBelowMaxUsers($domain)) { + $notification->push(sprintf(_("\"%s\" already has the maximum number of users allowed."), $domain), 'horde.error'); + require VILMA_BASE . '/users/index.php'; + exit; +} +if ($form->validate($vars)) { + $form->getInfo($vars, $info); + $info['user_name'] = Horde_String::lower($info['user_name']) . '@' . $domain; + $user_id = $vilma_driver->saveUser($info); + if (is_a($user_id, 'PEAR_Error')) { + Horde::logMessage($user_id, __FILE__, __LINE__, PEAR_LOG_ERR); + $notification->push(sprintf(_("Error saving user. %s"), $user_id->getMessage()), 'horde.error'); + } else { + $notification->push(_("User details saved."), 'horde.success'); + /* + $virtuals = $vilma_driver->getVirtuals($info['name']); + if (count($virtuals)) { + //User has virtual email addresses set up. + $url = Horde::applicationUrl('users/index.php', true); + header('Location: ' . (Vilma::hasPermission($domain) ? $url : Horde_Util::addParameter($url, 'domain', $domain, false))); + } else { + //User does not have any virtual email addresses set up. + $notification->push(_("No virtual email address set up for this user. You should set up at least one virtual email address if this user is to receive any emails."), 'horde.warning'); + $url = Horde::applicationUrl('virtuals/edit.php', true); + $url = Horde_Util::addParameter($url, array('domain' => $domain, 'stripped_email' => Vilma::stripUser($info['name']), 'virtual_destination' => $info['name']), null, false); + header('Location: ' . (Vilma::hasPermission($domain) ? $url : Horde_Util::addParameter($url, 'domain', $domain, false))); + } + */ + //exit; + } +} + +/* Render the form. */ +require_once 'Horde/Form/Renderer.php'; +$renderer = &new Horde_Form_Renderer(); + +$main = Horde_Util::bufferOutput(array($form, 'renderActive'), $renderer, $vars, 'edit.php', 'post'); + +$template->set('main', $main); +$template->set('menu', Vilma::getMenu('string')); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); + +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/main/main.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/vilma/users/index.php b/vilma/users/index.php new file mode 100644 index 000000000..ac90734e7 --- /dev/null +++ b/vilma/users/index.php @@ -0,0 +1,111 @@ + + * @author Ben Klang + * @author David Cummings + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; +require_once 'Horde/Prefs/CategoryManager.php'; + +/* Only admin should be using this. */ +if (!Vilma::hasPermission($curdomain)) { + Horde::authenticationFailureRedirect(); +} + +// Input validation: make sure we have a valid section +$vars = Horde_Variables::getDefaultVariables(); +$section = $vars->get('section'); +$tmp = Vilma::getUserMgrTypes(); +if (!array_key_exists($section, Vilma::getUserMgrTypes())) { + $section = 'all'; + $vars->set('section', $section); +} +$tabs = Vilma::getUserMgrTabs($vars); + +$addresses = $vilma_driver->getAddresses($curdomain['domain_name'], $section); +if (is_a($addresses, 'PEAR_Error')) { + $notification->push($addresses); + header('Location: ' . Horde::applicationUrl('index.php')); +} + +// Page results +$page = Horde_Util::getGet('page', 0); +$perpage = $prefs->getValue('addresses_perpage'); +$url = 'users/index.php'; +$url = Horde_Util::addParameter($url, 'section', $section); +$pager = new Horde_UI_Pager('page', + Horde_Variables::getDefaultVariables(), + array('num' => count($addresses), + 'url' => $url, + 'page_count' => 10, + 'perpage' => $perpage)); +$addresses = array_slice($addresses, $page*$perpage, $perpage); + +$types = Vilma::getUserMgrTypes(); +foreach ($addresses as $i => $address) { + $type = $address['type']; + $id = $address['id']; + $url = Horde::applicationUrl('users/edit.php'); + $url = Horde_Util::addParameter($url, 'address', $id); + if($type === 'alias') { + $addresses[$i]['edit_url'] = ''; + } else { + $addresses[$i]['edit_url'] = Horde_Util::addParameter($url, 'section', $section); + } + $url = Horde::applicationUrl('users/delete.php'); + $currentAddress = $address['address']; + if(!isset($currentAddress) || empty($currentAddress)) { + $currentAddress = $address['user_name'] . $address['domain']; + } + $url = Horde_Util::addParameter($url, 'address', $currentAddress); + //$addresses[$i]['del_url'] = Horde_Util::addParameter($url, 'address', $id); + $addresses[$i]['del_url'] = Horde_Util::addParameter($url, 'section', $section); + //$url = Horde::applicationUrl('users/edit.php'); + //$addresses[$i]['view_url'] = Horde_Util::addParameter($url, 'address', $address['user_name']); + $url = Horde::applicationUrl('users/edit.php'); + $url = Horde_Util::addParameter($url, 'address', $id); + if($type === 'alias') { + $addresses[$i]['view_url'] = ''; + } else { + $addresses[$i]['view_url'] = Horde_Util::addParameter($url, 'section', $section); + } + $addresses[$i]['type'] = $types[$address['type']]['singular']; + $addresses[$i]['status'] = $vilma_driver->getUserStatus($address); +} + +/* Set up the template action links. */ +if ($vilma_driver->isBelowMaxUsers($curdomain['domain_name'])) { + $url = Horde::applicationUrl('users/edit.php'); + $maxusers = ''; +} else { + $maxusers = _("Maximum Users"); +} + +$url = Horde::applicationUrl('virtuals/edit.php'); + +/* Set up the template fields. */ +$template->set('addresses', $addresses, true); +$template->set('maxusers', $maxusers, true); +$template->set('menu', Vilma::getMenu('string')); +$template->set('tabs', $tabs->render()); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); +$template->set('pager', $pager->render()); + +/* Set up the field list. */ +$images = array('delete' => Horde::img('delete.png', _("Delete User"), '', $registry->getImageDir('horde')), + 'edit' => Horde::img('edit.png', _("Edit User"), '', $registry->getImageDir('horde'))); +$template->set('images', $images); + +/* Render the page. */ +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/users/index.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/vilma/virtuals/delete.php b/vilma/virtuals/delete.php new file mode 100644 index 000000000..e222a1df1 --- /dev/null +++ b/vilma/virtuals/delete.php @@ -0,0 +1,69 @@ + + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; +require_once 'Horde/Form.php'; + +/* Only admin should be using this. */ +if (!Horde_Auth::isAdmin()) { + Horde::authenticationFailureRedirect(); +} + +$vars = Horde_Variables::getDefaultVariables(); +$virtual_id = $vars->get('virtual_id'); +$formname = $vars->get('formname'); + +$virtual = $vilma_driver->getVirtual($virtual_id); +$domain = Vilma::stripDomain($virtual['virtual_email']); +$domain = $vilma_driver->getDomainByName($domain); + +$form = new Horde_Form($vars, _("Delete Virtual Email Address")); + +/* Set up the form. */ +$form->setButtons(array(_("Delete"), _("Do not delete"))); +$form->addHidden('', 'virtual_id', 'text', false); +$form->addVariable(sprintf(_("Delete the virtual email address \"%s\" => \"%s\"?"), $virtual['virtual_email'], $virtual['virtual_destination']), 'description', 'description', false); + +if ($vars->get('submitbutton') == _("Delete")) { + if ($form->validate($vars)) { + $form->getInfo($vars, $info); + $delete = $vilma_driver->deleteVirtual($info['virtual_id']); + if (is_a($delete, 'PEAR_Error')) { + Horde::logMessage($delete, __FILE__, __LINE__, PEAR_LOG_ERR); + $notification->push(sprintf(_("Error deleting virtual email. %s."), $delete->getMessage()), 'horde.error'); + } else { + $notification->push(_("Virtual email deleted."), 'horde.success'); + $url = Horde_Util::addParameter(Horde::applicationUrl('virtuals/index.php'), 'domain_id', $domain['domain_id'], false); + header('Location: ' . $url); + exit; + } + } +} elseif ($vars->get('submitbutton') == _("Do not delete")) { + $notification->push(_("Virtual email not deleted."), 'horde.message'); + $url = Horde_Util::addParameter(Horde::applicationUrl('virtuals/index.php'), 'domain_id', $domain['domain_id'], false); + header('Location: ' . $url); + exit; +} + +/* Render the form. */ +require_once 'Horde/Form/Renderer.php'; +$renderer = &new Horde_Form_Renderer(); +$main = Horde_Util::bufferOutput(array($form, 'renderActive'), $renderer, $vars, 'delete.php', 'post'); + +$template->set('main', $main); +$template->set('menu', Vilma::getMenu('string')); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); + +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/main/main.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/vilma/virtuals/edit.php b/vilma/virtuals/edit.php new file mode 100644 index 000000000..c961da77b --- /dev/null +++ b/vilma/virtuals/edit.php @@ -0,0 +1,96 @@ + + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; +require_once 'Horde/Form.php'; +require_once 'Horde/Form/Action.php'; + +/* Only admin should be using this. */ +if (!Horde_Auth::isAdmin() && !Vilma::isDomainAdmin()) { + Horde::authenticationFailureRedirect(); +} + +$domain = Vilma::getDomain(); +$vars = Horde_Variables::getDefaultVariables(); +$virtual_id = $vars->get('virtual_id'); +$user = $vars->get('user'); +$formname = $vars->get('formname'); + +/* Check if a form is being edited. */ +$editing = false; +if ($virtual_id && !$formname) { + $vars = new Horde_Variables($vilma_driver->getVirtual($virtual_id)); + $editing = true; +} + +if (empty($domain)) { + $domain = Vilma::stripDomain($vars->get('virtual_destination')); +} +$users = $vilma_driver->getUsers($domain); +$user_list = array(); +foreach ($users as $user) { + $virtual_destination = substr($user['user_name'], 0, strpos($user['user_name'], '@')); + $user_list[$user['user_name']] = $virtual_destination; +} + +$form = new Horde_Form($vars, ($editing) ? _("Edit Virtual Email Address") : _("New Virtual Email Address")); + +/* Set up the form. */ +$form->setButtons(true, true); +$form->addHidden('', 'virtual_id', 'int', false); +$form->addHidden('', 'domain', 'text', false); +$form->addVariable(_("Virtual Email"), 'stripped_email', 'text', true, false, sprintf(_("Enter a virtual email address @%s and then indicate below where mail sent to that address is to be delivered. The address must begin with an alphanumerical character, it must contain only alphanumerical and '._-' characters, and must end with an alphanumerical character."), $domain), array('~^[a-zA-Z0-9]{1,1}[a-zA-Z0-9._-]*[a-zA-Z0-9]$~')); +$var = &$form->addVariable(_("Destination type"), 'destination_type', 'enum', + true, false, null, + array(array('local' => _("Local user"), + 'remote' => _("Remote address")))); +$action = Horde_Form_Action::factory('reload'); +$var->setAction($action); +if ($vars->get('destination_type') == 'remote') { + $form->addVariable(_("Remote e-mail address"), 'virtual_destination', + 'email', true, false); +} else { + $form->addVariable(_("Destination"), 'virtual_destination', 'enum', + true, false, null, array($user_list, true)); +} + +if ($form->validate($vars)) { + $form->getInfo($vars, $info); + $info['stripped_email'] = Horde_String::lower($info['stripped_email']); + if ($info['destination_type'] == 'remote') { + $info['virtual_destination'] = Horde_String::lower($info['virtual_destination']); + } + $virtual_id = $vilma_driver->saveVirtual($info, $domain); + if (is_a($virtual_id, 'PEAR_Error')) { + Horde::logMessage($virtual_id, __FILE__, __LINE__, PEAR_LOG_ERR); + $notification->push(sprintf(_("Error saving virtual email. %s."), $virtual_id->getMessage()), 'horde.error'); + } else { + $notification->push(_("Virtual email saved."), 'horde.success'); + $url = Horde::applicationUrl('virtuals/index.php', true); + header('Location: ' . Horde_Util::addParameter($url, 'user', $info['virtual_destination'], false)); + exit; + } +} + +/* Render the form. */ +require_once 'Horde/Form/Renderer.php'; +$renderer = new Horde_Form_Renderer(); +$main = Horde_Util::bufferOutput(array($form, 'renderActive'), $renderer, $vars, 'edit.php', 'post'); + +$template->set('main', $main); +$template->set('menu', Vilma::getMenu('string')); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); + +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/main/main.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc'; diff --git a/vilma/virtuals/index.php b/vilma/virtuals/index.php new file mode 100644 index 000000000..901e0ccfe --- /dev/null +++ b/vilma/virtuals/index.php @@ -0,0 +1,65 @@ + + */ + +@define('VILMA_BASE', dirname(__FILE__) . '/..'); +require_once VILMA_BASE . '/lib/base.php'; + +/* Only admin should be using this. */ +if (!Horde_Auth::isAdmin() && !Vilma::isDomainAdmin()) { + Horde::authenticationFailureRedirect(); +} + +$user = Horde_Util::getFormData('user'); +if (!empty($user)) { + $virtuals = $vilma_driver->getVirtuals($user); + $domain = Vilma::stripDomain($user); +} else { + $domain = Vilma::getDomain(); + $virtuals = $vilma_driver->getVirtuals($domain); +} + +if (is_a($virtuals, 'PEAR_Error')) { + $notification->push($virtuals); + header('Location: ' . Horde::applicationUrl('index.php')); +} + +foreach ($virtuals as $id => $virtual) { + $url = Horde::applicationUrl('virtuals/edit.php'); + $virtuals[$id]['edit_url'] = Horde_Util::addParameter($url, 'virtual_id', $virtual['virtual_id']); + $url = Horde::applicationUrl('virtuals/delete.php'); + $virtuals[$id]['del_url'] = Horde_Util::addParameter($url, 'virtual_id', $virtual['virtual_id']); +} + +$template->set('virtuals', $virtuals, true); + +/* Set up the template action links. */ +$actions = array(); +$url = Horde::applicationUrl('virtuals/edit.php'); +$actions['new_url'] = (Vilma::isDomainAdmin() ? $url : Horde_Util::addParameter($url, 'domain', $domain)); +$actions['new_text'] = _("New Virtual Email"); +$url = Horde::applicationUrl('users/index.php'); +$actions['users_url'] = (Vilma::isDomainAdmin() ? $url : Horde_Util::addParameter($url, 'domain', $domain)); +$actions['users_text'] = _("Users"); +$template->set('actions', $actions); + +/* Set up the field list. */ +$images = array('delete' => Horde::img('delete.png', _("Delete User"), '', $registry->getImageDir('horde')), + 'edit' => Horde::img('edit.png', _("Edit User"), '', $registry->getImageDir('horde'))); +$template->set('images', $images); + +$template->set('menu', Vilma::getMenu('string')); +$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status'))); + +/* Render the page. */ +require VILMA_TEMPLATES . '/common-header.inc'; +echo $template->fetch(VILMA_TEMPLATES . '/virtuals/index.html'); +require $registry->get('templates', 'horde') . '/common-footer.inc';