diff options
author | mszulecki | 2007-06-14 17:09:01 +0000 |
---|---|---|
committer | mszulecki | 2007-06-14 17:09:01 +0000 |
commit | 9f108dd1a969473375341d92a7b1252fa2cedc9a (patch) | |
tree | d5f2e35ec0bd2d52dab0ee3282fc6751e0fa8dba /apps/admin | |
parent | e35884d11b81e4e4bbd73e1882e2b8011e85d118 (diff) | |
download | mailadmin-9f108dd1a969473375341d92a7b1252fa2cedc9a.tar.gz mailadmin-9f108dd1a969473375341d92a7b1252fa2cedc9a.tar.bz2 |
Initial import.
git-svn-id: http://svn.sukimashita.com/repos/mailadmin/trunk@2 4281df72-ff29-0410-8fee-2d9ac0c5f5a7
Diffstat (limited to 'apps/admin')
75 files changed, 2520 insertions, 0 deletions
diff --git a/apps/admin/config/app.yml b/apps/admin/config/app.yml new file mode 100644 index 0000000..1380235 --- /dev/null +++ b/apps/admin/config/app.yml @@ -0,0 +1,50 @@ +# default values +prod: + server: + default: + imap: + # Client Backend to use for IMAP server communication + # FakeIMAPClient: Returns pseudo data for testing purposes + # IMAPClient: Operates on a standards compliant IMAP server + client: IMAPClient + host: localhost + port: 143 + admin: cyrus + pass: secret + +all: + info: + version: 1.0.0 + pager: + max_per_page_options: [10,25,50,100] + max_per_page: 25 + domain: + quota: 150000 + max_mailbox_count: 300 + default_mailbox_quota: 20000 + mailbox: + deny_names: [cyrus, postmaster] + max_address_count: 300 + address: + dest_collapse_count: 1 + user: + domain_perm_collapse_count: 3 + server: + default: + pam: + # Method to encrypt Mailbox passwords (should match your pam setting) + # 0: plain = Passwords stored in plaintext + # 1: crypt = Use shadow-compatible crypt(3) function + # 2: md5 = Use md5 function + # 3: sha1 = Use sha1 function + crypt: 1 + imap: + # Client Backend to use for IMAP server communication + # FakeIMAPClient: Returns pseudo data for testing purposes + # IMAPClient: Operates on a standards compliant IMAP server + client: IMAPClient + host: mirell.de + port: 143 + admin: cyrus + pass: secret + diff --git a/apps/admin/config/cache.yml b/apps/admin/config/cache.yml new file mode 100644 index 0000000..9a80ccb --- /dev/null +++ b/apps/admin/config/cache.yml @@ -0,0 +1,4 @@ +default: + enabled: off + with_layout: false + lifetime: 86400 diff --git a/apps/admin/config/config.php b/apps/admin/config/config.php new file mode 100644 index 0000000..4038d49 --- /dev/null +++ b/apps/admin/config/config.php @@ -0,0 +1,8 @@ +<?php + +// include project configuration +include(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php'); + +// symfony bootstraping +require_once($sf_symfony_lib_dir.'/util/sfCore.class.php'); +sfCore::bootstrap($sf_symfony_lib_dir, $sf_symfony_data_dir); diff --git a/apps/admin/config/factories.yml b/apps/admin/config/factories.yml new file mode 100644 index 0000000..5566c36 --- /dev/null +++ b/apps/admin/config/factories.yml @@ -0,0 +1,35 @@ +cli: + controller: + class: sfConsoleController + request: + class: sfConsoleRequest + response: + class: sfConsoleResponse + +test: + storage: + class: sfSessionTestStorage + +#all: +# controller: +# class: sfFrontWebController +# +# request: +# class: sfWebRequest +# +# response: +# class: sfWebResponse +# +# user: +# class: myUser +# +# storage: +# class: sfSessionStorage +# param: +# session_name: symfony +# +# view_cache: +# class: sfFileCache +# param: +# automaticCleaningFactor: 0 +# cacheDir: %SF_TEMPLATE_CACHE_DIR% diff --git a/apps/admin/config/filters.yml b/apps/admin/config/filters.yml new file mode 100644 index 0000000..4850f6f --- /dev/null +++ b/apps/admin/config/filters.yml @@ -0,0 +1,10 @@ +rendering: ~ +web_debug: ~ +security: ~ + +# generally, you will want to insert your own filters here + +cache: ~ +common: ~ +flash: ~ +execution: ~ diff --git a/apps/admin/config/i18n.yml b/apps/admin/config/i18n.yml new file mode 100644 index 0000000..b849457 --- /dev/null +++ b/apps/admin/config/i18n.yml @@ -0,0 +1,7 @@ +all: + default_culture: en + source: XLIFF + debug: off + cache: on + untranslated_prefix: "[T]" + untranslated_suffix: "[/T]" diff --git a/apps/admin/config/logging.yml b/apps/admin/config/logging.yml new file mode 100644 index 0000000..df51180 --- /dev/null +++ b/apps/admin/config/logging.yml @@ -0,0 +1,22 @@ +prod: + enabled: off + level: err + rotate: on + purge: off + +#all: +# enabled: on +# level: debug +# rotate: off +# period: 7 +# history: 10 +# purge: on +# loggers: +# sf_web_debug: +# class: sfWebDebugLogger +# param: +# condition: %SF_WEB_DEBUG% +# sf_file_debug: +# class: sfFileLogger +# param: +# file: %SF_LOG_DIR%/%SF_APP%_%SF_ENVIRONMENT%.log diff --git a/apps/admin/config/routing.yml b/apps/admin/config/routing.yml new file mode 100644 index 0000000..a3e29c3 --- /dev/null +++ b/apps/admin/config/routing.yml @@ -0,0 +1,23 @@ +# default rules +homepage: + url: / + param: { module: domain, action: index } + +login: + url: /login + param: { module: user, action: login } + +logout: + url: /logout + param: { module: user, action: logout } + +default_symfony: + url: /symfony/:action/* + param: { module: default } + +default_index: + url: /:module + param: { action: index } + +default: + url: /:module/:action/* diff --git a/apps/admin/config/security.yml b/apps/admin/config/security.yml new file mode 100644 index 0000000..87ef379 --- /dev/null +++ b/apps/admin/config/security.yml @@ -0,0 +1,3 @@ +all: + is_secure: on + diff --git a/apps/admin/config/settings.yml b/apps/admin/config/settings.yml new file mode 100644 index 0000000..c4d36e5 --- /dev/null +++ b/apps/admin/config/settings.yml @@ -0,0 +1,117 @@ +prod: + .settings: + no_script_name: on + +dev: + .settings: + # E_ALL | E_STRICT = 4095 + error_reporting: 4095 + web_debug: on + cache: off + no_script_name: off + etag: off + +test: + .settings: + # E_ALL | E_STRICT & ~E_NOTICE = 2047 + error_reporting: 2047 + cache: off + web_debug: off + no_script_name: off + etag: off + +all: + .settings: + validation_error_prefix: '' + validation_error_suffix: '' + + i18n: on + + .actions: + login_module: user + login_action: login + + secure_module: content + secure_action: secure + +#all: +# .actions: +# default_module: default # Default module and action to be called when +# default_action: index # A routing rule doesn't set it +# +# error_404_module: default # To be called when a 404 error is raised +# error_404_action: error404 # Or when the requested URL doesn't match any route +# +# login_module: default # To be called when a non-authenticated user +# login_action: login # Tries to access a secure page +# +# secure_module: default # To be called when a user doesn't have +# secure_action: secure # The credentials required for an action +# +# module_disabled_module: default # To be called when a user requests +# module_disabled_action: disabled # A module disabled in the module.yml +# +# unavailable_module: default # To be called when a user requests a page +# unavailable_action: unavailable # From an application disabled via the available setting below +# +# .settings: +# available: on # Enable the whole application. Switch to off to redirect all requests to the unavailable module and action. +# +# # Optional features. Deactivating unused features boots performance a bit. +# use_database: on # Enable database manager. Set to off if you don't use a database. +# use_security: on # Enable security features (login and credentials). Set to off for public applications. +# use_flash: on # Enable flash parameter feature. Set to off if you never use the set_flash() method in actions. +# i18n: off # Enable interface translation. Set to off if your application should not be translated. +# check_symfony_version: off # Enable check of symfony version for every request. Set to on to have symfony clear the cache automatically when the framework is upgraded. Set to off if you always clear the cache after an upgrade. +# use_process_cache: on # Enable symfony optimizations based on PHP accelerators. Set to off for tests or when you have enabled a PHP accelerator in your server but don't want symfony to use it internally. +# compressed: off # Enable PHP response compression. Set to on to compress the outgoing HTML via the PHP handler. +# check_lock: off # Enable the application lock system triggered by the clear-cache and disable tasks. Set to on to have all requests to disabled applications redirected to the $sf_symfony_data_dir/web/arrors/unavailable.php page. +# +# # Output escaping settings +# escaping_strategy: bc # Determines how variables are made available to templates. Accepted values: bc, both, on, off. The value off deactivates escaping completely and gives a slight boost. +# escaping_method: ESC_ENTITIES # Function or helper used for escaping. Accepted values: ESC_RAW, ESC_ENTITIES, ESC_JS, ESC_JS_NO_ENTITIES. +# +# # Routing settings +# suffix: . # Default suffix for generated URLs. If set to a single dot (.), no suffix is added. Possible values: .html, .php, and so on. +# no_script_name: off # Enable the front controller name in generated URLs +# +# # Validation settings, used for error generation by the Validation helper +# validation_error_prefix: ' ↓ ' +# validation_error_suffix: ' ↓' +# validation_error_class: form_error +# validation_error_id_prefix: error_for_ +# +# # Cache settings +# cache: off # Enable the template cache +# etag: on # Enable etag handling +# +# # Logging and debugging settings +# web_debug: off # Enable the web debug toolbar +# error_reporting: 341 # Determines which events are logged. The default value is E_PARSE | E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR | E_USER_ERROR = 341 +# +# # Assets paths +# rich_text_js_dir: js/tiny_mce +# prototype_web_dir: /sf/prototype +# admin_web_dir: /sf/sf_admin +# web_debug_web_dir: /sf/sf_web_debug +# +# # Helpers included in all templates by default +# standard_helpers: [Partial, Cache, Form] +# +# # Activated modules from plugins or from the symfony core +# enabled_modules: [default] +# +# # Charset used for the response +# charset: utf-8 +# +# # Miscellaneous +# strip_comments: on # Remove comments in core framework classes as defined in the core_compile.yml +# autoloading_functions: ~ # Functions called when a class is requested and this it is not already loaded. Expects an array of callables. Used by the framework bridges. +# timeout: 1800 # Session timeout, in seconds +# max_forwards: 5 +# path_info_array: SERVER +# path_info_key: PATH_INFO +# url_format: PATH +# +# # ORM +# orm: propel diff --git a/apps/admin/config/view.yml b/apps/admin/config/view.yml new file mode 100644 index 0000000..c7e566f --- /dev/null +++ b/apps/admin/config/view.yml @@ -0,0 +1,15 @@ +default: + http_metas: + content-type: text/html + + metas: + title: Mailadmin + robots: noindex, nofollow + description: IMAP Server Mailadministration + + stylesheets: [main] + + javascripts: [] + + has_layout: on + layout: layout diff --git a/apps/admin/lib/imap/FakeIMAPClient.php b/apps/admin/lib/imap/FakeIMAPClient.php new file mode 100644 index 0000000..aad0207 --- /dev/null +++ b/apps/admin/lib/imap/FakeIMAPClient.php @@ -0,0 +1,9 @@ +<?php + +class FakeIMAPClient implements IMAPClient +{ + +} + + +?> diff --git a/apps/admin/lib/imap/IMAPClient.php b/apps/admin/lib/imap/IMAPClient.php new file mode 100644 index 0000000..2271cc9 --- /dev/null +++ b/apps/admin/lib/imap/IMAPClient.php @@ -0,0 +1,498 @@ +<?php + +// Hello. Let's re-implement as we only need basic stuff... +// Could not find a suitable OO IMAP client class library either. + +class IMAPClient +{ + const RESULT_OK = 'OK'; + const RESULT_NO = 'NO'; + const RESULT_BAD = 'BAD'; + + const STATE_DISCONNECTED = 0; + const STATE_GREETING = 1; + const STATE_UNAUTH = 2; + const STATE_AUTH = 3; + const STATE_SELECTED = 4; + + // connection + protected $state = self::STATE_DISCONNECTED; + + private $socket = null; + public function __destruct() + { + // connection vanishes with instance + if($this->socket) + $this->closeConnection(); + } + + // FIXME: Extract server name and version; should probably be moved to own library (?) + /* + Couple of banners: + * OK mail.mirapoint.com Mirapoint IMAP4 3.7.4-GA server ready + * OK [CAPABILITY IMAP4rev1 UIDPLUS CHILDREN NAMESPACE THREAD=ORDEREDSUBJECT THREAD=REFERENCES SORT QUOTA IDLE ACL ACL2=UNION STARTTLS] Courier-IMAP ready. Copyright 1998-2004 Double Precision, Inc. See COPYING for distribution information. + * OK mail8.hotbox.ru Cyrus IMAP4 v2.2.3 server ready + * OK dovecot ready. + * OK Microsoft Exchange IMAP4rev1 server version 5.5.2654.50 (wlvexc00.diginsite.com) ready + * OK Microsoft Exchange Server 2003 IMAP4rev1 server version 6.5.6944.0 (stbowa02.stb.sun.ac.za) ready. + * OK [x.x.x.x] IMAP4rev1 Mercury/32 v4.01a server ready. + * OK Messaging Multiplexor (iPlanet Messaging Server 5.2 HotFix 1.26 (built Mar 31 2004)) + * OK [CAPABILITY IMAP4REV1 LOGIN-REFERRALS STARTTLS AUTH=LOGIN] leto IMAP4rev1 2001.315rh at Mon, 31 May 2004 11:06:55 +0200 (CEST) + * OK mail1 Cyrus IMAP4 v2.0.16 server ready + * OK Microsoft Exchange IMAP4rev1 server version Exchange 2000.4208.3 (EX2000.com) ready. + * OK mcis.com Microsoft IMAP4Rev1 Server ready at Thu, 16 Mar 2000 19:03:15 -0800 Version: 5.5.1877.377.37 + */ + + // list of (name, version) regex pairs, first match has to be the value + protected static $servers = array( + array("/(Cyrus\sIMAP)4/", "/Cyrus\sIMAP4\sv((\d+)\.(\d+).(\d+))/"), + array("/(Courier.IMAP)/", null), + ); + + public function getServerName() + { + foreach(self::$servers as $server) + { + if(preg_match($server[0], $this->greeting, $matches)) + { + return $matches[1]; + } + } + + return false; + } + + public function getServerVersion() + { + foreach(self::$servers as $server) + { + if(preg_match($server[0], $this->greeting, $matches)) + { + if($server[1] == null) + return "Unknown"; + + if(preg_match($server[1], $this->greeting, $matches)) + { + return $matches[1]; + } + } + } + + return false; + } + + protected $greeting = null; + public function getGreeting() + { + return $this->greeting; + } + + protected $uri = null; + public function getURI() + { + return $this->uri; + } + + public function openConnection($uri, $timeout = 10) + { + $this->resetClient(); + $this->socket = $this->socket = fsockopen($this->uri = $uri, null, $errno, $errstr); + if(!$this->socket) + throw new Exception('Could not open Socket for IMAP connection: "'.$errstr.'"', $errno); + $this->state = self::STATE_GREETING; + $this->greeting = fgets($this->socket, 1024); + + if (sfConfig::get('sf_logging_enabled')) + { + sfContext::getInstance()->getLogger()->info("{IMAPClient} Greeting: ".trim($this->greeting)); + } + + $this->state = self::STATE_UNAUTH; + + return true; + } + + public function closeConnection() + { + if($this->socket) + { + if(!$this->logout()) + throw new Exception("Logout error."); + fclose($this->socket); + } + $this->resetClient(); + return true; + } + + protected function resetClient() + { + $this->state = self::STATE_GREETING; + $this->capabilities = null; + $this->hierarchydelimiter = null; + } + + protected function sendCommand($tag, $cmd, $args = "") + { + // check if we got a connection + if(!$this->socket) + throw new Exception('Unable to execute "'.$cmd.'" command: Not connected to a server.'); + + if(is_array($args)) + { + $args = " \"" . implode("\" \"", $args) . "\""; + } + + if (sfConfig::get('sf_logging_enabled')) + { + sfContext::getInstance()->getLogger()->info("{IMAPClient} Command: ".$tag." ".$cmd.$args); + } + + //LogEntryPeer::log("{IMAPClient} Command: ".$tag." ".$cmd.$args, LogEntry::PRIO_DEBUG); + + // send command + fputs($this->socket, $tag." ".$cmd.$args."\n"); + + // read response + $response = array(); + do + { + $line = fgets($this->socket, 1024); + $response[] = $line; + + if (sfConfig::get('sf_logging_enabled')) + { + sfContext::getInstance()->getLogger()->info("{IMAPClient} Line: \"".trim($line)."\""); + } + //LogEntryPeer::log("{IMAPClient} Line: \"".trim($line)."\"", LogEntry::PRIO_DEBUG); + } + while(self::getTag($line) != $tag && !feof($this->socket)); + + return $response; + } + + // PARSER API + protected static $tagcounter = 0; + protected static function generateTag() + { + $pattern = "0123456789". + "abcdefghij". + "klmnopqrst". + "uvwxyz"; + + if(self::$tagcounter==0) + self::$tagcounter = rand(0,999999); + + $s = ""; + $r = self::$tagcounter++; + do + { + $m = $r % 36; + $s = $pattern{$m} . $s; + } + while(($r = ($r-$m) / 36) > 0); + return sprintf("%04s", $s); + } + + protected static function getTag($line) + { + return self::getResponseData($line, 0); + } + + protected static function getResponseData($line, $index = 0) + { + $tokens = explode(" ", $line); + return $tokens[$index]; + } + + protected static function getResultStatus($tag, $response) + { + if(is_array($response)) + { + foreach($response as $line) + { + if(self::getTag($line) == $tag) + { + return self::getResponseData($line, 1); + } + } + } + + return null; + } + + protected function runCommandAndGetResult($command, $arguments = "") + { + $tag = self::generateTag(); + $response = $this->sendCommand($tag, $command, $arguments); + return self::getResultStatus($tag, $response); + } + + // IMAP API + + // RFC 3501 - IMAP4rev1 + // RFC 1730 - IMAP4 + public function login($user, $password) + { + $result = $this->runCommandAndGetResult("login", array($user, $password)); + if($result == self::RESULT_OK) + $this->state = self::STATE_AUTH; + + return ($result == self::RESULT_OK); + } + + public function logout() + { + $result = $this->runCommandAndGetResult("logout"); + if($result == self::RESULT_OK) + $this->state = self::STATE_UNAUTH; + + return ($result == self::RESULT_OK); + } + + public function noop() + { + $result = $this->runCommandAndGetResult("noop"); + return ($result == self::RESULT_OK); + } + + protected $hierarchydelimiter = null; + + public function getHierarchyDelimiter() + { + if($this->hierarchydelimiter != null) + return $this->hierarchydelimiter; + + if($info = $this->getlist('', '')) + { + $this->hierarchydelimiter = $info[0]['delimiter']; + return $this->hierarchydelimiter; + } + + return $info; + } + + // API break as "list" is PHP keyword... + public function getlist($reference = '', $mailboxname = '*') + { + $tag = self::generateTag(); + $response = $this->sendCommand($tag, "list", array($reference, $mailboxname)); + $result = self::getResultStatus($tag, $response); + + if($result == self::RESULT_OK) + { + // unserialize response + $list = array(); + + foreach($response as $line) + { + if(preg_match('/\*\sLIST\s\((.*)\)\s\"(.*?)\"\s\"(.*?)\"/', $line, $matches)) + { + $list[] = array('attributes' => $matches[1], + 'delimiter' => $matches[2], + 'name' => $matches[3] + ); + } + } + + return $list; + } + + return false; + } + + protected $capabilities = null; + + public function hasCapability($id) + { + if($this->capabilities == null) + $this->capability(); + + foreach($this->capabilities as $capability) + { + if($id == $capability) + return true; + } + return false; + } + + public function capability() + { + // cache this call + if($this->capabilities) + return $this->capabilities; + + $tag = self::generateTag(); + $response = $this->sendCommand($tag, "capability"); + $result = self::getResultStatus($tag, $response); + + if($result == self::RESULT_OK) + { + foreach($response as $line) + { + if(preg_match('/\*\sCAPABILITY\s(.*?)$/i', $line, $matches)) + { + $this->capabilities = explode(" ", $matches[1]); + return $this->capabilities; + } + } + } + + return false; + } + + public function create($name) + { + $result = $this->runCommandAndGetResult("create", array($name)); + return ($result == self::RESULT_OK); + } + + public function delete($name) + { + $result = $this->runCommandAndGetResult("delete", array($name)); + return ($result == self::RESULT_OK); + } + + public function rename($name, $newname) + { + $result = $this->runCommandAndGetResult("rename", array($name, $newname)); + return ($result == self::RESULT_OK); + } + + // RFC 2087 - QUOTA (Extension) + const QUOTA_TYPE_STORAGE = "STORAGE"; + const QUOTA_TYPE_MESSAGE = "MESSAGE"; + + public function getquota($quotaroot) + { + $tag = self::generateTag(); + $response = $this->sendCommand($tag, "getquota", array($quotaroot)); + $result = self::getResultStatus($tag, $response); + + if($result == self::RESULT_OK) + { + foreach($response as $line) + { + if(preg_match('/\*\sQUOTA\s'.$quotaroot.'\s\((\w)*\s(\d+)\s(\d+)\)/i', $line, $matches)) + { + return array( + 'resource' => $matches[1], + 'current' => $matches[2], + 'max' => $matches[3], + ); + } + } + } + + // OK -> not set, NO -> not set + if($result != self::RESULT_BAD) + { + return array( + 'resource' => null, + 'current' => null, + 'max' => null + ); + } + + return false; + } + + public function setquota($quotaroot, $quota = null, $resource = self::QUOTA_TYPE_STORAGE) + { + $tag = self::generateTag(); + $args = ' "'.$quotaroot.'" ('; + if($quota == 0 || $quota == null) + $args .= ')'; + else + $args .= $resource.' '.intval($quota).')'; + $response = $this->sendCommand($tag, "setquota", $args); + $result = self::getResultStatus($tag, $response); + + return ($result == self::RESULT_OK); + } + + // RFC 4314 - ACL (Extension) + const ACL_NONE = ''; + const ACL_LOOKUP = 'l'; + const ACL_READ = 'r'; + const ACL_SEEN = 's'; + const ACL_WRITE = 'w'; + const ACL_INSERT = 'i'; + const ACL_POST = 'p'; + + const ACL_CREATE = 'c'; // obsolete/depreciated + const ACL_DELETE = 'd'; // obsolete/depreciated + + const ACL_ADMIN = 'a'; + + const ACL_CREATEMB = 'k'; + const ACL_DELETEMB = 'x'; + const ACL_EXPUNGE = 'e'; + const ACL_DELETEMSGS = 't'; + + public function getAvailableACL() + { + $result = self::ACL_LOOKUP. + self::ACL_READ. + self::ACL_SEEN. + self::ACL_WRITE. + self::ACL_INSERT. + self::ACL_POST. + self::ACL_CREATE. + self::ACL_DELETE. + self::ACL_ADMIN; + + // add additional rights set in the capabilities + if($this->capabilities == null) + $this->capability(); + + foreach($this->capabilities as $capability) + { + if(preg_match('/RIGHTS=([kxte]*)/i', $capability, $matches)) + { + $result .= $matches[1]; + break; + } + } + + return $result; + } + + public function getacl($mailboxname) + { + $tag = self::generateTag(); + $response = $this->sendCommand($tag, "getacl", array($mailboxname)); + $result = self::getResultStatus($tag, $response); + + if($result == self::RESULT_OK) + { + foreach($response as $line) + { + // grab acl list + if(preg_match('/\*\sACL\s[^\s]*\s(.*)/', $line, $matches)) + { + // grab all acls + if(preg_match_all('/([^\s]*)\s(['.$this->getAvailableACL().']*)/', $matches[1], $matches)) + { + return array_combine($matches[1], $matches[2]); + } + } + } + } + + return false; + } + + public function setacl($mailboxname, $identifier, $aclmodification) + { + $result = $this->runCommandAndGetResult("setacl", array($mailboxname, $identifier, $aclmodification)); + return ($result == self::RESULT_OK); + } + + public function deleteacl($mailboxname, $identifier) + { + $result = $this->runCommandAndGetResult("deleteacl", array($mailboxname, $identifier)); + return ($result == self::RESULT_OK); + } +} + +?> diff --git a/apps/admin/lib/imap/IMAPManager.php b/apps/admin/lib/imap/IMAPManager.php new file mode 100644 index 0000000..0cac78a --- /dev/null +++ b/apps/admin/lib/imap/IMAPManager.php @@ -0,0 +1,48 @@ +<?php + +class IMAPManager +{ + protected static $adminclient = null; + public static function getAdminConnection() + { + // exists + if(self::$adminclient != null) + return self::$adminclient; + + // create new instance + $server_settings = sfConfig::get('app_server_default'); + $imap_settings = $server_settings['imap']; + self::$adminclient = new $imap_settings['client']; + + // login + try + { + self::$adminclient->openConnection( + $imap_settings['host'].":". + $imap_settings['port'] + ); + + $success = self::$adminclient->login( + $imap_settings['admin'], + $imap_settings['pass'] + ); + + if(!$success) + throw new Exception("Failed to authenticate on IMAP server."); + + } catch (Exception $e) { + LogEntryPeer::log($e->getMessage(), LogEntry::PRIO_ALERT); + } + + return self::$adminclient; + } + + public static function getAdminUsername() + { + $server_settings = sfConfig::get('app_server_default'); + $imap_settings = $server_settings['imap']; + return $imap_settings['admin']; + } +} + +?> diff --git a/apps/admin/lib/imap/IMAPServerInformation.php b/apps/admin/lib/imap/IMAPServerInformation.php new file mode 100644 index 0000000..e185bae --- /dev/null +++ b/apps/admin/lib/imap/IMAPServerInformation.php @@ -0,0 +1,63 @@ +<?php + +class IMAPServerInformation +{ + protected $imap = null; + + public function __construct() + { + $this->imap = IMAPManager::getAdminConnection(); + } + + public function getGreeting() + { + return substr($this->imap->getGreeting(), 5); + } + + public function getServerName() + { + return $this->imap->getServerName(); + } + + public function getServerVersion() + { + return $this->imap->getServerVersion(); + } + + public function hasCapability($name) + { + return $this->imap->hasCapability($name); + } + + public function getCapabilties() + { + if(!($c = $this->imap->capability())) + $c = array(); + return $c; + } + + public function getHierarchyDelimiter() + { + return $this->imap->getHierarchyDelimiter(); + } + + public function getAvailableACL() + { + if(!$this->imap->hasCapability('ACL')) + return false; + + return $this->imap->getAvailableACL(); + } + + public function getHost() + { + return substr($this->imap->getURI(), 0, strpos($this->imap->getURI(), ":")); + } + + public function getPort() + { + return substr($this->imap->getURI(), strpos($this->imap->getURI(), ":")+1); + } +} + +?> diff --git a/apps/admin/lib/myChangeNicknameValidator.php b/apps/admin/lib/myChangeNicknameValidator.php new file mode 100644 index 0000000..e8dfdb1 --- /dev/null +++ b/apps/admin/lib/myChangeNicknameValidator.php @@ -0,0 +1,43 @@ +<?php + +class myChangeNicknameValidator extends sfValidator +{ + public function initialize($context, $parameters = null) + { + // initialize parent + parent::initialize($context); + + // set defaults + $this->setParameter('change_error', 'Invalid input'); + + $this->getParameterHolder()->add($parameters); + + return true; + } + + public function execute(&$value, &$error) + { + $current_nickname = $this->getContext()->getUser()->getNickname(); + + $new_nickname = $value; + + // changed the nickname? + if($new_nickname == $current_nickname) + return true; + + $c = new Criteria(); + $c->add(UserPeer::NICKNAME, $new_nickname); + $user = UserPeer::doSelectOne($c); + + // nickname exists? + if($user) + { + $error = $this->getParameter('change_error'); + return false; + } + + return true; + } +} + +?> diff --git a/apps/admin/lib/myDenyStringValidator.php b/apps/admin/lib/myDenyStringValidator.php new file mode 100644 index 0000000..d817ea9 --- /dev/null +++ b/apps/admin/lib/myDenyStringValidator.php @@ -0,0 +1,38 @@ +<?php + +class myDenyStringValidator extends sfValidator +{ + public function initialize($context, $parameters = null) + { + // initialize parent + parent::initialize($context); + + // set defaults + $this->setParameter('values_error', 'Invalid input'); + + $this->getParameterHolder()->add($parameters); + + return true; + } + + public function execute(&$value, &$error) + { + $values = $this->getParameter('values'); + + if(!is_array($values)) + return true; + + foreach($values as $check) + { + if($check==$value) + { + $error = $this->getParameter('values_error'); + return false; + } + } + + return true; + } +} + +?> diff --git a/apps/admin/lib/myLoginValidator.php b/apps/admin/lib/myLoginValidator.php new file mode 100644 index 0000000..03890aa --- /dev/null +++ b/apps/admin/lib/myLoginValidator.php @@ -0,0 +1,45 @@ +<?php + +class myLoginValidator extends sfValidator +{ + public function initialize($context, $parameters = null) + { + // initialize parent + parent::initialize($context); + + // set defaults + $this->setParameter('login_error', 'Invalid input'); + + $this->getParameterHolder()->add($parameters); + + return true; + } + + public function execute(&$value, &$error) + { + $password_param = $this->getParameter('password'); + $password = $this->getContext()->getRequest()->getParameter($password_param); + + $login = $value; + + $c = new Criteria(); + $c->add(UserPeer::NICKNAME, $login); + $user = UserPeer::doSelectOne($c); + + // nickname exists? + if ($user) + { + // password is OK? + if (sha1($user->getSalt().$password) == $user->getSha1Password()) + { + $this->getContext()->getUser()->signIn($user); + return true; + } + } + + $error = $this->getParameter('login_error'); + return false; + } +} + +?> diff --git a/apps/admin/lib/myUser.class.php b/apps/admin/lib/myUser.class.php new file mode 100644 index 0000000..2f67e51 --- /dev/null +++ b/apps/admin/lib/myUser.class.php @@ -0,0 +1,83 @@ +<?php + +class myUser extends sfBasicSecurityUser +{ + public function signIn($user) + { + $this->setAuthenticated(true); + + // TODO: set credentials + $this->addCredential($user->getRole()->getCredentials()); + + // set session attributes + $this->updateUserAttributes($user); + + $this->setResultsPerPage(sfConfig::get("app_pagination_results_per_page")); + + LogEntryPeer::log("User logged in.", LogEntry::PRIO_INFO); + + $user->setLastlogin(time()); + $user->save(); + } + + public function updateUserAttributes($user) + { + $this->setAttribute("nickname", $user->getNickname(), "user"); + $this->setAttribute("role", $user->getRole()->getName(), "user"); + $this->setAttribute("role_id", $user->getRole()->getId(), "user"); + $this->setAttribute("user_id", $user->getId(), "user"); + $this->setAttribute("lastlogin", $user->getLastLogin(), "user"); + } + + public function signOut($user) + { + LogEntryPeer::log("User logged out.", LogEntry::PRIO_INFO); + + $this->setAuthenticated(false); + $this->clearCredentials(); + $this->getAttributeHolder()->removeNamespace("user"); + $this->getAttributeHolder()->removeNamespace("pager"); + } + + public function getResultsPerPage() + { + return $this->getAttribute("max_per_page", sfConfig::get("app_pager_max_per_page"), "pager"); + } + + + public function setResultsPerPage($count) + { + $this->setAttribute("max_per_page", $count, "pager"); + } + + public function getDomainPermissions($c = null) + { + $user = UserPeer::retrieveByPK($this->getId()); + return $user->getDomainPermissions($c); + } + + public function getId() + { + return $this->getAttribute("user_id", '', "user"); + } + + public function getLastLogin() + { + return $this->getAttribute("lastlogin", '', "user"); + } + + public function getRoleId() + { + return $this->getAttribute("role_id", '', "user"); + } + + public function getRoleName() + { + return $this->getAttribute("role", '', "user"); + } + + public function getNickname() + { + return $this->getAttribute("nickname", '', "user"); + } +} diff --git a/apps/admin/modules/address/actions/actions.class.php b/apps/admin/modules/address/actions/actions.class.php new file mode 100644 index 0000000..d042fbf --- /dev/null +++ b/apps/admin/modules/address/actions/actions.class.php @@ -0,0 +1,165 @@ +<?php + +/** + * address actions. + * + * @package mailadmin + * @subpackage address + * @author Your name here + * @version SVN: $Id: actions.class.php 2288 2006-10-02 15:22:13Z fabien $ + */ +class addressActions extends autoaddressActions +{ + public function executeList() + { + // pageination + if($this->hasRequestParameter("max_per_page")) + $this->getUser()->setResultsPerPage($this->getRequestParameter("max_per_page")); + + return parent::executeList(); + } + + public function executeCreate() + { + $this->setTemplate("edit"); + $result = $this->executeEdit(); + + if($this->getRequest()->getMethod() == sfRequest::GET) + { + if(!$this->hasRequestParameter("id")) + { + $this->updateAddressFromRequest(); + } + $this->address->setActive(true); + $this->address->setSaveInMailbox(true); + } + + return $result; + } + + public function handleErrorCreate() + { + $this->setTemplate("edit"); + return $this->handleErrorEdit(); + } + + public function validateCreate() + { + return $this->validateEdit(); + } + + public function validateEdit() + { + $i18n = sfI18N::getInstance(); + + if($this->getRequest()->getMethod() == sfRequest::GET) + return true; + + $newaddress = $this->getRequestParameter('address'); + if($newaddress["domain_id"]=='') + { + $this->getRequest()->setError('address{alias}', 'A domain must be selected'); + return false; + } + + $address = new Address(); + + if($this->getRequest()->hasParameter('id')) + $address = AddressPeer::retrieveByPk($this->getRequestParameter('id')); + + // if we got different values than the current record already has + if($this->getActionName()=="create" || + $address->getLocalpart() != $newaddress["localpart"] || + $address->getDomainId() != $newaddress["domain_id"] + ) + { + // check if localpart@domain is already used + $c = new Criteria(); + $c->add(AddressPeer::LOCALPART, $newaddress["localpart"]); + $c->add(AddressPeer::DOMAIN_ID, $newaddress["domain_id"]); + $checkaddress = AddressPeer::doSelectOne($c); + if($checkaddress) + { + $this->getRequest()->setError('address{alias}', $i18n->__('The address "%1%" already exists', array("%1%"=>$checkaddress))); + return false; + } + } + + // check if either save to mailbox option or destination is set to satisfy message routing + if(!isset($newaddress["save_in_mailbox"]) && $newaddress["destination"]=='') + { + $this->getRequest()->setError('address{save_in_mailbox}', 'If messages are not saved in the mailbox, the forward destination has to be set'); + $this->getRequest()->setError('address{destination}', 'Destination can not be empty if the message is not saved in the mailbox'); + return false; + + } + + // verify destination list + $ev = new sfEmailValidator(); + $destinations = Address::getDestinationAsArray($newaddress["destination"]); + foreach($destinations as $dest) + { + if($dest=='') + continue; + + // check email + if(strpos($dest, "@") !== false) + { + $error = ''; + $ev->initialize($this->getContext(), array( + 'email_error' => $i18n->__('Invalid E-Mail address "%1%"', array("%1%" => $dest)) + )); + + if(!$ev->execute($dest, $error)) + { + $this->getRequest()->setError('address{destination}', $error); + return false; + } + } + else // check if mailbox name is valid + { + // superadmin has all freedom + if($this->getUser()->hasCredential("superadmin")) + continue; + + $c = new Criteria(); + $c->add(MailboxPeer::NAME, $dest); + $mailbox = MailboxPeer::doSelectOne($c); + if(!$mailbox) + { + // no such target + $this->getRequest()->setError('address{destination}', $i18n->__('Mailbox "%1%" does not exist', array("%1%" => $dest))); + return false; + } + + // check permissions + $c = new Criteria(); + $c->add(DomainPermissionPeer::DOMAIN_ID, $mailbox->getDomainId()); + $permissions = $this->getUser()->getDomainPermissions($c); + if(!$permissions) + { + $this->getRequest()->setError('address{destination}', $i18n->__('No permissions to use Mailbox "%1%" as destination', array("%1%" => $dest))); + return false; + } + } + } + + return true; + } + + protected function updateAddressFromRequest() + { + $address = $this->getRequestParameter('address'); + + if (isset($address['localpart'])) + { + $this->address->setLocalpart($address['localpart']); + } + if (isset($address['domain_id'])) + { + $this->address->setDomainId($address['domain_id']); + } + + return parent::updateAddressFromRequest(); + } +} diff --git a/apps/admin/modules/address/config/generator.yml b/apps/admin/modules/address/config/generator.yml new file mode 100644 index 0000000..2bd2e44 --- /dev/null +++ b/apps/admin/modules/address/config/generator.yml @@ -0,0 +1,48 @@ +generator: + class: sfPropelAdminGenerator + param: + model_class: Address + theme: mailadmin + + fields: + destination: { name: Destination } + mailbox_id: { name: Mailbox } + active: { name: Active } + + list: + peer_method: doSelectJoinAll + title: List of Addresses + display: [=_localpart, _domain_id, _destination, active, _mailbox_id] + filters: [alias, domain_id, active, mailbox_id, destination] + max_per_page: '$this->getUser()->getResultsPerPage("pager")' + sort: [mailbox_id, asc] + fields: + localpart: { name: Address, params: align=right } + domain_id: { params: align=left } + alias: { params: align=left } + destination: { params: align=left } + active: { params: align=center width=1% } + mailbox_id: { params: align=right } + object_actions: + edit: { name: Edit Address, action: edit, icon: edit.gif } + delete: { name: Delete Address, action: delete, icon: trash.gif, params: confirm=Are you sure? } + actions: {} + + create: + title: Create New Address + + edit: + title: 'Editing Address %%alias%%' + display: + 'Address': [_alias, active, mailbox_id] + 'Destination': [save_in_mailbox, destination] + fields: + mailbox_id: { name: For Mailbox, help: 'The primary mailbox for this address' } + alias: { name: Address, help: 'Leave blank if this is a catch all address' } + save_in_mailbox: { name: Save to Mailbox, type: checkbox_tag, help: 'Incoming messages are saved, then forwarded' } + destination: { name: Forward to these Destinations, params: size=51x8, help: 'E-Mail addresses and/or mailbox names, one per line or comma-seperated' } + active: { name: Active, help: Inactive addresses are not routed } + actions: + _save_and_list: { name: Save } + _save_and_add: { name: 'Save, then create new one' } + _list: { name: Cancel } diff --git a/apps/admin/modules/address/templates/_alias.php b/apps/admin/modules/address/templates/_alias.php new file mode 100644 index 0000000..e6550c1 --- /dev/null +++ b/apps/admin/modules/address/templates/_alias.php @@ -0,0 +1,9 @@ +<?php use_helper("Object") ?><?php $value = object_input_tag($address, 'getLocalpart', array ( + 'size' => 25, + 'control_name' => 'address[localpart]', + 'style' => 'text-align:right', +)); echo $value ? $value : ' ' ?> @ <?php $value = object_select_tag($address, 'getDomainId', array ( + 'related_class' => 'Domain', + 'control_name' => 'address[domain_id]', + 'include_blank' => true, +)); echo $value ? $value : ' ' ?> diff --git a/apps/admin/modules/address/templates/_destination.php b/apps/admin/modules/address/templates/_destination.php new file mode 100644 index 0000000..f01676c --- /dev/null +++ b/apps/admin/modules/address/templates/_destination.php @@ -0,0 +1,23 @@ +<?php use_helper('I18N','Javascript'); ?> +<?php $list = Address::getDestinationAsArray($address->getDestination()); + if($address->getSaveInMailbox()) + $list = array_merge(array($address->getMailbox()->getName()), $list); +?> +<div class="slidelist"> +<?php if(count($list) > sfConfig::get('app_address_dest_collapse_count')): ?> + +<?php echo link_to_function(__("Multiple (%1% entries)", array('%1%' => count($list))), visual_effect( +'toggle_slide', 'addresslist_'.$address->getId())) ?> +<div id="addresslist_<?php echo $address->getId() ?>" style="display:none"> +<?php endif; ?> + +<ul> +<?php foreach($list as $destination): ?> +<li><?php echo ($destination==$address->getMailbox()->getName()? __("Mailbox"): $destination) ?></li> +<?php endforeach; ?> +</ul> + +<?php if(count($list) > 1): ?> +</div> +<?php endif; ?> +</div> diff --git a/apps/admin/modules/address/templates/_domain_id.php b/apps/admin/modules/address/templates/_domain_id.php new file mode 100644 index 0000000..bb51b3d --- /dev/null +++ b/apps/admin/modules/address/templates/_domain_id.php @@ -0,0 +1 @@ +@<?php echo $address->getDomain() ?> diff --git a/apps/admin/modules/address/templates/_localpart.php b/apps/admin/modules/address/templates/_localpart.php new file mode 100644 index 0000000..e01fe5d --- /dev/null +++ b/apps/admin/modules/address/templates/_localpart.php @@ -0,0 +1 @@ +<?php echo ($address->isCatchAll() ? "*": $address->getLocalpart() ) ?> diff --git a/apps/admin/modules/address/templates/_mailbox_id.php b/apps/admin/modules/address/templates/_mailbox_id.php new file mode 100644 index 0000000..0ab885b --- /dev/null +++ b/apps/admin/modules/address/templates/_mailbox_id.php @@ -0,0 +1 @@ +<?php echo $address->getMailbox() ?> diff --git a/apps/admin/modules/address/validate/create.yml b/apps/admin/modules/address/validate/create.yml new file mode 100644 index 0000000..a55efed --- /dev/null +++ b/apps/admin/modules/address/validate/create.yml @@ -0,0 +1,10 @@ +fillin: + enabled: true + +fields: + address{domain_id}: + required: + msg: A domain has to be selected + address{mailbox_id}: + required: + msg: A primary mailbox has to be selected diff --git a/apps/admin/modules/address/validate/edit.yml b/apps/admin/modules/address/validate/edit.yml new file mode 100644 index 0000000..a55efed --- /dev/null +++ b/apps/admin/modules/address/validate/edit.yml @@ -0,0 +1,10 @@ +fillin: + enabled: true + +fields: + address{domain_id}: + required: + msg: A domain has to be selected + address{mailbox_id}: + required: + msg: A primary mailbox has to be selected diff --git a/apps/admin/modules/content/actions/actions.class.php b/apps/admin/modules/content/actions/actions.class.php new file mode 100644 index 0000000..bbc9d08 --- /dev/null +++ b/apps/admin/modules/content/actions/actions.class.php @@ -0,0 +1,18 @@ +<?php + +/** + * content actions. + * + * @package mailadmin + * @subpackage content + * @author Your name here + * @version SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $ + */ +class contentActions extends sfActions +{ + public function executeSecure() + { + LogEntryPeer::log("Attempt to access a secured action without proper credentials.", LogEntry::PRIO_WARNING); + $this->redirect($this->getRequest()->getReferer(), '@homepage'); + } +} diff --git a/apps/admin/modules/domain/actions/actions.class.php b/apps/admin/modules/domain/actions/actions.class.php new file mode 100644 index 0000000..badbf03 --- /dev/null +++ b/apps/admin/modules/domain/actions/actions.class.php @@ -0,0 +1,47 @@ +<?php + +/** + * domain actions. + * + * @package mailadmin + * @subpackage domain + * @author Your name here + * @version SVN: $Id: actions.class.php 2288 2006-10-02 15:22:13Z fabien $ + */ +class domainActions extends autodomainActions +{ + public function executeList() + { + // pageination + if($this->hasRequestParameter("max_per_page")) + $this->getUser()->setResultsPerPage($this->getRequestParameter("max_per_page")); + + return parent::executeList(); + } + + public function executeCreate() + { + // populate preset values + $this->getRequest()->setParameter('domain[creator_id]', $this->getUser()->getId()); + + $this->setTemplate("edit"); + return $this->executeEdit(); + } + + public function handleErrorCreate() + { + $this->setTemplate("edit"); + return $this->handleErrorEdit(); + } + + public function executeCreateMailbox() + { + $domain = DomainPeer::retrieveByPk($this->getRequestParameter('id')); + $this->redirect("mailbox/create?mailbox[domain_id]=".$domain->getId()."&mailbox[name]=".sprintf("%s%d", $domain->getMailboxPrefix(), $domain->getMailboxCount()+1)."&mailbox[max_quota]=".$domain->getDefaultMailboxQuota() ); + } + + public function executeViewMailboxes() + { + $this->redirect("mailbox/list?filter=filter&filters[domain_id]=".$this->getRequestParameter('id')); + } +} diff --git a/apps/admin/modules/domain/config/generator.yml b/apps/admin/modules/domain/config/generator.yml new file mode 100644 index 0000000..df971b3 --- /dev/null +++ b/apps/admin/modules/domain/config/generator.yml @@ -0,0 +1,53 @@ +generator: + class: sfPropelAdminGenerator + param: + model_class: Domain + theme: mailadmin + + fields: + name: { name: Domain } + mailbox_prefix: { name: Mailbox Prefix } + max_mailbox_count: { name: Max Mailbox Count } + quota: { name: Quota } + creator: { name: Created by } + + list: + title: List of Domains + display: [=name, user, mailbox_prefix, _max_mailbox_count, _quota, _default_mailbox_quota] + filters: [name, mailbox_prefix, max_mailbox_count, quota, default_mailbox_quota] + max_per_page: '$this->getUser()->getResultsPerPage("pager")' + sort: [name, asc] + fields: + name: { params: align=left } + mailbox_prefix: { params: align=left } + user: { name: Created By, credentials: [[superadmin]] } + max_mailbox_count: { params: align=right } + mailbox_count: { params: align=right } + quota: { params: align=right } + default_mailbox_quota: { name: Default Mailbox Quota, params: align=right } + object_actions: + viewmailboxes: { name: View Mailboxes, action: viewMailboxes, icon: mail.gif } + createmailbox: { name: Create New Mailbox, action: createMailbox, icon: mail-new.gif } + edit: { name: Edit Domain, action: edit, icon: edit.gif, credentials: [[superadmin, domainmaster]] } + delete: { name: Delete Domain, action: delete, icon: trash.gif, credentials: [[superadmin, domainmaster]], params: confirm=Are you sure? } + actions: {} + + create: + title: Create New Domain + + edit: + title: 'Editing Domain %%name%%' + display: + 'General Settings': [name, mailbox_prefix] + 'Limits': [max_mailbox_count, quota, default_mailbox_quota] + fields: + name: { name: Domain Name, params: size=50 } + mailbox_prefix: { name: Prefix for new Mailboxes, params: size=50 onfocus='updatePrefixFromDomainName(this);' } + max_mailbox_count: { name: Maximum Number of Mailboxes, help: '0 = No Limit', params: size=50 } + quota: { name: Default Quota in kb, help: '0 = No Limit', params: size=50 } + default_mailbox_quota: { name: Quota for Domain in kb, help: '0 = No Limit', params: size=50 } + actions: + _save_and_list: { name: Save } + _save_and_add: { name: 'Save, then create new one' } + _list: { name: Cancel } + diff --git a/apps/admin/modules/domain/config/security.yml b/apps/admin/modules/domain/config/security.yml new file mode 100644 index 0000000..2431ebf --- /dev/null +++ b/apps/admin/modules/domain/config/security.yml @@ -0,0 +1,11 @@ +create: + is_secure: on + credentials: [[superadmin, domainmaster]] + +edit: + is_secure: on + credentials: [[superadmin, domainmaster]] + +all: + is_secure: on + diff --git a/apps/admin/modules/domain/templates/_default_mailbox_quota.php b/apps/admin/modules/domain/templates/_default_mailbox_quota.php new file mode 100644 index 0000000..272ad83 --- /dev/null +++ b/apps/admin/modules/domain/templates/_default_mailbox_quota.php @@ -0,0 +1 @@ +<?php use_helper("Files") ?><?php echo ($domain->getDefaultMailboxQuota()==0 ? "Unlimited" : format_bytes($domain->getDefaultMailboxQuota()*1000)) ?> diff --git a/apps/admin/modules/domain/templates/_edit_header.php b/apps/admin/modules/domain/templates/_edit_header.php new file mode 100644 index 0000000..fed004a --- /dev/null +++ b/apps/admin/modules/domain/templates/_edit_header.php @@ -0,0 +1,13 @@ +<?php use_helper("Javascript") ?> + +<?php + use_javascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype'); + + echo javascript_tag(" + function updatePrefixFromDomainName(field) { + v = $('domain_name').value; + if(field.value!='') return true; + field.value = v.substring(0, v.indexOf('.')); + return true; + }"); +?> diff --git a/apps/admin/modules/domain/templates/_max_mailbox_count.php b/apps/admin/modules/domain/templates/_max_mailbox_count.php new file mode 100644 index 0000000..8b7a70b --- /dev/null +++ b/apps/admin/modules/domain/templates/_max_mailbox_count.php @@ -0,0 +1 @@ +<?php echo $domain->getMailboxCount() ?> / <?php echo ($domain->getMaxMailboxCount()==0 ? "Unlimited": $domain->getMaxMailboxCount()) ?> diff --git a/apps/admin/modules/domain/templates/_quota.php b/apps/admin/modules/domain/templates/_quota.php new file mode 100644 index 0000000..0b36b22 --- /dev/null +++ b/apps/admin/modules/domain/templates/_quota.php @@ -0,0 +1 @@ +<?php use_helper("Files") ?><?php echo format_bytes($domain->getUsedQuota()*1000) ?> / <?php echo ($domain->getQuota()==0 ? "Unlimited" : format_bytes($domain->getQuota()*1000)) ?> diff --git a/apps/admin/modules/domain/validate/create.yml b/apps/admin/modules/domain/validate/create.yml new file mode 100644 index 0000000..c8183c2 --- /dev/null +++ b/apps/admin/modules/domain/validate/create.yml @@ -0,0 +1,46 @@ +fillin: + enabled: true + +validators: + myStringValidator: + class: sfStringValidator + param: + min: 2 + min_error: This field is too short (2 characters minimum) + max: 100 + max_error: This field is too long (100 characters maximum) + +fields: + domain{name}: + required: + msg: The Domain Name is required + myStringValidator: + sfRegexValidator: + match:..........Yes + match_error: 'The name must be in the form: example.org' + pattern: /[^.]+\.[^.]+$/si + sfPropelUniqueValidator: + class: Domain + column: name + unique_error: This domain already exists + domain{mailbox_prefix}: + required: + msg: The Mailbox Prefix is required + myStringValidator: + sfRegexValidator: + match: Yes + match_error: The prefix must only consist out of alphanumeric characters + pattern: /[A-z0-9]/si + sfPropelUniqueValidator: + class: Domain + column: mailbox_prefix + unique_error: This prefix already exists + domain{max_mailbox_count}: + required: + msg: The Mailbox Count is required + domain{quota}: + required: + msg: The Domain Quota is required + domain{default_mailbox_quota}: + required: + msg: The Mailbox Quota is required diff --git a/apps/admin/modules/domain/validate/edit.yml b/apps/admin/modules/domain/validate/edit.yml new file mode 100644 index 0000000..c8183c2 --- /dev/null +++ b/apps/admin/modules/domain/validate/edit.yml @@ -0,0 +1,46 @@ +fillin: + enabled: true + +validators: + myStringValidator: + class: sfStringValidator + param: + min: 2 + min_error: This field is too short (2 characters minimum) + max: 100 + max_error: This field is too long (100 characters maximum) + +fields: + domain{name}: + required: + msg: The Domain Name is required + myStringValidator: + sfRegexValidator: + match:..........Yes + match_error: 'The name must be in the form: example.org' + pattern: /[^.]+\.[^.]+$/si + sfPropelUniqueValidator: + class: Domain + column: name + unique_error: This domain already exists + domain{mailbox_prefix}: + required: + msg: The Mailbox Prefix is required + myStringValidator: + sfRegexValidator: + match: Yes + match_error: The prefix must only consist out of alphanumeric characters + pattern: /[A-z0-9]/si + sfPropelUniqueValidator: + class: Domain + column: mailbox_prefix + unique_error: This prefix already exists + domain{max_mailbox_count}: + required: + msg: The Mailbox Count is required + domain{quota}: + required: + msg: The Domain Quota is required + domain{default_mailbox_quota}: + required: + msg: The Mailbox Quota is required diff --git a/apps/admin/modules/log/actions/actions.class.php b/apps/admin/modules/log/actions/actions.class.php new file mode 100644 index 0000000..9eed7c7 --- /dev/null +++ b/apps/admin/modules/log/actions/actions.class.php @@ -0,0 +1,46 @@ +<?php + +/** + * log actions. + * + * @package mailadmin + * @subpackage log + * @author Your name here + * @version SVN: $Id: actions.class.php 2288 2006-10-02 15:22:13Z fabien $ + */ +class logActions extends autologActions +{ + public function executeList() + { + // pageination + if($this->hasRequestParameter("max_per_page")) + $this->getUser()->setResultsPerPage($this->getRequestParameter("max_per_page")); + + return parent::executeList(); + } + + public function executeClear() + { + if($this->getRequest()->getMethod() == sfRequest::POST) + { + if($this->getRequestParameter("commit")=="Yes") + { + LogEntryPeer::doDeleteAll(); + return $this->redirect("log", "list"); + } + + } + + return sfView::SUCCESS; + } + + public function executeCreate() + { + return $this->forward404(); + } + + public function executeEdit() + { + return $this->forward404(); + } +} diff --git a/apps/admin/modules/log/config/generator.yml b/apps/admin/modules/log/config/generator.yml new file mode 100644 index 0000000..553b1c2 --- /dev/null +++ b/apps/admin/modules/log/config/generator.yml @@ -0,0 +1,30 @@ +generator: + class: sfPropelAdminGenerator + param: + model_class: LogEntry + theme: mailadmin + + fields: + created_at: { name: Time } + user_id: { name: User } + host: { name: Host } + priority: { name: Type } + + list: + peer_method: doSelectJoinUser + title: Logs + display: [created_at, _priority, message, _user_id, host] + filters: [created_at, priority, message, user_id, host] + max_per_page: '$this->getUser()->getResultsPerPage("pager")' + sort: [created_at, desc] + fields: + created_at: { params: align=left center } + user_id: { params: align=left } + message: { params: align=left } + host: { params: align=left } + priority: { params: align=left } + object_actions: + delete: { name: Delete, action: delete, icon: trash.gif, params: confirm=Are you sure? } + actions: {} + + edit: {} diff --git a/apps/admin/modules/log/config/security.yml b/apps/admin/modules/log/config/security.yml new file mode 100644 index 0000000..60868c9 --- /dev/null +++ b/apps/admin/modules/log/config/security.yml @@ -0,0 +1,2 @@ +all: + credentials: [superadmin] diff --git a/apps/admin/modules/log/templates/_priority.php b/apps/admin/modules/log/templates/_priority.php new file mode 100644 index 0000000..2427ac7 --- /dev/null +++ b/apps/admin/modules/log/templates/_priority.php @@ -0,0 +1 @@ +<?php echo image_tag(($log_entry->getPriority()<3?"information.gif":($log_entry->getPriority()<4?"warning.gif":"error.gif")),"alt=[!] border=0") ?><?php echo $log_entry->getLevel() ?> diff --git a/apps/admin/modules/log/templates/_user_id.php b/apps/admin/modules/log/templates/_user_id.php new file mode 100644 index 0000000..737a1c7 --- /dev/null +++ b/apps/admin/modules/log/templates/_user_id.php @@ -0,0 +1 @@ +<?php echo ($log_entry->getUser() ? $log_entry->getUser(): "Anonymous") ?> diff --git a/apps/admin/modules/log/templates/clearSuccess.php b/apps/admin/modules/log/templates/clearSuccess.php new file mode 100644 index 0000000..83508eb --- /dev/null +++ b/apps/admin/modules/log/templates/clearSuccess.php @@ -0,0 +1,12 @@ + <div id="context"> + <?php echo use_helper("Asset", "Form", "Object", "Validation") ?> + <?php echo form_tag("log/clear")?> + <h1>Clear Log</h1> + + <hr size="1" /> + + <h2>Do you really want to remove all log entries?</h2> + + <div class="formaction"><?php echo submit_tag("Yes") ?><?php echo button_to("Cancel", "log/list") ?></div> + </form> + </div> diff --git a/apps/admin/modules/mailbox/actions/actions.class.php b/apps/admin/modules/mailbox/actions/actions.class.php new file mode 100644 index 0000000..566c69f --- /dev/null +++ b/apps/admin/modules/mailbox/actions/actions.class.php @@ -0,0 +1,56 @@ +<?php + +/** + * mailbox actions. + * + * @package mailadmin + * @subpackage mailbox + * @author Your name here + * @version SVN: $Id: actions.class.php 2288 2006-10-02 15:22:13Z fabien $ + */ +class mailboxActions extends automailboxActions +{ + public function executeList() + { + // pageination + if($this->hasRequestParameter("max_per_page")) + $this->getUser()->setResultsPerPage($this->getRequestParameter("max_per_page")); + + return parent::executeList(); + } + + public function executeCreate() + { + $this->setTemplate("edit"); + $result = $this->executeEdit(); + + if($this->getRequest()->getMethod() == sfRequest::GET) + { + if(!$this->hasRequestParameter("id")) + { + $this->updateMailboxFromRequest(); + } + + // reset is needed as updateMailboxFromRequest() deactivates + $this->mailbox->setActive(true); + } + return $result; + } + + public function handleErrorCreate() + { + $this->setTemplate("edit"); + return $this->handleErrorEdit(); + } + + public function executeCreateAddress() + { + $mailbox = MailboxPeer::retrieveByPk($this->getRequestParameter('id')); + $this->redirect("address/create?address[mailbox_id]=".$this->getRequestParameter('id')."&address[domain_id]=".$mailbox->getDomainId()); + } + + public function executeViewAddresses() + { + $this->redirect("address/list?filter=filter&filters[mailbox_id]=".$this->getRequestParameter('id')); + } +} diff --git a/apps/admin/modules/mailbox/config/generator.yml b/apps/admin/modules/mailbox/config/generator.yml new file mode 100644 index 0000000..9c119ea --- /dev/null +++ b/apps/admin/modules/mailbox/config/generator.yml @@ -0,0 +1,56 @@ +generator: + class: sfPropelAdminGenerator + param: + model_class: Mailbox + theme: mailadmin + + fields: + domain: { name: Domain } + domain_id: { name: Domain } + name { name: Username } + max_quota: { name: Quota } + max_address_count: { name: Maximum Addresses } + last_login: { name: Last Login } + + list: + peer_method: doSelectJoinDomain + title: List of Mailboxes + display: [=name, _domain_id, _max_quota, _max_address_count, active, _last_login] + filters: [name, domain_id, max_quota, max_address_count, active, last_login] + max_per_page: '$this->getUser()->getResultsPerPage("pager")' + sort: [domain_id, asc] + fields: + name: { params: align=right } + domain_id: { params: align=left } + max_quota: { params: align=right } + max_address_count: { params: align=right } + active: { params: align=center width=1% } + last_login: { params: align=right } + object_actions: + viewaddresses: { name: View Addresses, action: viewAddresses, icon: address.gif } + createaddress: { name: Create New Address, action: createAddress, icon: address-new.gif } + edit: { name: Edit Mailbox, action: edit, icon: edit.gif } + delete: { name: Delete Mailbox, action: delete, icon: trash.gif, params: confirm=This will also remove all addresses for this mailbox. Are you sure? } + actions: {} + + create: + title: Create New Mailbox + + edit: + title: Editing Mailbox %%name%% + display: + 'General Settings': [name, _password, _new_password, domain_id, active] + 'Limits': [max_quota, max_address_count] + fields: + name: { name: Username, params: size=50 } + password: { name: Password, params: size=50, only_for: create } + new_password: { name: New Password, help: 'Enter a password to change it, leave the field blank to keep the current one', params: size=50, only_for: edit } + domain_id: { name: For Domain } + active: { name: Enable Login, help: 'Inactive mailboxes receive mail, however users are unable to login' } + max_quota: { name: Maximum Storage Space in kb, help: '0 = No Limit', params: size=50 } + max_address_count: { name: Maximum Number of Addresses, help: '0 = No Limit', params: size=50 } + actions: + _save_and_list: { name: Save } + _save_and_add: { name: 'Save, then create new one' } + _list: { name: Cancel } + diff --git a/apps/admin/modules/mailbox/templates/_domain_id.php b/apps/admin/modules/mailbox/templates/_domain_id.php new file mode 100644 index 0000000..4e93b4b --- /dev/null +++ b/apps/admin/modules/mailbox/templates/_domain_id.php @@ -0,0 +1 @@ +<?php echo $mailbox->getDomain()->getName() ?> diff --git a/apps/admin/modules/mailbox/templates/_last_login.php b/apps/admin/modules/mailbox/templates/_last_login.php new file mode 100644 index 0000000..6e0583a --- /dev/null +++ b/apps/admin/modules/mailbox/templates/_last_login.php @@ -0,0 +1 @@ +<?php echo ($mailbox->getLastLogin()==""? "Never":$mailbox->getLastLogin()) ?> diff --git a/apps/admin/modules/mailbox/templates/_max_address_count.php b/apps/admin/modules/mailbox/templates/_max_address_count.php new file mode 100644 index 0000000..66cc68f --- /dev/null +++ b/apps/admin/modules/mailbox/templates/_max_address_count.php @@ -0,0 +1 @@ +<?php use_helper("Files") ?><?php echo $mailbox->getAddressCount() ?> / <?php echo ($mailbox->getMaxAddressCount()==0 ? "Unlimited": $mailbox->getMaxAddressCount()) ?> diff --git a/apps/admin/modules/mailbox/templates/_max_quota.php b/apps/admin/modules/mailbox/templates/_max_quota.php new file mode 100644 index 0000000..3bf8c47 --- /dev/null +++ b/apps/admin/modules/mailbox/templates/_max_quota.php @@ -0,0 +1 @@ +<?php use_helper("Files") ?><?php $q = $mailbox->getQuota(); $qmax = ($q["max"] != null ? $q["max"]: $mailbox->getMaxQuota()); ?><?php if($q["resource"] != null): ?><?php echo format_bytes($q["current"]*1000) ?> / <?php endif; ?><?php echo ($qmax==0 ? "Unlimited" : format_bytes($qmax*1000)) ?> diff --git a/apps/admin/modules/mailbox/templates/_new_password.php b/apps/admin/modules/mailbox/templates/_new_password.php new file mode 100644 index 0000000..1c28ee6 --- /dev/null +++ b/apps/admin/modules/mailbox/templates/_new_password.php @@ -0,0 +1 @@ +<?php echo input_password_tag('mailbox[new_password]', '', 'size=50') ?> diff --git a/apps/admin/modules/mailbox/templates/_password.php b/apps/admin/modules/mailbox/templates/_password.php new file mode 100644 index 0000000..412f824 --- /dev/null +++ b/apps/admin/modules/mailbox/templates/_password.php @@ -0,0 +1 @@ +<?php echo input_password_tag('mailbox[password]', '', 'size=50') ?> diff --git a/apps/admin/modules/mailbox/validate/create.yml b/apps/admin/modules/mailbox/validate/create.yml new file mode 100644 index 0000000..3668321 --- /dev/null +++ b/apps/admin/modules/mailbox/validate/create.yml @@ -0,0 +1,50 @@ +fillin: + enabled: true + param: + exclude_types: [password] + +validators: + myStringValidator: + class: sfStringValidator + param: + min: 2 + min_error: This field is too short (2 characters minimum) + max: 100 + max_error: This field is too long (100 characters maximum) + myPasswordValidator: + class: sfStringValidator + param: + min: 5 + min_error: The password is too short (5 characters minimum) + max: 100 + max_error: The password is too long (100 characters maximum) + +fields: + mailbox{name}: + required: + msg: The Username is required + myStringValidator: + sfRegexValidator: + match:..........Yes + match_error: 'The characters ".,;/" are not allowed' + pattern: '/[^.,;\/]$/i' + myDenyStringValidator: + values: [<?php echo implode(', ',sfConfig::get('app_mailbox_deny_names')) ?>] + values_error: This Username is not allowed + sfPropelUniqueValidator: + class: Mailbox + column: name + unique_error: This Username already exists + mailbox{password}: + required: + msg: The Password is required + myPasswordValidator: + mailbox{domain_id}: + required: + msg: A Domain has to be specified + mailbox{max_quota}: + required: + msg: The Mailbox Quota is required + mailbox{max_address_count}: + required: + msg: The Maximum Address Count is required diff --git a/apps/admin/modules/mailbox/validate/edit.yml b/apps/admin/modules/mailbox/validate/edit.yml new file mode 100644 index 0000000..1629a9d --- /dev/null +++ b/apps/admin/modules/mailbox/validate/edit.yml @@ -0,0 +1,48 @@ +fillin: + enabled: true + param: + exclude_types: [password] + +validators: + myStringValidator: + class: sfStringValidator + param: + min: 2 + min_error: This field is too short (2 characters minimum) + max: 100 + max_error: This field is too long (100 characters maximum) + myPasswordValidator: + class: sfStringValidator + param: + min: 5 + min_error: The password is too short (5 characters minimum) + max: 100 + max_error: The password is too long (100 characters maximum) + +fields: + mailbox{name}: + required: + msg: The Username is required + myStringValidator: + sfRegexValidator: + match:..........Yes + match_error: 'The characters ".,;/" are not allowed' + pattern: '/[^.,;\/]$/i' + myDenyStringValidator: + values: [<?php echo implode(', ',sfConfig::get('app_mailbox_deny_names')) ?>] + values_error: This Username is not allowed + sfPropelUniqueValidator: + class: Mailbox + column: name + unique_error: This Username already exists + mailbox{new_password}: + myPasswordValidator: + mailbox{domain_id}: + required: + msg: A Domain has to be specified + mailbox{max_quota}: + required: + msg: The Mailbox Quota is required + mailbox{max_address_count}: + required: + msg: The Maximum Address Count is required diff --git a/apps/admin/modules/server/actions/actions.class.php b/apps/admin/modules/server/actions/actions.class.php new file mode 100644 index 0000000..a83d9b9 --- /dev/null +++ b/apps/admin/modules/server/actions/actions.class.php @@ -0,0 +1,29 @@ +<?php + +/** + * server actions. + * + * @package mailadmin + * @subpackage server + * @author Your name here + * @version SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $ + */ +class serverActions extends sfActions +{ + /** + * Executes index action + * + */ + public function executeIndex() + { + $this->forward('server', 'imap'); + } + + public function executeImap() + { + $serverinfo = new IMAPServerInformation(); + $this->serverinfo = $serverinfo; + + return sfView::SUCCESS; + } +} diff --git a/apps/admin/modules/server/templates/imapSuccess.php b/apps/admin/modules/server/templates/imapSuccess.php new file mode 100644 index 0000000..57569ad --- /dev/null +++ b/apps/admin/modules/server/templates/imapSuccess.php @@ -0,0 +1,57 @@ + <div id="context"> + <?php echo use_helper("Asset", "Form") ?> + <h1>IMAP Server Information</h1> + + <hr size="1" /> + + <table> + <tr> + <th colspan="2" align="left">Connection:</th> + </tr> + <tr> + <td>Host:</td> + <td><?php echo $serverinfo->getHost() ?></td> + </tr> + <tr> + <td>Port:</td> + <td><?php echo $serverinfo->getPort() ?></td> + </tr> + <tr> + <th colspan="2" align="left">General:</th> + </tr> + <tr> + <td>Greeting:</td> + <td><?php echo $serverinfo->getGreeting() ?></td> + </tr> + <?php if(($servername = $serverinfo->getServerName()) !== false): ?> + <tr> + <td>Server:</td> + <td><?php echo $serverinfo->getServerName() ?></td> + </tr> + <tr> + <td>Version:</td> + <td><?php echo $serverinfo->getServerVersion() ?></td> + </tr> + <?php endif; ?> + <tr> + <td>Hierarchy Delimiter:</td> + <td><?php echo $serverinfo->getHierarchyDelimiter() ?></td> + </tr> + <tr> + <td valign="top">Capabilities:</td> + <td><?php echo implode("<br />", $serverinfo->getCapabilties()) ?></td> + </tr> + <?php if($serverinfo->hasCapability('ACL')): ?> + <tr> + <th colspan="2" align="left">Extension: Access Control List (ACL)</th> + </tr> + <tr> + <td>Available ACL:</td> + <td><?php echo $serverinfo->getAvailableACL() ?></td> + </tr> + <?php endif; ?> + </table> + + <hr size="1" /> + + </div> diff --git a/apps/admin/modules/user/actions/actions.class.php b/apps/admin/modules/user/actions/actions.class.php new file mode 100644 index 0000000..1af2445 --- /dev/null +++ b/apps/admin/modules/user/actions/actions.class.php @@ -0,0 +1,115 @@ +<?php + +/** + * user actions. + * + * @package mailadmin + * @subpackage user + * @author Your name here + * @version SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $ + */ +class userActions extends autouserActions +{ + public function executeList() + { + // pageination + if($this->hasRequestParameter("max_per_page")) + $this->getUser()->setResultsPerPage($this->getRequestParameter("max_per_page")); + + return parent::executeList(); + } + + public function executeCreate() + { + // populate preset values + $user = $this->getRequestParameter('user'); + $user["parent_user_id"] = $this->getUser()->getId(); + $this->getRequest()->setParameter('user', $user); + + $this->setTemplate("edit"); + return $this->executeEdit(); + } + + public function handleErrorCreate() + { + // populate preset values + $user = $this->getRequestParameter('user'); + $user["parent_user_id"] = $this->getUser()->getId(); + $this->getRequest()->setParameter('user', $user); + + $this->setTemplate("edit"); + return $this->handleErrorEdit(); + } + + public function executeLogin() + { + if($this->getRequest()->getMethod() != sfRequest::POST) + { + $this->getRequest()->setAttribute('referer', $this->getRequest()->getReferer()); + + return sfView::SUCCESS; + } + else + { + return $this->redirect($this->getRequestParameter('referer', '@homepage')); + } + } + + public function handleErrorLogin() + { + return sfView::SUCCESS; + } + + public function executeSettings() + { + $user = UserPeer::retrieveByPK($this->getUser()->getId()); + $this->user = $user; + + if($this->getRequest()->getMethod() != sfRequest::POST) + { + $this->getRequest()->setAttribute('referer', $this->getRequest()->getReferer()); + } + else + { + if($this->getRequest()->getParameter("commit") == "Cancel") + return $this->redirect($this->getRequestParameter('referer', '@homepage')); + + // update record + $user->setNickname($this->getRequestParameter("nickname")); + $user->setFirstName($this->getRequestParameter("first_name")); + $user->setLastName($this->getRequestParameter("last_name")); + $user->setEmail($this->getRequestParameter("email")); + + // set new password + $password = $this->getRequestParameter("password2"); + if($password != "") + $user->setPassword($password); + + $user->save(); + + // update session + $this->getUser()->updateUserAttributes($user); + + return $this->redirect($this->getRequestParameter('referer', '@homepage')); + } + + return sfView::SUCCESS; + } + + public function handleErrorSettings() + { + $user = UserPeer::retrieveByPK($this->getUser()->getId()); + $this->user = $user; + + if($this->getRequest()->getParameter("commit") == "Cancel") + return $this->redirect($this->getRequestParameter('referer', '@homepage')); + + return sfView::SUCCESS; + } + + public function executeLogout() + { + $this->getUser()->signOut($user); + $this->redirect("@homepage"); + } +} diff --git a/apps/admin/modules/user/config/generator.yml b/apps/admin/modules/user/config/generator.yml new file mode 100644 index 0000000..4764f5b --- /dev/null +++ b/apps/admin/modules/user/config/generator.yml @@ -0,0 +1,55 @@ +generator: + class: sfPropelAdminGenerator + param: + model_class: User + theme: mailadmin + + fields: + nickname: { name: Nickname } + full_name: { name: Name } + email: { name: E-Mail } + last_login: { name: Last Login } + + list: + peer_method: doSelectJoinRole + title: List of Administrators + display: [=nickname, _role_id, _domain_permissions, full_name, email, _last_login] + filters: [nickname, role_id, email, parent_user_id, last_login, created_at] + max_per_page: '$this->getUser()->getResultsPerPage("pager")' + sort: [nickname, asc] + fields: + domain_permissions: { name: Associated Domains, params: align=left } + nickname: { params: align=left } + role_id: { params: align=left } + full_name: { params: align=left } + email: { params: align=left } + last_login: { params: align=right } + object_actions: + edit: { name: Edit, action: edit, icon: edit.gif } + delete: { name: Delete, action: delete, icon: trash.gif, params: confirm=Are you sure? } + actions: {} + + create: + title: Create New Administrator + + edit: + title: 'Editing Administrator %%nickname%%' + display: + 'General Settings': [nickname, first_name, last_name, email, parent_user_id] + 'Password Settings': [_password, _password2] + 'Permissions': [role_id, domain_permission] + fields: + domain_permission: { name: Assign Domains, type: admin_double_list, params: through_class=DomainPermission, help: Assign which domains the user is allowed to see (Ignored for superadmins) } + parent_user_id: { name: Parent User, only_for: edit } + nickname: { name: Nickname, params: size=50 } + first_name: { name: First Name, params: size=50 } + last_name: { name: Last Name, params: size=50 } + email: { name: E-Mail, params: size=50, help: Used for password requests or notifications } + role_id: { name: Role } + password: { name: Desired Password } + password2: { name: Re-Type New Password, only_for: edit, help: Leave blank if you do not want to change the password } + actions: + _save_and_list: { name: Save } + _save_and_add: { name: 'Save, then create new one' } + _list: { name: Cancel } + diff --git a/apps/admin/modules/user/config/security.yml b/apps/admin/modules/user/config/security.yml new file mode 100644 index 0000000..dbe3ebb --- /dev/null +++ b/apps/admin/modules/user/config/security.yml @@ -0,0 +1,13 @@ +settings: + is_secure: on + credentials: [] + +login: + is_secure: off + +logout: + is_secure: off + +all: + is_secure: on + credentials: [superadmin] diff --git a/apps/admin/modules/user/templates/_domain_permissions.php b/apps/admin/modules/user/templates/_domain_permissions.php new file mode 100644 index 0000000..0d3e19d --- /dev/null +++ b/apps/admin/modules/user/templates/_domain_permissions.php @@ -0,0 +1,27 @@ +<?php use_helper('I18N','Javascript'); ?> +<?php if($user->getRoleId() == Role::SUPERADMIN): ?> +<?php echo "All Domains" ?> +<?php else: ?> +<?php $list = $user->getDomainPermissionsJoinDomain() ?> +<?php if(count($list) == 0): ?> +<?php echo "None" ?> +<?php else: ?> +<div class="slidelist"> +<?php if(count($list) > sfConfig::get('app_user_domain_perm_collapse_count')): ?> +<?php echo link_to_function(__("Multiple (%1% entries)", array('%1%' => count($list))), visual_effect( +'toggle_slide', 'domain_permissionlist_'.$user->getId())) ?> +<div id="domain_permissionlist_<?php echo $user->getId() ?>" style="display:none"> +<?php endif; ?> + +<ul> +<?php foreach($list as $permission): ?> +<li><?php echo ($permission->getDomain()) ?></li> +<?php endforeach; ?> +</ul> + +<?php if(count($list) > 1): ?> +</div> +<?php endif; ?> +</div> +<?php endif; ?> +<?php endif; ?> diff --git a/apps/admin/modules/user/templates/_last_login.php b/apps/admin/modules/user/templates/_last_login.php new file mode 100644 index 0000000..f15439a --- /dev/null +++ b/apps/admin/modules/user/templates/_last_login.php @@ -0,0 +1 @@ +<?php echo ($user->getLastLogin() ? $user->getLastLogin(): "Never") ?> diff --git a/apps/admin/modules/user/templates/_password.php b/apps/admin/modules/user/templates/_password.php new file mode 100644 index 0000000..e32e4ab --- /dev/null +++ b/apps/admin/modules/user/templates/_password.php @@ -0,0 +1,3 @@ +<?php $value = input_password_tag("user[password]", '', array ( + 'size' => 50, +)); echo $value ? $value : ' ' ?> diff --git a/apps/admin/modules/user/templates/_password1.php b/apps/admin/modules/user/templates/_password1.php new file mode 100644 index 0000000..e32e4ab --- /dev/null +++ b/apps/admin/modules/user/templates/_password1.php @@ -0,0 +1,3 @@ +<?php $value = input_password_tag("user[password]", '', array ( + 'size' => 50, +)); echo $value ? $value : ' ' ?> diff --git a/apps/admin/modules/user/templates/_password2.php b/apps/admin/modules/user/templates/_password2.php new file mode 100644 index 0000000..eab912d --- /dev/null +++ b/apps/admin/modules/user/templates/_password2.php @@ -0,0 +1,3 @@ +<?php $value = input_password_tag("user[password2]", '', array ( + 'size' => 50, +)); echo $value ? $value : ' ' ?> diff --git a/apps/admin/modules/user/templates/_role_id.php b/apps/admin/modules/user/templates/_role_id.php new file mode 100644 index 0000000..bfaf818 --- /dev/null +++ b/apps/admin/modules/user/templates/_role_id.php @@ -0,0 +1 @@ +<?php echo $user->getRole() ?> diff --git a/apps/admin/modules/user/templates/loginSuccess.php b/apps/admin/modules/user/templates/loginSuccess.php new file mode 100644 index 0000000..f41a809 --- /dev/null +++ b/apps/admin/modules/user/templates/loginSuccess.php @@ -0,0 +1,12 @@ + <div id="context"> + <?php echo use_helper("I18N","Asset", "Form", "Validation") ?> + <?php echo form_tag("user/login")?> + <h1><?php echo __("Please authenticate yourself") ?>:</h1> + <hr size="1" /> + <label for="nickname">Username: </label><?php echo input_tag("nickname", $sf_params->get("nickname"), "size=50") ?><?php echo form_error('nickname') ?><br /> + <label for="password">Password: </label><?php echo input_password_tag("password", "", "size=50") ?><?php echo form_error('password') ?><br /> + <?php echo input_hidden_tag("referer", $sf_request->getAttribute('referer')) ?> + <div class="formaction"><?php echo submit_tag("Login") ?></div> + + </form> + </div> diff --git a/apps/admin/modules/user/templates/settingsSuccess.php b/apps/admin/modules/user/templates/settingsSuccess.php new file mode 100644 index 0000000..f1c49d7 --- /dev/null +++ b/apps/admin/modules/user/templates/settingsSuccess.php @@ -0,0 +1,22 @@ + <div id="context"> + <?php echo use_helper("Asset", "Form", "Object", "Validation") ?> + <?php echo form_tag("user/settings")?> + <h1>Update Settings:</h1> + + <hr size="1" /> + + <h2>General Settings:</h2> + + <label for="nickname">Username: </label><?php echo object_input_tag($user, "getNickname","size=50") ?><br /><?php echo form_error('nickname') ?> + <label for="first_name">First Name: </label><?php echo object_input_tag($user, "getFirstName","size=50") ?><br /><?php echo form_error('first_name') ?> + <label for="last_name">Last Name: </label><?php echo object_input_tag($user, "getLastName", "size=50") ?><br /><?php echo form_error('last_name') ?> + <label for="email">E-Mail: </label><?php echo object_input_tag($user, "getEmail", "size=50") ?><div class="sf_admin_edit_help">Used to retrieve your password or to send critical notifications</div><br /><?php echo form_error('email') ?><br /> + + <h2>Change Password:</h2> + <label for="password1">New Password: </label><?php echo input_password_tag("password1", "", "size=50") ?><br /> + <label for="password2">Re-Type New Password: </label><?php echo input_password_tag("password2", "", "size=50") ?><br /><?php echo form_error('password2') ?> + <?php echo input_hidden_tag("referer", $sf_request->getAttribute('referer')) ?> + + <div class="formaction"><?php echo submit_tag("Update") ?><?php echo submit_tag("Cancel") ?></div> + </form> + </div> diff --git a/apps/admin/modules/user/validate/create.yml b/apps/admin/modules/user/validate/create.yml new file mode 100644 index 0000000..7686c7b --- /dev/null +++ b/apps/admin/modules/user/validate/create.yml @@ -0,0 +1,37 @@ +fillin: + enabled: true + param: + exclude_types: [password] + +validators: + myStringValidator: + class: sfStringValidator + param: + min: 2 + min_error: This field is too short (2 characters minimum) + max: 100 + max_error: This field is too long (100 characters maximum) + +fields: + user{nickname}: + required: + msg: The Username is required + sfStringValidator: + min: 5 + min_error: Username must be 5 or more characters + sfPropelUniqueValidator: + class: User + column: nickname + unique_error: This Username does already exist + user{email}: + myStringValidator: + sfEmailValidator: + email_error: This E-Mail Address is invalid + user{password}: + required: + msg: You must define a password + myStringValidator: + user{role_id}: + required: + msg: You must set a role for this user + diff --git a/apps/admin/modules/user/validate/edit.yml b/apps/admin/modules/user/validate/edit.yml new file mode 100644 index 0000000..6480b37 --- /dev/null +++ b/apps/admin/modules/user/validate/edit.yml @@ -0,0 +1,40 @@ +fillin: + enabled: true + param: + exclude_types: [password] + +validators: + myStringValidator: + class: sfStringValidator + param: + min: 2 + min_error: This field is too short (2 characters minimum) + max: 100 + max_error: This field is too long (100 characters maximum) + +fields: + user{nickname}: + required: + msg: The Username is required + sfStringValidator: + min: 5 + min_error: Username must be 5 or more characters + sfPropelUniqueValidator: + class: User + column: nickname + unique_error: This Username does already exist + user{email}: + myStringValidator: + sfEmailValidator: + email_error: This E-Mail Address is invalid + user{role_id}: + required: + msg: You must set a role for this user + user{password}: + group: password_group + user{password2}: + group: password_group + sfCompareValidator: + check: "user[password]" + compare_error: The two passwords do not match + diff --git a/apps/admin/modules/user/validate/login.yml b/apps/admin/modules/user/validate/login.yml new file mode 100644 index 0000000..d6ea563 --- /dev/null +++ b/apps/admin/modules/user/validate/login.yml @@ -0,0 +1,24 @@ +methods: + post: [nickname, password] + +names: + nickname: + required: true + required_msg: Your Username is required + validators: [nicknameValidator, userValidator] + + password: + required: true + required_msg: Your password is required + +nicknameValidator: + class: sfStringValidator + param: + min: 5 + min_error: Username must be 5 or more characters + +userValidator: + class: myLoginValidator + param: + password: password + login_error: This Username does not exist or you entered a wrong password diff --git a/apps/admin/modules/user/validate/settings.yml b/apps/admin/modules/user/validate/settings.yml new file mode 100644 index 0000000..0706d53 --- /dev/null +++ b/apps/admin/modules/user/validate/settings.yml @@ -0,0 +1,43 @@ +fillin: + enabled: true + param: + exclude_types: [password] + +validators: + myStringValidator: + class: sfStringValidator + param: + min: 2 + min_error: This field is too short (2 characters minimum) + max: 100 + max_error: This field is too long (100 characters maximum) + +fields: + nickname: + required: + msg: Your Username is required + sfStringValidator: + min: 5 + min_error: Username must be 5 or more characters + myChangeNicknameValidator: + change_error: This Username does already exist + + first_name: + myStringValidator: + last_name: + myStringValidator: + + email: + required: + msg: Your must provide an E-Mail Address + myStringValidator: + sfEmailValidator: + email_error: This E-Mail Address is invalid + + password1: + group: password_group + password2: + group: password_group + sfCompareValidator: + check: password1 + compare_error: The two passwords do not match diff --git a/apps/admin/templates/_branding.php b/apps/admin/templates/_branding.php new file mode 100644 index 0000000..c035a54 --- /dev/null +++ b/apps/admin/templates/_branding.php @@ -0,0 +1,4 @@ + <?php echo use_helper("Asset") ?> + <div class="branding"> + <div class="logo"><?php echo image_tag("logo","alt=Title")?></div> + </div> diff --git a/apps/admin/templates/_navigation.php b/apps/admin/templates/_navigation.php new file mode 100644 index 0000000..b991247 --- /dev/null +++ b/apps/admin/templates/_navigation.php @@ -0,0 +1,53 @@ + <?php use_helper("Asset","Javascript") ?> + <div class="navigation"> + <ul><? if($sf_user->hasCredential(array('superadmin','domainmaster', 'mailboxmaster'), false)): ?><li<?php echo ($module=="domain"?" class=\"active\"":"") ?>><?php echo link_to("Domains","domain/list") ?></li><li<?php echo ($module=="mailbox"?" class=\"active\"":"") ?>><?php echo link_to("Mailboxes","mailbox/list") ?></li><?php endif; ?><li<?php echo ($module=="address"?" class=\"active\"":"") ?>><?php echo link_to("Addresses","address/list") ?></li><? if($sf_user->hasCredential('superadmin')): ?><li<?php echo ($module=="user"?" class=\"active\"":"") ?>><?php echo link_to("Administrators","user/list") ?></li><li<?php echo ($module=="log"?" class=\"active\"":"") ?>><?php echo link_to("Logs","log/list") ?></li><li<?php echo ($module=="server"?" class=\"active\"":"") ?>><?php echo link_to("Server","server/index") ?></li><?php endif; ?></ul> + </div> + <?php if($module=="domain"): ?> + <div class="subnavigation"> + <ul> + <li <?php echo ($action=="list"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("list.gif","alt=[...] border=0") . " Browse Domains", $module."/list")?></li> + <? if($sf_user->hasCredential(array('superadmin','domainmaster'), false)): ?><li <?php echo ($action=="create"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("add.gif","alt=[+] border=0") . " Add New Domain", $module."/create")?></li><?php endif; ?> + </ul> + </div> + <?php endif; ?> + <?php if($module=="mailbox"): ?> + <div class="subnavigation"> + <ul> + <li <?php echo ($action=="list"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("list.gif","alt=[...] border=0") . " Browse Mailboxes", $module."/list")?></li> + <li <?php echo ($action=="create"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("add.gif","alt=[+] border=0") . " Add New Mailbox", $module."/create")?></li> + </ul> + </div> + <?php endif; ?> + <?php if($module=="address"): ?> + <div class="subnavigation"> + <ul> + <li <?php echo ($action=="list"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("list.gif","alt=[...] border=0") . " Browse Addresses", $module."/list")?></li> + <li <?php echo ($action=="create"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("add.gif","alt=[+] border=0") . " Add New Address", $module."/create")?></li> + </ul> + </div> + <?php endif; ?> + <? if($sf_user->hasCredential('superadmin')): ?> + <?php if($module=="user"): ?> + <div class="subnavigation"> + <ul> + <li <?php echo ($action=="list"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("list.gif","alt=[...] border=0") . " Browse Administrators", $module."/list")?></li> + <li <?php echo ($action=="create"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("add.gif","alt=[+] border=0") . " Add New Administrator", $module."/create")?></li> + </ul> + </div> + <?php endif; ?> + <?php if($module=="log"): ?> + <div class="subnavigation"> + <ul> + <li <?php echo ($action=="list"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("list.gif","alt=[...] border=0") . " Browse Logs", $module."/list")?></li> + <li <?php echo ($action=="clear"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("shred.gif","alt=[-] border=0") . " Clear Logs", $module."/clear")?></li> + </ul> + </div> + <?php endif; ?> + <?php if($module=="server"): ?> + <div class="subnavigation"> + <ul> + <li <?php echo ($action=="imap"?"class=\"active\"":"") ?>><?php echo link_to(image_tag("network-server.gif","alt=[...] border=0") . " IMAP Summary", $module."/imap")?></li> + </ul> + </div> + <?php endif; ?> + <?php endif; ?> diff --git a/apps/admin/templates/_notes.php b/apps/admin/templates/_notes.php new file mode 100644 index 0000000..e994a50 --- /dev/null +++ b/apps/admin/templates/_notes.php @@ -0,0 +1,9 @@ + <?php echo use_helper("I18N","Asset","Date") ?> + <div class="notes"> + <ul> + <li><?php echo link_to("Mailadmin ".sfConfig::get("app_info_version"), "http://wiki.sukimashita.com/Mailadmin") ?></li> + <li><?php echo image_tag("ok.gif","alt=[x] border=0")?> <?php echo link_to("XHTML 1.0", "http://validator.w3.org/check/referer") ?></li> + <li><?php echo image_tag("ok.gif","alt=[x] border=0")?> <?php echo link_to("CSS", "http://jigsaw.w3.org/css-validator/check/referer") ?></li> + </ul> + <span class="legal">© <?php echo format_date(time(), "yyyy") ?> <?php echo link_to("Mirell Development", "http://mirell.de") ?> - <?php echo __('This web application is licensed under the terms of the GNU General Public License') ?></span> + </div> diff --git a/apps/admin/templates/layout.php b/apps/admin/templates/layout.php new file mode 100644 index 0000000..d10d047 --- /dev/null +++ b/apps/admin/templates/layout.php @@ -0,0 +1,35 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> + <?php include_http_metas() ?> + <?php include_metas() ?> + <?php include_title() ?> + <link rel="icon" href="/images/favicon.ico" /><link rel="SHORTCUT ICON" href="/images/favicon.ico" /> +</head> +<body> +<div class="base"> + <?php include_partial('global/branding') ?> + <?php echo use_helper("Asset","Date") ?> + <div class="session"> + <?php if($sf_user->isAuthenticated()): ?> + <ul> + <li><?php echo image_tag("information.gif","alt=[?]")?><b>Logged in as:</b> <span class="adminname"><?php echo $sf_user->getNickname() ?></span> (<span class="adminrole"><?php echo $sf_user->getRoleName() ?></span>) | <?php echo link_to("Settings","user/settings") ?> | <?php echo link_to("Logout","user/logout") ?></li> + <li><b>Last Login:</b> <?php if($sf_user->getLastLogin()!=""): ?> + <?php echo format_date($sf_user->getLastLogin(),array('P','t')) ?> + <?php else: ?> + <?php echo "Never" ?> + <?php endif; ?></li> + <li id="indicator"><?php echo image_tag("load.gif", "alt=[...] border=0") ?> loading</li> + </ul> + <?php else: ?> + <ul><li><?php echo image_tag("warning.gif","alt=[!]")?><b>You are not authenticated.</b> | <?php echo link_to("Login","user/login") ?></li></ul> + <?php endif; ?> + </div> + <?php if($sf_user->isAuthenticated()): ?> + <?php include_partial("global/navigation", array("module" => $sf_context->getModuleName(), "action" => $sf_context->getActionName())) ?> + <?php endif; ?> + <?php echo $sf_data->getRaw('sf_content') ?> + <?php include_partial('global/notes') ?> +</div> +</body> +</html> |