From c7b9800aee5425a3964963c77c761f4439578b75 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Thu, 1 Aug 2013 11:35:05 +0200 Subject: Extension manager: First draft of the extension class --- lib/plugins/extension/README | 27 +++ lib/plugins/extension/helper/extension.php | 289 +++++++++++++++++++++++++++++ lib/plugins/extension/plugin.info.txt | 7 + 3 files changed, 323 insertions(+) create mode 100644 lib/plugins/extension/README create mode 100644 lib/plugins/extension/helper/extension.php create mode 100644 lib/plugins/extension/plugin.info.txt (limited to 'lib') diff --git a/lib/plugins/extension/README b/lib/plugins/extension/README new file mode 100644 index 000000000..5eefe924d --- /dev/null +++ b/lib/plugins/extension/README @@ -0,0 +1,27 @@ +extension Plugin for DokuWiki + +Extension manager + +All documentation for this plugin can be found at +https://www.dokuwiki.org/plugin:extension + +If you install this plugin manually, make sure it is installed in +lib/plugins/extension/ - if the folder is called different it +will not work! + +Please refer to http://www.dokuwiki.org/plugins for additional info +on how to install plugins in DokuWiki. + +---- +Copyright (C) Michael Hamann + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +See the COPYING file in your DokuWiki folder for details diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php new file mode 100644 index 000000000..2746837be --- /dev/null +++ b/lib/plugins/extension/helper/extension.php @@ -0,0 +1,289 @@ + + */ + +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +/** + * Class helper_plugin_extension_extension represents a single extension (plugin or template) + */ +class helper_plugin_extension_extension extends DokuWiki_Plugin { + private $name; + private $is_template; + private $localInfo; + private $remoteInfo; + + /** + * @return bool false, this component is not a singleton + */ + public function isSingleton() { + return false; + } + + /** + * Set the name of the extension this instance shall represents, triggers loading the local and remote data + * + * @param string $name The base name of the extension + * @param bool $is_template If the extension is a template + * @return bool If some (local or remote) data was found + */ + public function setExtension($name, $is_template) { + $this->name = $name; + $this->is_template = $is_template; + } + + /** + * If the extension is installed locally + * + * @return bool If the extension is installed locally + */ + public function isInstalled() { + } + + /** + * If the extension should be updated, i.e. if an updated version is available + * + * @return bool If an update is available + */ + public function updateAvailable() { + return $this->getInstalledVersion() < $this->getLastUpdate(); + } + + /** + * If the extension is a template + * + * @return bool If this extension is a template + */ + public function isTemplate() { + return $this->is_template; + } + + // Data from plugin.info.txt/template.info.txt or the repo when not available locally + /** + * Get the basename of the extension + * + * @return string The basename + */ + public function getBase() { + } + + /** + * Get the display name of the extension + * + * @return string The display name + */ + public function getName() { + } + + /** + * Get the author name of the extension + * + * @return string The name of the author + */ + public function getAuthor() { + } + + /** + * Get the email of the author of the extension + * + * @return string The email address + */ + public function getEmail() { + } + + /** + * Get the description of the extension + * + * @return string The description + */ + public function getDescription() { + } + + /** + * Get the URL of the extension, usually a page on dokuwiki.org + * + * @return string The URL + */ + public function getURL() { + } + + /** + * Get the installed version of the extension + * + * @return string The version, usually in the form yyyy-mm-dd + */ + public function getInstalledVersion() { + } + + /** + * Get the names of the dependencies of this extension + * + * @return array The base names of the dependencies + */ + public function getDependencies() { + } + + /** + * Get the names of all conflicting extensions + * + * @return array The names of the conflicting extensions + */ + public function getConflicts() { + } + + /** + * Get the names of similar extensions + * + * @return array The names of similar extensions + */ + public function getSimilarPlugins() { + } + + /** + * Get the names of the tags of the extension + * + * @return array The names of the tags of the extension + */ + public function getTags() { + } + + /** + * Get the text of the security warning if there is any + * + * @return string|bool The security warning if there is any, false otherwise + */ + public function getSecurityWarning() { + } + + /** + * Get the text of the security issue if there is any + * + * @return string|bool The security issue if there is any, false otherwise + */ + public function getSecurityIssue() { + } + + /** + * Get the URL of the screenshot of the extension if there is any + * + * @return string|bool The screenshot URL if there is any, false otherwise + */ + public function getScreenshotURL() { + } + + /** + * Get the last used download URL of the extension if there is any + * + * @return string|bool The previously used download URL, false if the extension has been installed manually + */ + public function getLastDownloadURL() { + } + + /** + * Get the download URL of the extension if there is any + * + * @return string|bool The download URL if there is any, false otherwise + */ + public function getDownloadURL() { + } + + /** + * Get the bug tracker URL of the extension if there is any + * + * @return string|bool The bug tracker URL if there is any, false otherwise + */ + public function getBugtrackerURL() { + } + + /** + * Get the URL of the source repository if there is any + * + * @return string|bool The URL of the source repository if there is any, false otherwise + */ + public function getSourcerepoURL() { + } + + /** + * Get the donation URL of the extension if there is any + * + * @return string|bool The donation URL if there is any, false otherwise + */ + public function getDonationURL() { + } + + /** + * Get the extension type(s) + * + * @return array The type(s) as array of strings + */ + public function getType() { + } + + /** + * Get a list of all DokuWiki versions this extension is compatible with + * + * @return array The versions in the form yyyy-mm-dd + */ + public function getCompatibleVersions() { + } + + /** + * Get the date of the last available update + * + * @return string The last available update in the form yyyy-mm-dd + */ + public function getLastUpdate() { + } + + /** + * Get the base path of the extension + * + * @return string The base path of the extension + */ + public function getInstallDir() { + if ($this->isTemplate()) { + return basename(tpl_incdir()).$this->name; + } else { + return DOKU_PLUGIN.$this->name; + } + } + + /** + * The type of extension installation + * + * @return string One of "none", "manual", "git" or "automatic" + */ + public function getInstallType() { + } + + /** + * If the extension can probably be installed/updated or uninstalled + * + * @return bool|string True or one of "nourl", "noparentperms" (template/plugin install path not writable), "noperms" (extension itself not writable) + */ + public function canModify() { + } + + /** + * Install or update the extension + * + * @return bool|string True or an error message + */ + public function installOrUpdate() { + } + + /** + * Uninstall the extension + * + * @return bool|string True or an error message + */ + public function deleteExtension() { + } +} + +// vim:ts=4:sw=4:et: diff --git a/lib/plugins/extension/plugin.info.txt b/lib/plugins/extension/plugin.info.txt new file mode 100644 index 000000000..3c4469ad7 --- /dev/null +++ b/lib/plugins/extension/plugin.info.txt @@ -0,0 +1,7 @@ +base extension +author Michael Hamann +email michael@content-space.de +date 2013-08-01 +name extension plugin +desc Extension manager +url https://www.dokuwiki.org/plugin:extension -- cgit v1.2.3 From b9ca398d17863ad9a679d220dd742b0480fa80b6 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Thu, 1 Aug 2013 20:50:37 +0200 Subject: Extension manager: implemented more extension info and basic repository access --- lib/plugins/extension/helper/extension.php | 188 ++++++++++++++++++++++++++-- lib/plugins/extension/helper/repository.php | 112 +++++++++++++++++ 2 files changed, 292 insertions(+), 8 deletions(-) create mode 100644 lib/plugins/extension/helper/repository.php (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 2746837be..b8981cf91 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -17,6 +17,9 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { private $is_template; private $localInfo; private $remoteInfo; + private $managerData; + /** @var helper_plugin_extension_repository $repository */ + private $repository = null; /** * @return bool false, this component is not a singleton @@ -35,6 +38,28 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { public function setExtension($name, $is_template) { $this->name = $name; $this->is_template = $is_template; + $this->localInfo = array(); + $this->managerData = array(); + $this->remoteInfo = array(); + + if ($this->isInstalled()) { + if ($this->isTemplate()) { + $infopath = $this->getInstallDir().'/template.info.txt'; + } else { + $infopath = $this->getInstallDir().'/plugin.info.txt'; + } + if (is_readable($infopath)) { + $this->localInfo = confToHash($infopath); + } + + $this->readManagerData(); + } + + if ($this->repository == null) { + $this->repository = $this->loadHelper('extension_repository'); + } + + $this->remoteInfo = $this->repository->getData(($this->isTemplate() ? 'template:' : '').$this->getBase()); } /** @@ -43,6 +68,18 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool If the extension is installed locally */ public function isInstalled() { + return is_dir($this->getInstallDir()); + } + + /** + * If the extension is enabled + * + * @return bool If the extension is enabled + */ + public function isEnabled() { + /* @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; + return !$plugin_controller->isdisabled($this->name); } /** @@ -51,6 +88,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool If an update is available */ public function updateAvailable() { + $lastupdate = $this->getLastUpdate(); + if ($lastupdate === false) return false; return $this->getInstalledVersion() < $this->getLastUpdate(); } @@ -70,6 +109,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The basename */ public function getBase() { + return $this->name; } /** @@ -78,6 +118,9 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The display name */ public function getName() { + if (isset($this->localInfo['name'])) return $this->localInfo['name']; + if (isset($this->remoteInfo['name'])) return $this->remoteInfo['name']; + return $this->name; } /** @@ -86,14 +129,31 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The name of the author */ public function getAuthor() { + if (isset($this->localInfo['author'])) return $this->localInfo['author']; + if (isset($this->remoteInfo['author'])) return $this->remoteInfo['author']; + return $this->getLang('unknownauthor'); } /** - * Get the email of the author of the extension + * Get the email of the author of the extension if there is any * - * @return string The email address + * @return string|bool The email address or false if there is none */ public function getEmail() { + // email is only in the local data + if (isset($this->localInfo['email'])) return $this->localInfo['email']; + return false; + } + + /** + * Get the email id, i.e. the md5sum of the email + * + * @return string|bool The md5sum of the email if there is any, false otherwise + */ + public function getEmailID() { + if (isset($this->remoteInfo['emailid'])) return $this->remoteInfo['emailid']; + if (isset($this->localInfo['email'])) return md5($this->localInfo['email']); + return false; } /** @@ -102,6 +162,9 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The description */ public function getDescription() { + if (isset($this->localInfo['desc'])) return $this->localInfo['desc']; + if (isset($this->remoteInfo['description'])) return $this->remoteInfo['description']; + return ''; } /** @@ -110,14 +173,19 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The URL */ public function getURL() { + if (isset($this->localInfo['url'])) return $this->localInfo['url']; + return 'https://www.dokuwiki.org/plugin:'.$this->name; } /** * Get the installed version of the extension * - * @return string The version, usually in the form yyyy-mm-dd + * @return string|bool The version, usually in the form yyyy-mm-dd if there is any */ public function getInstalledVersion() { + if (isset($this->localInfo['date'])) return $this->localInfo['date']; + if ($this->isInstalled()) return $this->getLang('unknownversion'); + return false; } /** @@ -126,6 +194,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return array The base names of the dependencies */ public function getDependencies() { + if (isset($this->remoteInfo['dependencies'])) return $this->remoteInfo['dependencies']; + return array(); } /** @@ -134,6 +204,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return array The names of the conflicting extensions */ public function getConflicts() { + if (isset($this->remoteInfo['conflicts'])) return $this->remoteInfo['dependencies']; + return array(); } /** @@ -141,7 +213,9 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The names of similar extensions */ - public function getSimilarPlugins() { + public function getSimilarExtensions() { + if (isset($this->remoteInfo['similar'])) return $this->remoteInfo['similar']; + return array(); } /** @@ -150,6 +224,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return array The names of the tags of the extension */ public function getTags() { + if (isset($this->remoteInfo['tags'])) return $this->remoteInfo['tags']; + return array(); } /** @@ -158,6 +234,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The security warning if there is any, false otherwise */ public function getSecurityWarning() { + if (isset($this->remoteInfo['securitywarning'])) return $this->remoteInfo['securitywarning']; + return false; } /** @@ -166,6 +244,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The security issue if there is any, false otherwise */ public function getSecurityIssue() { + if (isset($this->remoteInfo['securityissue'])) return $this->remoteInfo['securityissue']; + return false; } /** @@ -174,6 +254,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The screenshot URL if there is any, false otherwise */ public function getScreenshotURL() { + if (isset($this->remoteInfo['screenshoturl'])) return $this->remoteInfo['screenshoturl']; + return false; } /** @@ -182,6 +264,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The previously used download URL, false if the extension has been installed manually */ public function getLastDownloadURL() { + if (isset($this->managerData['downloadurl'])) return $this->managerData['downloadurl']; + return false; } /** @@ -190,6 +274,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The download URL if there is any, false otherwise */ public function getDownloadURL() { + if (isset($this->remoteInfo['downloadurl'])) return $this->remoteInfo['downloadurl']; + return false; } /** @@ -198,6 +284,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The bug tracker URL if there is any, false otherwise */ public function getBugtrackerURL() { + if (isset($this->remoteInfo['bugtracker'])) return $this->remoteInfo['bugtracker']; + return false; } /** @@ -206,6 +294,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The URL of the source repository if there is any, false otherwise */ public function getSourcerepoURL() { + if (isset($this->remoteInfo['sourcerepo'])) return $this->remoteInfo['sourcerepo']; + return false; } /** @@ -214,6 +304,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The donation URL if there is any, false otherwise */ public function getDonationURL() { + if (isset($this->remoteInfo['donationurl'])) return $this->remoteInfo['donationurl']; + return false; } /** @@ -221,23 +313,30 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return array The type(s) as array of strings */ - public function getType() { + public function getTypes() { + if (isset($this->remoteInfo['types'])) return explode(', ', $this->remoteInfo['types']); + if ($this->isTemplate()) return array(32 => 'template'); + return array(); } /** * Get a list of all DokuWiki versions this extension is compatible with * - * @return array The versions in the form yyyy-mm-dd + * @return array The versions in the form yyyy-mm-dd => ('label' => label, 'implicit' => implicit) */ public function getCompatibleVersions() { + if (isset($this->remoteInfo['compatible'])) return $this->remoteInfo['compatible']; + return array(); } /** * Get the date of the last available update * - * @return string The last available update in the form yyyy-mm-dd + * @return string|bool The last available update in the form yyyy-mm-dd if there is any, false otherwise */ public function getLastUpdate() { + if (isset($this->remoteInfo['lastupdate'])) return $this->remoteInfo['lastupdate']; + return false; } /** @@ -259,6 +358,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string One of "none", "manual", "git" or "automatic" */ public function getInstallType() { + if (!$this->isInstalled()) return 'none'; + if (!empty($this->managerData)) return 'automatic'; + if (is_dir($this->getInstallDir().'/.git')) return 'git'; + return 'manual'; } /** @@ -282,7 +385,76 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return bool|string True or an error message */ - public function deleteExtension() { + public function uninstall() { + } + + /** + * Enable the extension + * + * @return bool|string True or an error message + */ + public function enable() { + if ($this->isTemplate()) return $this->getLang('notimplemented'); + /* @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; + if (!$this->isInstalled()) return $this->getLang('notinstalled'); + if (!$this->isEnabled()) return $this->getLang('alreadyenabled'); + if ($plugin_controller->enable($this->name)) { + return true; + } else { + return $this->getLang('pluginlistsaveerror'); + } + } + + /** + * Disable the extension + * + * @return bool|string True or an error message + */ + public function disable() { + if ($this->isTemplate()) return $this->getLang('notimplemented'); + + /* @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; + if (!$this->isInstalled()) return $this->getLang('notinstalled'); + if (!$this->isEnabled()) return $this->getLang('alreadydisabled'); + if ($plugin_controller->disable($this->name)) { + return true; + } else { + return $this->getLang('pluginlistsaveerror'); + } + } + + /** + * Read the manager.dat file + */ + protected function readManagerData() { + $managerpath = $this->getInstallDir().'/manager.dat'; + if (is_readable($managerpath)) { + $file = @file($managerpath); + if(!empty($file)) { + foreach($file as $line) { + list($key, $value) = explode('=', trim($line, PHP_EOL), 2); + $key = trim($key); + $value = trim($value); + // backwards compatible with old plugin manager + if($key == 'url') $key = 'downloadurl'; + $this->managerData[$key] = $value; + } + } + } + } + + /** + * Write the manager.data file + */ + protected function writeManagerData() { + $managerpath = $this->getInstallDir().'/manager.dat'; + $data = ''; + foreach ($this->managerData as $k => $v) { + $data .= $k.'='.$v.DOKU_LF; + } + io_saveFile($managerpath, $data); } } diff --git a/lib/plugins/extension/helper/repository.php b/lib/plugins/extension/helper/repository.php new file mode 100644 index 000000000..37b9bc02c --- /dev/null +++ b/lib/plugins/extension/helper/repository.php @@ -0,0 +1,112 @@ + + */ + +if (!defined('EXTENSION_REPOSITORY_API_ENDPOINT')) + define('EXTENSION_REPSITORY_API', 'http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php'); + +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +/** + * Class helper_plugin_extension_repository provides access to the extension repository on dokuwiki.org + */ +class helper_plugin_extension_repository extends DokuWiki_Plugin { + private $loaded_extensions = array(); + private $has_access = null; + /** + * Initialize the repository (cache), fetches data for all installed plugins + */ + public function init() { + /* @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; + if ($this->hasAccess()) { + $list = $plugin_controller->getList('', true); + $request_data = array('fmt' => 'php'); + $request_needed = false; + foreach ($list as $name) { + $cache = new cache('##extension_manager##'.$name, 'repo'); + $result = null; + if (!isset($this->loaded_extensions[$name]) && $this->hasAccess() && !$cache->useCache(array('age' => 3600 * 24))) { + $this->loaded_extensions[$name] = true; + $request_data['ext'][] = $name; + $request_needed = true; + } + } + + if ($request_needed) { + $httpclient = new DokuHTTPClient(); + $data = $httpclient->post(EXTENSION_REPSITORY_API, $request_data); + if ($data !== false) { + $extensions = unserialize($data); + foreach ($extensions as $extension) { + $cache = new cache('##extension_manager##'.$extension['plugin'], 'repo'); + $cache->storeCache(serialize($extension)); + } + } else { + $this->has_access = false; + } + } + } + } + + /** + * If repository access is available + * + * @return bool If repository access is available + */ + public function hasAccess() { + if ($this->has_access === null) { + $cache = new cache('##extension_manager###hasAccess', 'repo'); + $result = null; + if (!$cache->useCache(array('age' => 3600 * 24))) { + $httpclient = new DokuHTTPClient(); + $httpclient->timeout = 5; + $data = $httpclient->get(EXTENSION_REPSITORY_API.'?cmd=ping'); + if ($data !== false) { + $this->has_access = true; + $cache->storeCache(1); + } else { + $this->has_access = false; + $cache->storeCache(0); + } + } else { + $this->has_access = ($cache->retrieveCache(false) == 1); + } + } + return $this->has_access; + } + + /** + * Get the remote data of an individual plugin or template + * + * @param string $name The plugin name to get the data for, template names need to be prefix by 'template:' + * @return array The data or null if nothing was found (possibly no repository access) + */ + public function getData($name) { + $cache = new cache('##extension_manager##'.$name, 'repo'); + $result = null; + if (!isset($this->loaded_extensions[$name]) && $this->hasAccess() && !$cache->useCache(array('age' => 3600 * 24))) { + $this->loaded_extensions[$name] = true; + $httpclient = new DokuHTTPClient(); + $data = $httpclient->get(EXTENSION_REPSITORY_API.'?fmt=php&ext[]='.urlencode($name)); + if ($data !== false) { + $result = unserialize($data); + $cache->storeCache(serialize($result[0])); + return $result[0]; + } else { + $this->has_access = false; + } + } + if (file_exists($cache->cache)) { + return unserialize($cache->retrieveCache(false)); + } + return array(); + } +} + +// vim:ts=4:sw=4:et: -- cgit v1.2.3 From 788f86d986d170475e9fda3578b4fde5ba4864dd Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Thu, 1 Aug 2013 21:14:17 +0200 Subject: Extension manager: add language file and simple admin component --- lib/plugins/extension/admin.php | 58 ++++++++++++++++++++++++++++++++++ lib/plugins/extension/lang/en/lang.php | 21 ++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 lib/plugins/extension/admin.php create mode 100644 lib/plugins/extension/lang/en/lang.php (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php new file mode 100644 index 000000000..19863e772 --- /dev/null +++ b/lib/plugins/extension/admin.php @@ -0,0 +1,58 @@ + + */ + +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +class admin_plugin_extension extends DokuWiki_Admin_Plugin { + + /** + * @return int sort number in admin menu + */ + public function getMenuSort() { + return 0; + } + + /** + * @return bool true if only access for superuser, false is for superusers and moderators + */ + public function forAdminOnly() { + return true; + } + + /** + * Should carry out any processing required by the plugin. + */ + public function handle() { + /* @var helper_plugin_extension_repository $repository */ + $repository = $this->loadHelper('extension_repository'); + $repository->init(); + } + + /** + * Render HTML output, e.g. helpful text and a form + */ + public function html() { + /* @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; + ptln('

'.$this->getLang('menu').'

'); + + $pluginlist = $plugin_controller->getList('', true); + /* @var helper_plugin_extension_extension $extension */ + $extension = $this->loadHelper('extension_extension'); + foreach ($pluginlist as $name) { + $extension->setExtension($name, false); + ptln('

'.hsc($extension->getName()).'

'); + ptln('

'.hsc($extension->getDescription()).'

'); + ptln('

Latest available version: '.hsc($extension->getLastUpdate()).'

'); + ptln('

Installed version: '.hsc($extension->getInstalledVersion()).'

'); + } + } +} + +// vim:ts=4:sw=4:et: \ No newline at end of file diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php new file mode 100644 index 000000000..81069e498 --- /dev/null +++ b/lib/plugins/extension/lang/en/lang.php @@ -0,0 +1,21 @@ + + */ + +// menu entry for admin plugins +$lang['menu'] = 'Extension manager'; + +// custom language strings for the plugin +$lang['notimplemented'] = 'This feature hasn\'t been implemented yet'; +$lang['alreadyenabled'] = 'This extension has already been enabled'; +$lang['alreadydisabled'] = 'This extension has already been disabled'; +$lang['pluginlistsaveerror'] = 'There was an error saving the plugin list'; +$lang['unknownauthor'] = 'Unknown author'; +$lang['unknownversion'] = 'Unknown version'; + + + +//Setup VIM: ex: et ts=4 : -- cgit v1.2.3 From 9c0a72696a95f03deea27243cb67a497ed3d6993 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Fri, 2 Aug 2013 12:28:08 +0200 Subject: Extension manager: fix install dir for templates --- lib/plugins/extension/helper/extension.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index b8981cf91..05f64efeb 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -8,6 +8,7 @@ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); +if(!defined('DOKU_TPLLIB')) define('DOKU_TPLLIB', DOKU_INC.'lib/tpl/'); /** * Class helper_plugin_extension_extension represents a single extension (plugin or template) @@ -346,7 +347,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function getInstallDir() { if ($this->isTemplate()) { - return basename(tpl_incdir()).$this->name; + return DOKU_TPLLIB.$this->name; } else { return DOKU_PLUGIN.$this->name; } -- cgit v1.2.3 From 7c30f5ced5496bbc22c78497011da33d121aeb56 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Fri, 2 Aug 2013 12:29:34 +0200 Subject: Extension manager: Use getInfo() when no info.txt is available --- lib/plugins/extension/helper/extension.php | 52 ++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 05f64efeb..4243afb69 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -44,15 +44,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $this->remoteInfo = array(); if ($this->isInstalled()) { - if ($this->isTemplate()) { - $infopath = $this->getInstallDir().'/template.info.txt'; - } else { - $infopath = $this->getInstallDir().'/plugin.info.txt'; - } - if (is_readable($infopath)) { - $this->localInfo = confToHash($infopath); - } - + $this->readLocalData(); $this->readManagerData(); } @@ -426,6 +418,48 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } } + /** + * Read local extension data either from info.txt or getInfo() + */ + protected function readLocalData() { + if ($this->isTemplate()) { + $infopath = $this->getInstallDir().'/template.info.txt'; + } else { + $infopath = $this->getInstallDir().'/plugin.info.txt'; + } + + if (is_readable($infopath)) { + $this->localInfo = confToHash($infopath); + } elseif (!$this->isTemplate() && $this->isEnabled()) { + global $plugin_types; + $path = $this->getInstallDir().'/'; + $plugin = null; + + foreach($plugin_types as $type) { + if(@file_exists($path.$type.'.php')) { + $plugin = plugin_load($type, $this->getBase()); + if ($plugin) break; + } + + if($dh = @opendir($path.$type.'/')) { + while(false !== ($cp = readdir($dh))) { + if($cp == '.' || $cp == '..' || strtolower(substr($cp, -4)) != '.php') continue; + + $plugin = plugin_load($type, $this->getBase().'_'.substr($cp, 0, -4)); + if ($plugin) break; + } + if ($plugin) break; + closedir($dh); + } + } + + if ($plugin) { + /* @var DokuWiki_Plugin $plugin */ + $this->localInfo = $plugin->getInfo(); + } + } + } + /** * Read the manager.dat file */ -- cgit v1.2.3 From 449f398253213589bf4cd3c28f2c38b9d853b06a Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Fri, 2 Aug 2013 12:30:42 +0200 Subject: Extension manager: Improve update check --- lib/plugins/extension/helper/extension.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 4243afb69..5e3074c83 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -83,6 +83,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { public function updateAvailable() { $lastupdate = $this->getLastUpdate(); if ($lastupdate === false) return false; + $installed = $this->getInstalledVersion(); + if ($installed === false || $installed === $this->getLang('unknownversion')) return true; return $this->getInstalledVersion() < $this->getLastUpdate(); } -- cgit v1.2.3 From 1981046ea006031f74fb082960756b3d2919b99e Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Fri, 2 Aug 2013 12:31:11 +0200 Subject: Extension manager: implement uninstall, canModify and install/update --- lib/plugins/extension/helper/extension.php | 361 ++++++++++++++++++++++++++++- lib/plugins/extension/lang/en/lang.php | 6 + 2 files changed, 366 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 5e3074c83..b80e56a4d 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -365,6 +365,18 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool|string True or one of "nourl", "noparentperms" (template/plugin install path not writable), "noperms" (extension itself not writable) */ public function canModify() { + if ($this->isInstalled()) { + if (!is_writable($this->getInstallDir())) { + return 'noperms'; + } + } + $parent_path = ($this->isTemplate() ? DOKU_TPLLIB : DOKU_PLUGIN); + if (!is_writable($parent_path)) { + return 'noparentperms'; + } + + if (!$this->getDownloadURL()) return 'nourl'; + return true; } /** @@ -373,14 +385,26 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool|string True or an error message */ public function installOrUpdate() { + if (($status = $this->download($this->getDownloadURL(), $path)) === true) { + if (($status = $this->installArchive($path, $installed_extensions, $this->isInstalled(), $this->getBase())) == true) { + // refresh extension information + if (!isset($installed_extensions[$this->getBase()])) { + $status = 'Error, the requested extension hasn\'t been installed or updated'; + } + $this->setExtension($this->name, $this->isTemplate()); + } + $this->dir_delete(dirname($path)); + } + return $status; } /** * Uninstall the extension * - * @return bool|string True or an error message + * @return bool If the plugin was sucessfully installed */ public function uninstall() { + return $this->dir_delete($this->getInstallDir()); } /** @@ -493,6 +517,341 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } io_saveFile($managerpath, $data); } + + /** + * delete, with recursive sub-directory support + * + * @param string $path The path that shall be deleted + * @return bool If the directory has been successfully deleted + */ + protected function dir_delete($path) { + if(!is_string($path) || $path == "") return false; + + if(is_dir($path) && !is_link($path)) { + if(!$dh = @opendir($path)) return false; + + while ($f = readdir($dh)) { + if($f == '..' || $f == '.') continue; + $this->dir_delete("$path/$f"); + } + + closedir($dh); + return @rmdir($path); + } else { + return @unlink($path); + } + } + + /** + * Download an archive to a protected path + * @param string $url The url to get the archive from + * @param string $path The path where the archive was saved (output parameter) + * @return bool|string True on success, an error message on failure + */ + public function download($url, &$path) { + // check the url + $matches = array(); + if(!preg_match("/[^/]*$/", $url, $matches) || !$matches[0]) { + return $this->getLang('baddownloadurl'); + } + $file = $matches[0]; + + // create tmp directory for download + if(!($tmp = io_mktmpdir())) { + return $this->getLang('error_dircreate'); + } + + // download + if(!$file = io_download($url, $tmp.'/', true, $file)) { + $this->dir_delete($tmp); + return sprintf($this->getLang('error_download'), $url); + } + + $path = $tmp.'/'.$file; + + return true; + } + + /** + * @param string $file The path to the archive that shall be installed + * @param bool $overwrite If an already installed plugin should be overwritten + * @param array $installed_extensions Array of all installed extensions in the form $base => ('type' => $type, 'action' => 'update'|'install') + * @param string $base The basename of the plugin if it's known + * @return bool|string True on success, an error message on failure + */ + public function installArchive($file, &$installed_extensions, $overwrite=false, $base = '') { + $error = false; + + // create tmp directory for decompression + if(!($tmp = io_mktmpdir())) { + return $this->getLang('error_dircreate'); + } + + // add default base folder if specified to handle case where zip doesn't contain this + if($base && !@mkdir($tmp.'/'.$base)) { + $error = $this->getLang('error_dircreate'); + } + + if(!$error && !$this->decompress("$tmp/$file", "$tmp/".$base)) { + $error = sprintf($this->getLang('error_decompress'), $file); + } + + // search $tmp/$base for the folder(s) that has been created + // move the folder(s) to lib/.. + if(!$error) { + $result = array('old'=>array(), 'new'=>array()); + + if(!$this->find_folders($result, $tmp.'/'.$base, ($this->isTemplate() ? 'template' : 'plugin'))) { + $error = $this->getLang('error_findfolder'); + + } else { + // choose correct result array + if(count($result['new'])) { + $install = $result['new']; + }else{ + $install = $result['old']; + } + + // now install all found items + foreach($install as $item) { + // where to install? + if($item['type'] == 'template') { + $target_base_dir = DOKU_TPLLIB; + }else{ + $target_base_dir = DOKU_PLUGIN; + } + + if(!empty($item['base'])) { + // use base set in info.txt + } elseif($base && count($install) == 1) { + $item['base'] = $base; + } else { + // default - use directory as found in zip + // plugins from github/master without *.info.txt will install in wrong folder + // but using $info->id will make 'code3' fail (which should install in lib/code/..) + $item['base'] = basename($item['tmp']); + } + + // check to make sure we aren't overwriting anything + $target = $target_base_dir.$item['base']; + if(!$overwrite && @file_exists($target)) { + // TODO remember our settings, ask the user to confirm overwrite + continue; + } + + $action = @file_exists($target) ? 'update' : 'install'; + + // copy action + if($this->dircopy($item['tmp'], $target)) { + // TODO: write manager.dat! + $installed_extensions[$item['base']] = array('type' => $item['type'], 'action' => $action); + } else { + $error = sprintf($this->getLang('error_copy').DOKU_LF, $item['base']); + break; + } + } + } + } + + // cleanup + if($tmp) $this->dir_delete($tmp); + + if($error) { + return $error; + } + + return true; + } + + /** + * Find out what was in the extracted directory + * + * Correct folders are searched recursively using the "*.info.txt" configs + * as indicator for a root folder. When such a file is found, it's base + * setting is used (when set). All folders found by this method are stored + * in the 'new' key of the $result array. + * + * For backwards compatibility all found top level folders are stored as + * in the 'old' key of the $result array. + * + * When no items are found in 'new' the copy mechanism should fall back + * the 'old' list. + * + * @author Andreas Gohr + * @param array $result - results are stored here + * @param string $base - the temp directory where the package was unpacked to + * @param string $default_type - type used if no info.txt available + * @param string $dir - a subdirectory. do not set. used by recursion + * @return bool - false on error + */ + private function find_folders(&$result, $base, $default_type, $dir='') { + $this_dir = "$base$dir"; + $dh = @opendir($this_dir); + if(!$dh) return false; + + $found_dirs = array(); + $found_files = 0; + $found_template_parts = 0; + $found_info_txt = false; + while (false !== ($f = readdir($dh))) { + if($f == '.' || $f == '..') continue; + + if(is_dir("$this_dir/$f")) { + $found_dirs[] = "$dir/$f"; + + } else { + // it's a file -> check for config + $found_files++; + switch ($f) { + case 'plugin.info.txt': + case 'template.info.txt': + $found_info_txt = true; + $info = array(); + $type = explode('.', $f, 2); + $info['type'] = $type[0]; + $info['tmp'] = $this_dir; + $conf = confToHash("$this_dir/$f"); + $info['base'] = basename($conf['base']); + $result['new'][] = $info; + break; + + case 'main.php': + case 'details.php': + case 'mediamanager.php': + case 'style.ini': + $found_template_parts++; + break; + } + } + } + closedir($dh); + + // URL downloads default to 'plugin', try extra hard to indentify templates + if(!$default_type && $found_template_parts > 2 && !$found_info_txt) { + $info = array(); + $info['type'] = 'template'; + $info['tmp'] = $this_dir; + $result['new'][] = $info; + } + + // files in top level but no info.txt, assume this is zip missing a base directory + // works for all downloads unless direct URL where $base will be the tmp directory ($info->id was empty) + if(!$dir && $found_files > 0 && !$found_info_txt && $default_type) { + $info = array(); + $info['type'] = $default_type; + $info['tmp'] = $base; + $result['old'][] = $info; + return true; + } + + foreach ($found_dirs as $found_dir) { + // if top level add to dir list for old method, then recurse + if(!$dir) { + $info = array(); + $info['type'] = ($default_type ? $default_type : 'plugin'); + $info['tmp'] = "$base$found_dir"; + $result['old'][] = $info; + } + $this->find_folders($result, $base, $default_type, "$found_dir"); + } + return true; + } + + + /** + * Decompress a given file to the given target directory + * + * Determines the compression type from the file extension + */ + private function decompress($file, $target) { + // decompression library doesn't like target folders ending in "/" + if(substr($target, -1) == "/") $target = substr($target, 0, -1); + + $ext = $this->guess_archive($file); + if(in_array($ext, array('tar', 'bz', 'gz'))) { + switch($ext) { + case 'bz': + $compress_type = Tar::COMPRESS_BZIP; + break; + case 'gz': + $compress_type = Tar::COMPRESS_GZIP; + break; + default: + $compress_type = Tar::COMPRESS_NONE; + } + + $tar = new Tar(); + try { + $tar->open($file, $compress_type); + $tar->extract($target); + } catch (Exception $e) { + return $e->getMessage(); + } + + return true; + } elseif($ext == 'zip') { + + $zip = new ZipLib(); + $ok = $zip->Extract($file, $target); + + return ($ok==-1 ? 'Error extracting the zip archive' : true); + } + + // the only case when we don't get one of the recognized archive types is when the archive file can't be read + return 'Couldn\'t read archive file'; + } + + /** + * Determine the archive type of the given file + * + * Reads the first magic bytes of the given file for content type guessing, + * if neither bz, gz or zip are recognized, tar is assumed. + * + * @author Andreas Gohr + * @param string $file The file to analyze + * @return string|bool false if the file can't be read, otherwise an "extension" + */ + private function guess_archive($file) { + $fh = fopen($file, 'rb'); + if(!$fh) return false; + $magic = fread($fh, 5); + fclose($fh); + + if(strpos($magic, "\x42\x5a") === 0) return 'bz'; + if(strpos($magic, "\x1f\x8b") === 0) return 'gz'; + if(strpos($magic, "\x50\x4b\x03\x04") === 0) return 'zip'; + return 'tar'; + } + + /** + * Copy with recursive sub-directory support + */ + private function dircopy($src, $dst) { + global $conf; + + if(is_dir($src)) { + if(!$dh = @opendir($src)) return false; + + if($ok = io_mkdir_p($dst)) { + while ($ok && (false !== ($f = readdir($dh)))) { + if($f == '..' || $f == '.') continue; + $ok = $this->dircopy("$src/$f", "$dst/$f"); + } + } + + closedir($dh); + return $ok; + + } else { + $exists = @file_exists($dst); + + if(!@copy($src, $dst)) return false; + if(!$exists && !empty($conf['fperm'])) chmod($dst, $conf['fperm']); + @touch($dst, filemtime($src)); + } + + return true; + } } // vim:ts=4:sw=4:et: diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 81069e498..f0999ff01 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -17,5 +17,11 @@ $lang['unknownauthor'] = 'Unknown author'; $lang['unknownversion'] = 'Unknown version'; +$lang['error_badurl'] = 'URL ends with slash - unable to determine file name from the url'; +$lang['error_dircreate'] = 'Unable to create temporary folder to receive download'; +$lang['error_download'] = 'Unable to download the file: %s'; +$lang['error_decompress'] = 'Unable to decompress the downloaded file. This maybe as a result of a bad download, in which case you should try again; or the compression format may be unknown, in which case you will need to download and install manually'; +$lang['error_findfolder'] = 'Unable to identify extension directory, you need to download and install manually'; +$lang['error_copy'] = 'There was a file copy error while attempting to install files for directory %s: the disk could be full or file access permissions may be incorrect. This may have resulted in a partially installed plugin and leave your wiki installation unstable'; //Setup VIM: ex: et ts=4 : -- cgit v1.2.3 From 2a2a2ba2f6092b0b68a7de0ccc798062682487f4 Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Fri, 2 Aug 2013 21:35:13 +0100 Subject: added basic suport for embedding (html5) videos --- lib/images/fileicons/mp4.png | Bin 0 -> 740 bytes lib/images/fileicons/ogv.png | Bin 0 -> 740 bytes lib/images/fileicons/webm.png | Bin 0 -> 740 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 lib/images/fileicons/mp4.png create mode 100644 lib/images/fileicons/ogv.png create mode 100644 lib/images/fileicons/webm.png (limited to 'lib') diff --git a/lib/images/fileicons/mp4.png b/lib/images/fileicons/mp4.png new file mode 100644 index 000000000..b89fc5299 Binary files /dev/null and b/lib/images/fileicons/mp4.png differ diff --git a/lib/images/fileicons/ogv.png b/lib/images/fileicons/ogv.png new file mode 100644 index 000000000..b89fc5299 Binary files /dev/null and b/lib/images/fileicons/ogv.png differ diff --git a/lib/images/fileicons/webm.png b/lib/images/fileicons/webm.png new file mode 100644 index 000000000..b89fc5299 Binary files /dev/null and b/lib/images/fileicons/webm.png differ -- cgit v1.2.3 From 02779b18797b2ee1304613de684d54988815dacb Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Fri, 2 Aug 2013 23:30:32 +0200 Subject: Extension manager: Implement extension table This uses a lot of code and the whole design from the previous extension manager implementation. --- lib/plugins/extension/admin.php | 78 ++++- lib/plugins/extension/helper/extension.php | 189 ++++++++++-- lib/plugins/extension/helper/list.php | 477 +++++++++++++++++++++++++++++ lib/plugins/extension/images/disabled.png | Bin 0 -> 1486 bytes lib/plugins/extension/images/donate.png | Bin 0 -> 1293 bytes lib/plugins/extension/images/down.png | Bin 0 -> 280 bytes lib/plugins/extension/images/enabled.png | Bin 0 -> 1231 bytes lib/plugins/extension/images/icons.xcf | Bin 0 -> 43016 bytes lib/plugins/extension/images/license.txt | 4 + lib/plugins/extension/images/plugin.png | Bin 0 -> 6259 bytes lib/plugins/extension/images/template.png | Bin 0 -> 6802 bytes lib/plugins/extension/images/up.png | Bin 0 -> 281 bytes lib/plugins/extension/lang/en/lang.php | 96 +++++- lib/plugins/extension/style.css | 368 ++++++++++++++++++++++ 14 files changed, 1172 insertions(+), 40 deletions(-) create mode 100644 lib/plugins/extension/helper/list.php create mode 100644 lib/plugins/extension/images/disabled.png create mode 100644 lib/plugins/extension/images/donate.png create mode 100644 lib/plugins/extension/images/down.png create mode 100644 lib/plugins/extension/images/enabled.png create mode 100644 lib/plugins/extension/images/icons.xcf create mode 100644 lib/plugins/extension/images/license.txt create mode 100644 lib/plugins/extension/images/plugin.png create mode 100644 lib/plugins/extension/images/template.png create mode 100644 lib/plugins/extension/images/up.png create mode 100644 lib/plugins/extension/style.css (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 19863e772..373f90183 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -9,7 +9,11 @@ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); +/** + * Admin part of the extension manager + */ class admin_plugin_extension extends DokuWiki_Admin_Plugin { + protected $infoFor = null; /** * @return int sort number in admin menu @@ -26,32 +30,94 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { } /** - * Should carry out any processing required by the plugin. + * Execute the requested action(s) and initialize the plugin repository */ public function handle() { + global $INPUT; + // initialize the remote repository /* @var helper_plugin_extension_repository $repository */ $repository = $this->loadHelper('extension_repository'); $repository->init(); + + /* @var helper_plugin_extension_extension $extension */ + $extension = $this->loadHelper('extension_extension'); + + if ($INPUT->post->has('fn')) { + $actions = $INPUT->post->arr('fn'); + foreach ($actions as $action => $extensions) { + foreach ($extensions as $extname => $label) { + switch ($action) { + case 'info': + $this->infoFor = $extname; + break; + case 'install': + msg('Not implemented'); + break; + case 'reinstall': + case 'update': + $extension->setExtension($extname, false); + $status = $extension->installOrUpdate(); + if ($status !== true) { + msg($status, -1); + } else { + msg(sprintf($this->getLang('msg_update_success'), hsc($extension->getName())), 1); + } + break; + case 'uninstall': + $extension->setExtension($extname, false); + $status = $extension->uninstall(); + if ($status !== true) { + msg($status, -1); + } else { + msg(sprintf($this->getLang('msg_delete_success'), hsc($extension->getName())), 1); + } + break; + case 'enable'; + $extension->setExtension($extname, false); + $status = $extension->enable(); + if ($status !== true) { + msg($status, -1); + } else { + msg(sprintf($this->getLang('msg_enabled'), hsc($extension->getName())), 1); + } + break; + case 'disable'; + $extension->setExtension($extname, false); + $status = $extension->disable(); + if ($status !== true) { + msg($status, -1); + } else { + msg(sprintf($this->getLang('msg_disabled'), hsc($extension->getName())), 1); + } + break; + } + } + } + } } /** - * Render HTML output, e.g. helpful text and a form + * Render HTML output */ public function html() { /* @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; ptln('

'.$this->getLang('menu').'

'); + ptln('
'); $pluginlist = $plugin_controller->getList('', true); /* @var helper_plugin_extension_extension $extension */ $extension = $this->loadHelper('extension_extension'); + /* @var helper_plugin_extension_list $list */ + $list = $this->loadHelper('extension_list'); + $list->start_form(); foreach ($pluginlist as $name) { $extension->setExtension($name, false); - ptln('

'.hsc($extension->getName()).'

'); - ptln('

'.hsc($extension->getDescription()).'

'); - ptln('

Latest available version: '.hsc($extension->getLastUpdate()).'

'); - ptln('

Installed version: '.hsc($extension->getInstalledVersion()).'

'); + $list->add_row($extension, $name == $this->infoFor); } + $list->end_form(); + $list->render(); + ptln('
'); } } diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index b80e56a4d..093ee7828 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -64,6 +64,35 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { return is_dir($this->getInstallDir()); } + /** + * If the extension is bundled + * + * @return bool If the extension is bundled + */ + public function isBundled() { + if (!empty($this->remoteInfo['bundled'])) return $this->remoteInfo['bundled']; + return in_array($this->name, + array('acl', 'info', 'extension', 'test', 'revert', 'popularity', 'config', 'plugin', 'safefnrecode', 'authplain')); + } + + /** + * If the extension is protected + * + * @return bool if the extension is protected + */ + public function isProtected() { + return in_array($this->name, array('acl', 'config', 'info', 'plugin', 'revert', 'usermanager')); + } + + /** + * If the extension is installed in the correct directory + * + * @return bool If the extension is installed in the correct directory + */ + public function isInWrongFolder() { + return $this->name != $this->getBase(); + } + /** * If the extension is enabled * @@ -97,6 +126,15 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { return $this->is_template; } + /** + * Get the name of the installation directory + * + * @return string The name of the installation directory + */ + public function getInstallName() { + return $this->name; + } + // Data from plugin.info.txt/template.info.txt or the repo when not available locally /** * Get the basename of the extension @@ -104,6 +142,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The basename */ public function getBase() { + if (!empty($this->localInfo['base'])) return $this->localInfo['base']; return $this->name; } @@ -113,20 +152,20 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The display name */ public function getName() { - if (isset($this->localInfo['name'])) return $this->localInfo['name']; - if (isset($this->remoteInfo['name'])) return $this->remoteInfo['name']; + if (!empty($this->localInfo['name'])) return $this->localInfo['name']; + if (!empty($this->remoteInfo['name'])) return $this->remoteInfo['name']; return $this->name; } /** * Get the author name of the extension * - * @return string The name of the author + * @return string|bool The name of the author or false if there is none */ public function getAuthor() { - if (isset($this->localInfo['author'])) return $this->localInfo['author']; - if (isset($this->remoteInfo['author'])) return $this->remoteInfo['author']; - return $this->getLang('unknownauthor'); + if (!empty($this->localInfo['author'])) return $this->localInfo['author']; + if (!empty($this->remoteInfo['author'])) return $this->remoteInfo['author']; + return false; } /** @@ -136,7 +175,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function getEmail() { // email is only in the local data - if (isset($this->localInfo['email'])) return $this->localInfo['email']; + if (!empty($this->localInfo['email'])) return $this->localInfo['email']; return false; } @@ -146,8 +185,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The md5sum of the email if there is any, false otherwise */ public function getEmailID() { - if (isset($this->remoteInfo['emailid'])) return $this->remoteInfo['emailid']; - if (isset($this->localInfo['email'])) return md5($this->localInfo['email']); + if (!empty($this->remoteInfo['emailid'])) return $this->remoteInfo['emailid']; + if (!empty($this->localInfo['email'])) return md5($this->localInfo['email']); return false; } @@ -157,8 +196,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The description */ public function getDescription() { - if (isset($this->localInfo['desc'])) return $this->localInfo['desc']; - if (isset($this->remoteInfo['description'])) return $this->remoteInfo['description']; + if (!empty($this->localInfo['desc'])) return $this->localInfo['desc']; + if (!empty($this->remoteInfo['description'])) return $this->remoteInfo['description']; return ''; } @@ -168,8 +207,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The URL */ public function getURL() { - if (isset($this->localInfo['url'])) return $this->localInfo['url']; - return 'https://www.dokuwiki.org/plugin:'.$this->name; + if (!empty($this->localInfo['url'])) return $this->localInfo['url']; + return 'https://www.dokuwiki.org/'.($this->isTemplate() ? 'template' : 'plugin').':'.$this->getBase(); } /** @@ -178,28 +217,66 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The version, usually in the form yyyy-mm-dd if there is any */ public function getInstalledVersion() { - if (isset($this->localInfo['date'])) return $this->localInfo['date']; + if (!empty($this->localInfo['date'])) return $this->localInfo['date']; if ($this->isInstalled()) return $this->getLang('unknownversion'); return false; } + /** + * Get the install date of the current version + * + * @return string|bool The date of the last update or false if not available + */ + public function getUpdateDate() { + if (!empty($this->managerData['updated'])) return $this->managerData['updated']; + return false; + } + + /** + * Get the date of the installation of the plugin + * + * @return string|bool The date of the installation or false if not available + */ + public function getInstallDate() { + if (!empty($this->managerData['installed'])) return $this->managerData['installed']; + return false; + } + /** * Get the names of the dependencies of this extension * * @return array The base names of the dependencies */ public function getDependencies() { - if (isset($this->remoteInfo['dependencies'])) return $this->remoteInfo['dependencies']; + if (!empty($this->remoteInfo['dependencies'])) return $this->remoteInfo['dependencies']; return array(); } + /** + * Get the names of the missing dependencies + * + * @return array The base names of the missing dependencies + */ + public function getMissingDependencies() { + /* @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; + $dependencies = $this->getDependencies(); + $missing_dependencies = array(); + foreach ($dependencies as $dependency) { + if ($plugin_controller->isdisabled($dependency)) { + $missing_dependencies[] = $dependency; + } + } + return $missing_dependencies; + } + /** * Get the names of all conflicting extensions * * @return array The names of the conflicting extensions */ public function getConflicts() { - if (isset($this->remoteInfo['conflicts'])) return $this->remoteInfo['dependencies']; + if (!empty($this->remoteInfo['conflicts'])) return $this->remoteInfo['dependencies']; return array(); } @@ -209,7 +286,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return array The names of similar extensions */ public function getSimilarExtensions() { - if (isset($this->remoteInfo['similar'])) return $this->remoteInfo['similar']; + if (!empty($this->remoteInfo['similar'])) return $this->remoteInfo['similar']; return array(); } @@ -219,17 +296,28 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return array The names of the tags of the extension */ public function getTags() { - if (isset($this->remoteInfo['tags'])) return $this->remoteInfo['tags']; + if (!empty($this->remoteInfo['tags'])) return $this->remoteInfo['tags']; return array(); } + /** + * Get the popularity information as floating point number [0,1] + * + * @return float|bool The popularity information or false if it isn't available + */ + public function getPopularity() { + if (!empty($this->remoteInfo['popularity'])) return $this->remoteInfo['popularity']/200.0; + return false; + } + + /** * Get the text of the security warning if there is any * * @return string|bool The security warning if there is any, false otherwise */ public function getSecurityWarning() { - if (isset($this->remoteInfo['securitywarning'])) return $this->remoteInfo['securitywarning']; + if (!empty($this->remoteInfo['securitywarning'])) return $this->remoteInfo['securitywarning']; return false; } @@ -239,7 +327,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The security issue if there is any, false otherwise */ public function getSecurityIssue() { - if (isset($this->remoteInfo['securityissue'])) return $this->remoteInfo['securityissue']; + if (!empty($this->remoteInfo['securityissue'])) return $this->remoteInfo['securityissue']; return false; } @@ -249,17 +337,26 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The screenshot URL if there is any, false otherwise */ public function getScreenshotURL() { - if (isset($this->remoteInfo['screenshoturl'])) return $this->remoteInfo['screenshoturl']; + if (!empty($this->remoteInfo['screenshoturl'])) return $this->remoteInfo['screenshoturl']; return false; } + /** + * Get the URL of the thumbnail of the extension if there is any + * + * @return string|bool The thumbnail URL if there is any, false otherwise + */ + public function getThumbnailURL() { + if (!empty($this->remoteInfo['thumbnailurl'])) return $this->remoteInfo['thumbnailurl']; + return false; + } /** * Get the last used download URL of the extension if there is any * * @return string|bool The previously used download URL, false if the extension has been installed manually */ public function getLastDownloadURL() { - if (isset($this->managerData['downloadurl'])) return $this->managerData['downloadurl']; + if (!empty($this->managerData['downloadurl'])) return $this->managerData['downloadurl']; return false; } @@ -269,17 +366,28 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The download URL if there is any, false otherwise */ public function getDownloadURL() { - if (isset($this->remoteInfo['downloadurl'])) return $this->remoteInfo['downloadurl']; + if (!empty($this->remoteInfo['downloadurl'])) return $this->remoteInfo['downloadurl']; return false; } + /** + * If the download URL has changed since the last download + * + * @return bool If the download URL has changed + */ + public function hasDownloadURLChanged() { + $lasturl = $this->getLastDownloadURL(); + $currenturl = $this->getDownloadURL(); + return ($lasturl && $currenturl && $lasturl != $currenturl); + } + /** * Get the bug tracker URL of the extension if there is any * * @return string|bool The bug tracker URL if there is any, false otherwise */ public function getBugtrackerURL() { - if (isset($this->remoteInfo['bugtracker'])) return $this->remoteInfo['bugtracker']; + if (!empty($this->remoteInfo['bugtracker'])) return $this->remoteInfo['bugtracker']; return false; } @@ -289,7 +397,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The URL of the source repository if there is any, false otherwise */ public function getSourcerepoURL() { - if (isset($this->remoteInfo['sourcerepo'])) return $this->remoteInfo['sourcerepo']; + if (!empty($this->remoteInfo['sourcerepo'])) return $this->remoteInfo['sourcerepo']; return false; } @@ -299,7 +407,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The donation URL if there is any, false otherwise */ public function getDonationURL() { - if (isset($this->remoteInfo['donationurl'])) return $this->remoteInfo['donationurl']; + if (!empty($this->remoteInfo['donationurl'])) return $this->remoteInfo['donationurl']; return false; } @@ -309,7 +417,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return array The type(s) as array of strings */ public function getTypes() { - if (isset($this->remoteInfo['types'])) return explode(', ', $this->remoteInfo['types']); + if (!empty($this->remoteInfo['types'])) return $this->remoteInfo['types']; if ($this->isTemplate()) return array(32 => 'template'); return array(); } @@ -320,7 +428,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return array The versions in the form yyyy-mm-dd => ('label' => label, 'implicit' => implicit) */ public function getCompatibleVersions() { - if (isset($this->remoteInfo['compatible'])) return $this->remoteInfo['compatible']; + if (!empty($this->remoteInfo['compatible'])) return $this->remoteInfo['compatible']; return array(); } @@ -330,7 +438,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string|bool The last available update in the form yyyy-mm-dd if there is any, false otherwise */ public function getLastUpdate() { - if (isset($this->remoteInfo['lastupdate'])) return $this->remoteInfo['lastupdate']; + if (!empty($this->remoteInfo['lastupdate'])) return $this->remoteInfo['lastupdate']; return false; } @@ -392,6 +500,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $status = 'Error, the requested extension hasn\'t been installed or updated'; } $this->setExtension($this->name, $this->isTemplate()); + $this->purgeCache(); } $this->dir_delete(dirname($path)); } @@ -404,6 +513,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool If the plugin was sucessfully installed */ public function uninstall() { + $this->purgeCache(); return $this->dir_delete($this->getInstallDir()); } @@ -417,8 +527,9 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /* @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; if (!$this->isInstalled()) return $this->getLang('notinstalled'); - if (!$this->isEnabled()) return $this->getLang('alreadyenabled'); + if ($this->isEnabled()) return $this->getLang('alreadyenabled'); if ($plugin_controller->enable($this->name)) { + $this->purgeCache(); return true; } else { return $this->getLang('pluginlistsaveerror'); @@ -438,12 +549,24 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { if (!$this->isInstalled()) return $this->getLang('notinstalled'); if (!$this->isEnabled()) return $this->getLang('alreadydisabled'); if ($plugin_controller->disable($this->name)) { + $this->purgeCache(); return true; } else { return $this->getLang('pluginlistsaveerror'); } } + /** + * Purge the cache by touching the main configuration file + */ + protected function purgeCache() { + global $config_cascade; + + // expire dokuwiki caches + // touching local.php expires wiki page, JS and CSS caches + @touch(reset($config_cascade['main']['local'])); + } + /** * Read local extension data either from info.txt or getInfo() */ @@ -463,7 +586,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { foreach($plugin_types as $type) { if(@file_exists($path.$type.'.php')) { - $plugin = plugin_load($type, $this->getBase()); + $plugin = plugin_load($type, $this->name); if ($plugin) break; } @@ -471,7 +594,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { while(false !== ($cp = readdir($dh))) { if($cp == '.' || $cp == '..' || strtolower(substr($cp, -4)) != '.php') continue; - $plugin = plugin_load($type, $this->getBase().'_'.substr($cp, 0, -4)); + $plugin = plugin_load($type, $this->name.'_'.substr($cp, 0, -4)); if ($plugin) break; } if ($plugin) break; @@ -551,7 +674,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { public function download($url, &$path) { // check the url $matches = array(); - if(!preg_match("/[^/]*$/", $url, $matches) || !$matches[0]) { + if(!preg_match("/[^\/]*$/", $url, $matches) || !$matches[0]) { return $this->getLang('baddownloadurl'); } $file = $matches[0]; diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php new file mode 100644 index 000000000..ffb88114d --- /dev/null +++ b/lib/plugins/extension/helper/list.php @@ -0,0 +1,477 @@ + + */ + +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +/** + * Class helper_plugin_extension_extension represents a single extension (plugin or template) + */ +class helper_plugin_extension_list extends DokuWiki_Plugin { + protected $form = ''; + + function start_form() { + $this->form .= '
'; + $hidden = array( + 'do'=>'admin', + 'page'=>'extension', + 'sectok'=>getSecurityToken() + ); + $this->add_hidden($hidden); + $this->form .= '
    '; + } + /** + * Build single row of extension table + * @param helper_plugin_extension_extension $extension The extension that shall be added + * @param bool $showinfo Show the info area + */ + function add_row(helper_plugin_extension_extension $extension, $showinfo = false) { + $this->start_row($extension); + $this->populate_column('legend', $this->make_legend($extension, $showinfo)); + $this->populate_column('actions', $this->make_actions($extension)); + $this->end_row(); + } + + /** + * Adds a header to the form + * + * @param string $id The id of the header + * @param string $header The content of the header + * @param int $level The level of the header + */ + function add_header($id, $header, $level = 2) { + $this->form .=''.hsc($header).''; + } + + /** + * Adds a paragraph to the form + * + * @param string $data The content + */ + function add_p($data) { + $this->form .= '

    '.hsc($data).'

    '; + } + + /** + * Add hidden fields to the form with the given data + * @param array $array + */ + function add_hidden(array $array) { + $this->form .= '
    '; + foreach ($array as $key => $value) { + $this->form .= ''; + } + $this->form .= '
    '; + } + + /** + * Add closing tags + */ + function end_form() { + $this->form .= '
'; + $this->form .= '
'; + } + + /** + * Print the form + */ + function render() { + echo $this->form; + } + + /** + * Start the HTML for the row for the extension + * + * @param helper_plugin_extension_extension $extension The extension + */ + private function start_row(helper_plugin_extension_extension $extension) { + $this->form .= '
  • '; + } + + /** + * Add a column with the given class and content + * @param string $class The class name + * @param string $html The content + */ + private function populate_column($class, $html) { + $this->form .= '
    '.$html.'
    '; + } + + /** + * End the row + */ + private function end_row() { + $this->form .= '
  • '.DOKU_LF; + } + + /** + * Generate the link to the plugin homepage + * + * @param helper_plugin_extension_extension $extension The extension + * @return string The HTML code + */ + function make_homepagelink(helper_plugin_extension_extension $extension) { + $text = $this->getLang('homepage_link'); + $url = hsc($extension->getURL()); + return ''.$text.' '; + } + + /** + * Generate the class name for the row of the extensio + * + * @param helper_plugin_extension_extension $extension The extension object + * @return string The class name + */ + function make_class(helper_plugin_extension_extension $extension) { + $class = ($extension->isTemplate()) ? 'template' : 'plugin'; + if($extension->isInstalled()) { + $class.=' installed'; + $class.= ($extension->isEnabled()) ? ' enabled':' disabled'; + } + if(!$extension->canModify()) $class.= ' notselect'; + if($extension->isProtected()) $class.= ' protected'; + //if($this->showinfo) $class.= ' showinfo'; + return $class; + } + + /** + * Generate a link to the author of the extension + * + * @param helper_plugin_extension_extension $extension The extension object + * @return string The HTML code of the link + */ + function make_author(helper_plugin_extension_extension $extension) { + global $ID; + + if($extension->getAuthor()) { + + $params = array( + 'do'=>'admin', + 'page'=>'extension', + 'tab'=>'search', + 'q'=>'author:'.$extension->getAuthor() + ); + $url = wl($ID, $params); + return ''.hsc($extension->getAuthor()).''; + } + return "".$this->getLang('unknown_author').""; + } + + /** + * Get the link and image tag for the screenshot/thumbnail + * + * @param helper_plugin_extension_extension $extension The extension object + * @return string The HTML code + */ + function make_screenshot(helper_plugin_extension_extension $extension) { + if($extension->getScreenshotURL()) { + $img = ''. + ''.hsc($extension->getName()).''. + ''; + } elseif($extension->isTemplate()) { + $img = 'template'; + + } else { + $img = 'plugin'; + } + return '
    '.$img.'
    '; + } + + /** + * Extension main description + * + * @param helper_plugin_extension_extension $extension The extension object + * @param bool $showinfo Show the info section + * @return string The HTML code + */ + function make_legend(helper_plugin_extension_extension $extension, $showinfo = false) { + $return = '
    '; + $return .= '

    '; + $return .= sprintf($this->getLang('extensionby'), hsc($extension->getName()), $this->make_author($extension)); + $return .= '

    '; + + $return .= $this->make_screenshot($extension); + + $popularity = $extension->getPopularity(); + if ($popularity !== false && !$extension->isBundled()) { + $popularityText = sprintf($this->getLang('popularity'), $popularity); + $return .= '
    '; + } + + $return .= '

    '; + if($extension->getDescription()) { + $return .= hsc($extension->getDescription()).' '; + } + $return .= '

    '; + + $return .= $this->make_linkbar($extension); + $return .= $this->make_action('info', $extension, $showinfo); + if ($showinfo) { + $return .= $this->make_info($extension); + } + $return .= $this->make_noticearea($extension); + $return .= '
    '; + return $return; + } + + /** + * Generate the link bar HTML code + * + * @param helper_plugin_extension_extension $extension The extension instance + * @return string The HTML code + */ + function make_linkbar(helper_plugin_extension_extension $extension) { + $return = ''; + $return .= $this->make_homepagelink($extension); + if ($extension->getBugtrackerURL()) { + $return .= ' '.$this->getLang('bugs_features').' '; + } + foreach ($extension->getTags() as $tag) { + $return .= hsc($tag).' '; //$this->manager->handler->html_taglink($tag); + } + $return .= ''; + return $return; + } + + /** + * Notice area + * + * @param helper_plugin_extension_extension $extension The extension + * @return string The HTML code + */ + function make_noticearea(helper_plugin_extension_extension $extension) { + $return = ''; + $missing_dependencies = $extension->getMissingDependencies(); + if(!empty($missing_dependencies)) { + $return .= '
    '. + sprintf($this->getLang('missing_dependency'), implode(', ', /*array_map(array($this->helper, 'make_extensionsearchlink'),*/ $missing_dependencies)). + '
    '; + } + if($extension->isInWrongFolder()) { + $return .= '
    '. + sprintf($this->getLang('wrong_folder'), hsc($extension->getInstallName()), hsc($extension->getBase())). + '
    '; + } + if(($securityissue = $extension->getSecurityIssue()) !== false) { + $return .= '
    '. + sprintf($this->getLang('security_issue'), hsc($securityissue )). + '
    '; + } + if(($securitywarning = $extension->getSecurityWarning()) !== false) { + $return .= '
    '. + sprintf($this->getLang('security_warning'), hsc($securitywarning)). + '
    '; + } + if($extension->updateAvailable()) { + $return .= '
    '. + sprintf($this->getLang('update_available'), hsc($extension->getLastUpdate())). + '
    '; + } + if($extension->hasDownloadURLChanged()) { + $return .= '
    '. + sprintf($this->getLang('url_change'), hsc($extension->getDownloadURL()), hsc($extension->getLastDownloadURL())). + '
    '; + } + return $return; + } + + /** + * Create a link from the given URL + * + * Shortens the URL for display + * + * @param string $url + * + * @return string HTML link + */ + function shortlink($url){ + $link = parse_url($url); + + $base = $link['host']; + if($link['port']) $base .= $base.':'.$link['port']; + $long = $link['path']; + if($link['query']) $long .= $link['query']; + + $name = shorten($base, $long, 55); + + return ''.hsc($name).''; + } + + /** + * Plugin/template details + * + * @param helper_plugin_extension_extension $extension The extension + * @return string The HTML code + */ + function make_info(helper_plugin_extension_extension $extension) { + $default = $this->getLang('unknown'); + $return = '
    '; + + if (!$extension->isBundled()) { + $return .= '
    '.$this->getLang('downloadurl').'
    '; + $return .= '
    '; + $return .= ($extension->getDownloadURL() ? $this->shortlink($extension->getDownloadURL()) : $default); + $return .= '
    '; + + $return .= '
    '.$this->getLang('repository').'
    '; + $return .= '
    '; + $return .= ($extension->getSourcerepoURL() ? $this->shortlink($extension->getSourcerepoURL()) : $default); + $return .= '
    '; + } + + if ($extension->isInstalled()) { + if ($extension->getInstalledVersion()) { + $return .= '
    '.$this->getLang('installed_version').'
    '; + $return .= '
    '; + $return .= hsc($extension->getInstalledVersion()); + $return .= '
    '; + } else { + $return .= '
    '.$this->getLang('install_date').'
    '; + $return .= '
    '; + $return .= ($extension->getUpdateDate() ? hsc($extension->getUpdateDate()) : $this->getLang('unknown')); + $return .= '
    '; + } + } + if (!$extension->isInstalled() || $extension->updateAvailable()) { + $return .= '
    '.$this->getLang('available_version').'
    '; + $return .= '
    '; + $return .= ($extension->getLastUpdate() ? hsc($extension->getLastUpdate()) : $this->getLang('unknown')); + $return .= '
    '; + } + + if($extension->getInstallDate()) { + $return .= '
    '.$this->getLang('installed').'
    '; + $return .= '
    '; + $return .= hsc($extension->getInstallDate()); + $return .= '
    '; + } + + $return .= '
    '.$this->getLang('provides').'
    '; + $return .= '
    '; + $return .= ($extension->getTypes() ? hsc(implode(', ', $extension->getTypes())) : $default); + $return .= '
    '; + + if($extension->getCompatibleVersions()) { + $return .= '
    '.$this->getLang('compatible').'
    '; + $return .= '
    '; + foreach ($extension->getCompatibleVersions() as $date => $version) { + $return .= $version['label'].' ('.$date.'), '; + } + $return .= '
    '; + } + if($extension->getDependencies()) { + $return .= '
    '.$this->getLang('depends').'
    '; + $return .= '
    '; + $return .= $this->make_linklist($extension->getDependencies()); + $return .= '
    '; + } + + if($extension->getSimilarExtensions()) { + $return .= '
    '.$this->getLang('similar').'
    '; + $return .= '
    '; + $return .= $this->make_linklist($extension->getSimilarExtensions()); + $return .= '
    '; + } + + if($extension->getConflicts()) { + $return .= '
    '.$this->getLang('conflicts').'
    '; + $return .= '
    '; + $return .= $this->make_linklist($extension->getConflicts()); + $return .= '
    '; + } + if ($extension->getDonationURL()) { + $return .= ''; + } + $return .= '
    '; + return $return; + } + + /** + * Generate a list of links for extensions + * @param array $links The links + * @return string The HTML code + */ + function make_linklist($links) { + $return = ''; + foreach ($links as $link) { + $dokulink = hsc($link); + if (strpos($link, 'template:') !== 0) $dokulink = 'plugin:'.$dokulink; + $return .= ''.$link.' '; + } + return $return; + } + + /** + * Display the action buttons if they are possible + * + * @param helper_plugin_extension_extension $extension The extension + * @return string The HTML code + */ + function make_actions(helper_plugin_extension_extension $extension) { + $return = ''; + if (!$extension->isInstalled() && $extension->canModify() === true) { + $return .= $this->make_action('install', $extension); + } elseif ($extension->canModify()) { + if (!$extension->isBundled()) { + $return .= $this->make_action('uninstall', $extension); + if ($extension->getDownloadURL()) { + if ($extension->updateAvailable()) { + $return .= $this->make_action('update', $extension); + } else { + $return .= $this->make_action('reinstall', $extension); + } + } + } + if (!$extension->isProtected()) { + if ($extension->isEnabled()) { + $return .= $this->make_action('disable', $extension); + } else { + $return .= $this->make_action('enable', $extension); + } + } + } + + if (!$extension->isInstalled()) { + $return .= ' '.$this->getLang('available_version').' '; + $return .= ($extension->getLastUpdate() ? hsc($extension->getLastUpdate()) : $this->getLang('unknown')).''; + } + + return $return; + } + + /** + * Display an action button for an extension + * + * @param string $action The action + * @param helper_plugin_extension_extension $extension The extension + * @param bool $showinfo If the info block is shown + * @return string The HTML code + */ + function make_action($action, $extension, $showinfo = false) { + $title = $revertAction = $extraClass = ''; + + switch ($action) { + case 'info': + $title = 'title="'.$this->getLang('btn_info').'"'; + if ($showinfo) { + $revertAction = '-'; + $extraClass = 'close'; + } + break; + case 'install': + case 'reinstall': + $title = 'title="'.$extension->getDownloadURL().'"'; + break; + } + + $classes = 'button '.$action.' '.$extraClass; + $name = 'fn['.$action.']['.$revertAction.hsc($extension->getInstallName()).']'; + + return ''; + } +} diff --git a/lib/plugins/extension/images/disabled.png b/lib/plugins/extension/images/disabled.png new file mode 100644 index 000000000..7a0dbb3b5 Binary files /dev/null and b/lib/plugins/extension/images/disabled.png differ diff --git a/lib/plugins/extension/images/donate.png b/lib/plugins/extension/images/donate.png new file mode 100644 index 000000000..b26ceb66e Binary files /dev/null and b/lib/plugins/extension/images/donate.png differ diff --git a/lib/plugins/extension/images/down.png b/lib/plugins/extension/images/down.png new file mode 100644 index 000000000..df7beda4e Binary files /dev/null and b/lib/plugins/extension/images/down.png differ diff --git a/lib/plugins/extension/images/enabled.png b/lib/plugins/extension/images/enabled.png new file mode 100644 index 000000000..7c051cda1 Binary files /dev/null and b/lib/plugins/extension/images/enabled.png differ diff --git a/lib/plugins/extension/images/icons.xcf b/lib/plugins/extension/images/icons.xcf new file mode 100644 index 000000000..a99747d81 Binary files /dev/null and b/lib/plugins/extension/images/icons.xcf differ diff --git a/lib/plugins/extension/images/license.txt b/lib/plugins/extension/images/license.txt new file mode 100644 index 000000000..254b9cdf6 --- /dev/null +++ b/lib/plugins/extension/images/license.txt @@ -0,0 +1,4 @@ +enabled.png - CC-BY-ND, (c) Emey87 http://www.iconfinder.com/icondetails/65590/48/lightbulb_icon +disabled.png - CC-BY-ND, (c) Emey87 http://www.iconfinder.com/icondetails/65589/48/idea_lightbulb_off_icon +plugin.png - public domain, (c) nicubunu, http://openclipart.org/detail/15093/blue-jigsaw-piece-07-by-nicubunu +template.png - public domain, (c) mathec, http://openclipart.org/detail/166596/palette-by-mathec diff --git a/lib/plugins/extension/images/plugin.png b/lib/plugins/extension/images/plugin.png new file mode 100644 index 000000000..b9133681f Binary files /dev/null and b/lib/plugins/extension/images/plugin.png differ diff --git a/lib/plugins/extension/images/template.png b/lib/plugins/extension/images/template.png new file mode 100644 index 000000000..383c4d0a3 Binary files /dev/null and b/lib/plugins/extension/images/template.png differ diff --git a/lib/plugins/extension/images/up.png b/lib/plugins/extension/images/up.png new file mode 100644 index 000000000..ec9337715 Binary files /dev/null and b/lib/plugins/extension/images/up.png differ diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index f0999ff01..b3a451ecc 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -3,6 +3,7 @@ * English language file for extension plugin * * @author Michael Hamann + * @author Christopher Smith */ // menu entry for admin plugins @@ -16,6 +17,100 @@ $lang['pluginlistsaveerror'] = 'There was an error saving the plugin list'; $lang['unknownauthor'] = 'Unknown author'; $lang['unknownversion'] = 'Unknown version'; +// extension list +$lang['btn_info'] = 'Show more info'; +$lang['btn_update'] = 'Update'; +$lang['btn_uninstall'] = 'Uninstall'; +$lang['btn_enable'] = 'Enable'; +$lang['btn_disable'] = 'Disable'; +//$lang['btn_disable_all'] = 'Disable all'; +//$lang['btn_settings'] = 'Settings'; +$lang['btn_install'] = 'Install'; +$lang['btn_reinstall'] = 'Re-install'; +//$lang['btn_disdown'] = 'Download as Disabled'; +//$lang['btn_dependown'] = 'Download with dependencies'; + +$lang['extensionby'] = '%s by %s'; +$lang['popularity'] = 'Popularity: %s'; +$lang['homepage_link'] = 'Docs'; +$lang['bugs_features'] = 'Bugs'; +$lang['author_hint'] = 'Search extensions by this author'; +$lang['tag_hint'] = 'Search extensions with this tag'; +$lang['installed'] = 'Installed:'; +$lang['lastupdate'] = 'Last updated:'; +$lang['downloadurl'] = 'Download URL:'; +$lang['repository'] = 'Repository:'; +$lang['unknown'] = 'unknown'; +$lang['installed_version'] = 'Installed version:'; +$lang['install_date'] = 'Your last update:'; +$lang['available_version'] = 'Version:'; +$lang['compatible'] = 'Compatible with:'; +$lang['depends'] = 'Depends on:'; +$lang['similar'] = 'Similar to:'; +$lang['conflicts'] = 'Conflicts with:'; +$lang['donate'] = 'Donate'; +$lang['bundled'] = 'bundled'; +$lang['manual_install'] = 'manual install'; + +$lang['msg_tpl_uninstalled'] = 'Template %s uninstalled'; +$lang['msg_tpl_uninstalled'] = 'Template %s could not be uninstalled'; +$lang['msg_uninstalled'] = 'Plugin %s uninstalled'; +$lang['msg_uninstalled'] = 'Plugin %s could not be uninstalled'; + +$lang['msg_tpl_enabled'] = 'Template %s enabled'; +$lang['msg_tpl_notenabled'] = 'Template %s could not be enabled, check file permissions'; +$lang['msg_enabled'] = 'Plugin %s enabled'; +$lang['msg_notenabled'] = 'Plugin %s could not be enabled, check file permissions'; + +$lang['msg_disabled'] = 'Plugin %s disabled'; +$lang['msg_notdisabled'] = 'Plugin %s could not be disabled, check file permissions'; + +$lang['msg_url_failed'] = 'URL [%s] could not be downloaded.
    %s'; +$lang['msg_download_failed'] = 'Plugin %s could not be downloaded.
    %s'; +$lang['msg_download_success'] = 'Plugin %s installed successfully'; +$lang['msg_tpl_download_failed'] = 'Template %s could not be downloaded.
    %s'; +$lang['msg_tpl_download_success'] = 'Template %s installed successfully'; +$lang['msg_download_pkg_success'] = '%s extension package successfully installed (%s)'; +$lang['msg_tpl_download_pkg_success'] = '%s extension package successfully installed (%s)'; + +$lang['msg_update_success'] = 'Plugin %s successfully updated'; +$lang['msg_update_failed'] = 'Update of plugin %s failed.
    %s'; +$lang['msg_tpl_update_success'] = 'Template %s successfully updated'; +$lang['msg_tpl_update_failed'] = 'Update of template %s failed.
    %s'; +$lang['msg_update_pkg_success'] = '%s extension package successfully updated (%s)'; +$lang['msg_tpl_update_pkg_success'] = '%s extension package successfully updated (%s)'; + +$lang['msg_reinstall_success'] = 'Plugin %s re-installed successfully'; +$lang['msg_reinstall_failed'] = 'Failed to re-install plugin %s.
    %s'; +$lang['msg_tpl_reinstall_success'] = 'Template %s re-installed successfully'; +$lang['msg_tpl_reinstall_failed'] = 'Failed to re-install template %s.
    %s'; +$lang['msg_reinstall_pkg_success'] = '%s extension package successfully reinstalled (%s)'; +$lang['msg_tpl_reinstall_pkg_success'] = '%s extension package successfully reinstalled (%s)'; + +// info titles +$lang['plugin'] = 'Plugin'; +$lang['provides'] = 'Provides:'; +$lang['noinfo'] = 'This plugin returned no information, it may be invalid.'; +$lang['name'] = 'Name:'; +$lang['date'] = 'Date:'; +$lang['type'] = 'Type:'; +$lang['desc'] = 'Description:'; +$lang['author'] = 'Author:'; +$lang['www'] = 'Web:'; + +// error messages +$lang['needed_by'] = 'Needed by:'; +$lang['not_writable'] = 'DokuWiki can not write to the folder'; +$lang['missing_dependency'] = 'Missing or disabled dependency: %s'; +$lang['security_issue'] = 'Security Issue: %s'; +$lang['security_warning'] = 'Security Warning: %s'; +$lang['update_available'] = 'Update: New version %s is available.'; +$lang['wrong_folder'] = 'Plugin installed incorrectly: Rename plugin directory "%s" to "%s".'; +$lang['url_change'] = 'URL changed: Download URL has changed since last download. Check if the new URL is valid before updating the extension.
    New: %s
    Old: %s'; +$lang['gitmanaged'] = 'Extension installed with git'; +$lang['bundled_source'] = 'Bundled with DokuWiki source'; +$lang['no_url'] = 'No download URL'; +$lang['no_manager'] = 'Could not find manager.dat file'; $lang['error_badurl'] = 'URL ends with slash - unable to determine file name from the url'; $lang['error_dircreate'] = 'Unable to create temporary folder to receive download'; @@ -23,5 +118,4 @@ $lang['error_download'] = 'Unable to download the file: %s'; $lang['error_decompress'] = 'Unable to decompress the downloaded file. This maybe as a result of a bad download, in which case you should try again; or the compression format may be unknown, in which case you will need to download and install manually'; $lang['error_findfolder'] = 'Unable to identify extension directory, you need to download and install manually'; $lang['error_copy'] = 'There was a file copy error while attempting to install files for directory %s: the disk could be full or file access permissions may be incorrect. This may have resulted in a partially installed plugin and leave your wiki installation unstable'; - //Setup VIM: ex: et ts=4 : diff --git a/lib/plugins/extension/style.css b/lib/plugins/extension/style.css new file mode 100644 index 000000000..1cce52be8 --- /dev/null +++ b/lib/plugins/extension/style.css @@ -0,0 +1,368 @@ +/* + * Extension plugin styles + * + * @author Christopher Smith + * @author Piyush Mishra + * @author Håkan Sandell + * @author Anika Henke + */ + +/* + * tab support not included in "Angua", copied from _mediamanager.css + */ +#extension__manager .panelHeader { + background-color: __background_alt__; + margin-bottom: 10px; + padding: 10px; + text-align: left; + /* to counter partly missing border of ul.tabs: */ + border-top: 1px solid __border__; + margin-top: -1px; +} + +#extension__manager .panelHeader p { + float: left; + font-weight: normal; + font-size: 1em; + padding: 0; + margin: 0 0 3px; +} +[dir=rtl] #extension__manager .panelHeader p { + float: right; +} + +#extension__manager ul.tabs div.message { + display: inline; + margin: 0 .5em; +} + +/* + * general layout + */ +#extension__manager h2 { + margin-left: 0; +} + +#extension__manager a.taglink { + padding: 1px 4px; + background-color: __background_neu__; + border-radius: 3px; +} +[dir=rtl] #extension__manager a.taglink { + display: inline-block; + line-height: 1.2; +} + +#extension__manager .panelHeader div.error { + margin-top: 0; + float: left; +} +[dir=rtl] #extension__manager .panelHeader div.error { + float: right; +} + +/* + * search & url download forms + */ +#extension__manager form.search, +#extension__manager form.btn_reload { + float: right; +} +[dir=rtl] #extension__manager form.search, +[dir=rtl] #extension__manager form.btn_reload { + float: left; +} + +#extension__manager div.search form.search { + float: none; +} + +#extension__manager .tagcloud { + width: 55%; + float: left; + margin: 0 0.5em 1em 0; +} +[dir=rtl] #extension__manager .tagcloud { + float: right; + margin: 0 0 1em .5em; +} + +#extension__manager .tagcloud a.taglink { + background-color: inherit; +} + +#extension__manager div.search { + width: 44%; + float: left; +} +[dir=rtl] #extension__manager div.search { + float: right; +} + +#extension__manager fieldset { + margin-top: 0.5em; + width: auto; +} + +#extension__manager fieldset p { + margin: 0.5em; + text-align: justify; + font-size: 85%; +} + +/* tag cloud */ +#extension__manager a.cl0 { font-size: 0.7em; } +#extension__manager a.cl1 { font-size: 0.9em; } +#extension__manager a.cl2 { font-size: 1em; } +#extension__manager a.cl3 { font-size: 1.3em; } +#extension__manager a.cl4 { font-size: 1.6em; } +#extension__manager a.cl5 { font-size: 1.9em; } + + +#extension__manager .extensionList input.button { + margin: 0 .3em .3em 0; +} +[dir=rtl] #extension__manager .extensionList input.button { + margin: 0 0 .3em .3em; +} + +/* + * extensions table + */ +#extension__manager .extensionList { + margin-left: 0; + margin-right: 0; + padding: 0; + list-style: none; +} + +#extension__manager .extensionList li { + margin: 0 0 .5em; + padding: 0 0 .5em; + color: __text__; + border-bottom: 1px solid __border__; + overflow: hidden; +} + +#extension__manager .legend { + position: relative; + width: 75%; + float: left; +} +[dir=rtl] #extension__manager .legend { + float: right; +} + +#extension__manager .legend > div { + padding: 0 .5em 0 132px; + border-right: 1px solid __background_alt__; + overflow: hidden; +} +[dir=rtl] #extension__manager .legend > div { + padding: 0 132px 0 .5em; + border-left: 1px solid __background_alt__; + border-right-width: 0; +} + +#extension__manager .enabled div.screenshot span { + background: transparent url(images/enabled.png) no-repeat 2px 2px; +} + +#extension__manager .disabled div.screenshot span { + background: transparent url(images/disabled.png) no-repeat 2px 2px; +} + +#extension__manager .legend div.screenshot { + margin-top: 4px; + margin-left: -132px; + max-width: 120px; + float: left; +} +[dir=rtl] #extension__manager .legend div.screenshot { + margin-left: 0; + margin-right: -132px; + float: right; +} + +#extension__manager .legend div.screenshot span { + min-height: 24px; + min-width: 24px; + position: absolute; + left: 0; +} +[dir=rtl] #extension__manager .legend div.screenshot span { + left: auto; + right: 0; +} + +#extension__manager .legend h2 { + width: 100%; + float: right; + margin: 0.2em 0 0.5em; + font-size: 100%; + font-weight: normal; + border: none; +} +[dir=rtl] #extension__manager .legend h2 { + float: left; +} + +#extension__manager .legend h2 strong { + font-size: 120%; + font-weight: bold; + vertical-align: baseline; +} + +#extension__manager .legend p { + margin: 0 0 0.6em 0; +} + +#extension__manager .legend span.linkbar { + font-size: 85%; +} + +#extension__manager .legend span.linkbar a.urlextern + a.taglink, +#extension__manager .legend span.linkbar a.interwiki + a.taglink { + margin-left: 0.4em; +} +[dir=rtl] #extension__manager .legend span.linkbar a.urlextern + a.taglink, +[dir=rtl] #extension__manager .legend span.linkbar a.interwiki + a.taglink { + margin-left: 0; +} +[dir=rtl] #extension__manager .legend span.linkbar a.urlextern, +[dir=rtl] #extension__manager .legend span.linkbar a.interwiki { + margin-left: .4em; +} + +#extension__manager .legend input.button { + background: transparent url(images/up.png) no-repeat 0 0; + box-shadow: none; + border-width: 0; + height: 14px; + text-indent: -99999px; + float: right; + margin: .5em 0 0; +} +[dir=rtl] #extension__manager .legend input.button { + float: left; + margin: .5em 0 0; +} + +#extension__manager .legend input.button.close { + background: transparent url(images/down.png) no-repeat 0 0; +} + +#extension__manager .legend div.popularity { + background-color: __background__; + border: 1px solid silver; + height: .4em; + margin: 0 auto; + padding: 1px; + width: 5.5em; + position: absolute; + right: .5em; + top: 0.2em; +} +[dir=rtl] #extension__manager .legend div.popularity { + right: auto; + left: .5em; +} + +#extension__manager .legend div.popularity div { + background-color: __border__; + height: 100%; +} + +#extension__manager .legend div.popularity div span { + display: none;/* @todo: hide accessibly */ +} + +#extension__manager .actions { + padding: 0; + font-size: 95%; + width: 25%; + float: right; + text-align: right; +} +[dir=rtl] #extension__manager .actions { + float: left; + text-align: left; +} + +#extension__manager .actions .version { + display: block; +} + +#extension__manager .actions p { + margin: 0.2em 0; + text-align: center; +} + +/* + * extensions table, detailed info box + */ +#extension__manager dl.details { + margin: 0.4em 0 0 0; + font-size: 85%; + border-top: 1px solid __background_alt__; + clear: both; +} + +#extension__manager dl.details dt { + clear: left; + float: left; + width: 25%; + margin: 0; + text-align: right; + font-weight: normal; + padding: 0.2em 5px 0 0; +} +[dir=rtl] #extension__manager dl.details dt { + clear: right; + float: right; + text-align: left; + padding: 0.2em 0 0 5px; +} + +#extension__manager dl.details dd { + margin-left: 25%; + font-weight: bold; + padding: 0.2em 0 0 5px; +} +[dir=rtl] #extension__manager dl.details dd { + margin-left: 0; + margin-right: 25%; + padding: 0.2em 5px 0 0 ; +} + +#extension__manager dl.details dd a { + font-weight: normal; +} + +#extension__manager #info__popup { + z-index: 20; + overflow: hidden; + opacity: 0.9; + border: 1px solid __border__; + background-color: __border__; /*background_other__;*/ + text-align: left; + padding: 0.2em; +} +[dir=rtl] #extension__manager #info__popup { + text-align: right; +} + +#extension__manager div.msg { + margin: 0.4em 0 0 0; +} + +#extension__manager ul.tabs div.msg { + display: inline; + margin-left: 0.4em; +} +[dir=rtl] #extension__manager ul.tabs div.msg { + margin-left: 0; + margin-right: 0.4em; +} + +/* end admin plugin styles */ -- cgit v1.2.3 From d637819dca760b20f6e53e5847a92d08d8d15b8c Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Sun, 4 Aug 2013 10:36:50 +0100 Subject: added spacing below video and audio elements Note: The spacing will now show as too much as long as the paragraph bug is not fixed --- lib/tpl/dokuwiki/css/basic.css | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/tpl/dokuwiki/css/basic.css b/lib/tpl/dokuwiki/css/basic.css index ba263f4c5..ef278c939 100644 --- a/lib/tpl/dokuwiki/css/basic.css +++ b/lib/tpl/dokuwiki/css/basic.css @@ -93,6 +93,8 @@ pre, table, hr, blockquote, +video, +audio, figure, details, fieldset, -- cgit v1.2.3 From dfabb2233685be891929dd4065c257a025dc3151 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 18:20:45 +0200 Subject: added tabURL builder --- lib/plugins/extension/helper/list.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'lib') diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index ffb88114d..e8b4f472f 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -474,4 +474,24 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { return ''; } + + /** + * Create an URL inside the extension manager + * + * @param string tab tb to load, empty for current tab + * @param array $params associative array of parameter to set + * @return string + */ + static public function tabURL($tab='', $params=array()){ + global $ID; + global $INPUT; + + if(!$tab) $tab = $INPUT->str('tab', 'installed', true); + $defaults = array( + 'do' => 'admin', + 'page' => 'extension', + 'tab' => $tab, + ); + return wl($ID, array_merge($defaults, $params)); + } } -- cgit v1.2.3 From b8d600ef317ee91b73133cc7af7a83cf12d5d0d9 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 18:21:08 +0200 Subject: fixed screenshot height --- lib/plugins/extension/style.css | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/plugins/extension/style.css b/lib/plugins/extension/style.css index 1cce52be8..0a3a0cc0e 100644 --- a/lib/plugins/extension/style.css +++ b/lib/plugins/extension/style.css @@ -172,6 +172,11 @@ background: transparent url(images/disabled.png) no-repeat 2px 2px; } +#extension__manager div.screenshot img { + width: 120px; + height: 70px; +} + #extension__manager .legend div.screenshot { margin-top: 4px; margin-left: -132px; -- cgit v1.2.3 From 141407788877f98d4acc6eabc7cc3e831eaa8317 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 18:22:39 +0200 Subject: fixed typo in define --- lib/plugins/extension/helper/repository.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/repository.php b/lib/plugins/extension/helper/repository.php index 37b9bc02c..459d7cbec 100644 --- a/lib/plugins/extension/helper/repository.php +++ b/lib/plugins/extension/helper/repository.php @@ -6,8 +6,10 @@ * @author Michael Hamann */ +define('EXTENSION_REPOSITORY_API', 'http://localhost/dokuwiki/lib/plugins/pluginrepo/api.php'); + if (!defined('EXTENSION_REPOSITORY_API_ENDPOINT')) - define('EXTENSION_REPSITORY_API', 'http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php'); + define('EXTENSION_REPOSITORY_API', 'http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php'); // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); @@ -40,7 +42,7 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { if ($request_needed) { $httpclient = new DokuHTTPClient(); - $data = $httpclient->post(EXTENSION_REPSITORY_API, $request_data); + $data = $httpclient->post(EXTENSION_REPOSITORY_API, $request_data); if ($data !== false) { $extensions = unserialize($data); foreach ($extensions as $extension) { @@ -66,7 +68,7 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { if (!$cache->useCache(array('age' => 3600 * 24))) { $httpclient = new DokuHTTPClient(); $httpclient->timeout = 5; - $data = $httpclient->get(EXTENSION_REPSITORY_API.'?cmd=ping'); + $data = $httpclient->get(EXTENSION_REPOSITORY_API.'?cmd=ping'); if ($data !== false) { $this->has_access = true; $cache->storeCache(1); @@ -93,7 +95,7 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { if (!isset($this->loaded_extensions[$name]) && $this->hasAccess() && !$cache->useCache(array('age' => 3600 * 24))) { $this->loaded_extensions[$name] = true; $httpclient = new DokuHTTPClient(); - $data = $httpclient->get(EXTENSION_REPSITORY_API.'?fmt=php&ext[]='.urlencode($name)); + $data = $httpclient->get(EXTENSION_REPOSITORY_API.'?fmt=php&ext[]='.urlencode($name)); if ($data !== false) { $result = unserialize($data); $cache->storeCache(serialize($result[0])); -- cgit v1.2.3 From e45b5c14dbb09dd200d66ff21de1bba960113c68 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 18:24:20 +0200 Subject: added connectivity recheck --- lib/plugins/extension/admin.php | 7 +++++++ lib/plugins/extension/helper/repository.php | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 373f90183..6cad58595 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -39,6 +39,13 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { $repository = $this->loadHelper('extension_repository'); $repository->init(); + if(!$repository->hasAccess()){ + $url = helper_plugin_extension_list::tabURL('', array('purge'=>1)); + + msg('The DokuWiki extension repository can not be reached currently. + Online Features are not available. [retry]', -1); + } + /* @var helper_plugin_extension_extension $extension */ $extension = $this->loadHelper('extension_extension'); diff --git a/lib/plugins/extension/helper/repository.php b/lib/plugins/extension/helper/repository.php index 459d7cbec..a5012ccb5 100644 --- a/lib/plugins/extension/helper/repository.php +++ b/lib/plugins/extension/helper/repository.php @@ -65,7 +65,7 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { if ($this->has_access === null) { $cache = new cache('##extension_manager###hasAccess', 'repo'); $result = null; - if (!$cache->useCache(array('age' => 3600 * 24))) { + if (!$cache->useCache(array('age' => 3600 * 24, 'purge'=>1))) { $httpclient = new DokuHTTPClient(); $httpclient->timeout = 5; $data = $httpclient->get(EXTENSION_REPOSITORY_API.'?cmd=ping'); -- cgit v1.2.3 From a8332b68fa9dd8f70d2fc9d9e50c34957cf9e24d Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 18:24:53 +0200 Subject: various gui fixes --- lib/plugins/extension/helper/extension.php | 2 ++ lib/plugins/extension/helper/list.php | 34 +++++++++++++++++++----------- 2 files changed, 24 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 093ee7828..296b81ac5 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -53,6 +53,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } $this->remoteInfo = $this->repository->getData(($this->isTemplate() ? 'template:' : '').$this->getBase()); + + return ($this->localInfo || $this->remoteInfo); } /** diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index e8b4f472f..816d4a444 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -10,7 +10,7 @@ if(!defined('DOKU_INC')) die(); /** - * Class helper_plugin_extension_extension represents a single extension (plugin or template) + * Class helper_plugin_extension_list takes care of creating a HTML list of extensions */ class helper_plugin_extension_list extends DokuWiki_Plugin { protected $form = ''; @@ -150,16 +150,15 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { if($extension->getAuthor()) { - $params = array( - 'do'=>'admin', - 'page'=>'extension', - 'tab'=>'search', - 'q'=>'author:'.$extension->getAuthor() - ); - $url = wl($ID, $params); - return ''.hsc($extension->getAuthor()).''; + $mailid = $extension->getEmailID(); + if($mailid){ + $url = $this->tabURL('search', array('q' => 'mailid:'.$mailid)); + return ''.hsc($extension->getAuthor()).''; + }else{ + return ''.hsc($extension->getAuthor()).''; + } } - return "".$this->getLang('unknown_author').""; + return "".$this->getLang('unknown_author').""; } /** @@ -231,8 +230,19 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { if ($extension->getBugtrackerURL()) { $return .= ' '.$this->getLang('bugs_features').' '; } - foreach ($extension->getTags() as $tag) { - $return .= hsc($tag).' '; //$this->manager->handler->html_taglink($tag); + if($extension->getTags()){ + $first = true; + echo ''; + foreach ($extension->getTags() as $tag) { + if(!$first){ + $return .= ', '; + }else{ + $first = false; + } + $url = $this->tabURL('search', array('q' => 'tag:'.$tag)); + $return .= ''.hsc($tag).''; + } + echo ''; } $return .= ''; return $return; -- cgit v1.2.3 From d7410643d8e3db12a76845370d8eee2508fa6115 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 19:46:02 +0200 Subject: added tab navigation --- lib/plugins/extension/admin.php | 49 +++++++++++++++++------ lib/plugins/extension/helper/gui.php | 71 ++++++++++++++++++++++++++++++++++ lib/plugins/extension/helper/list.php | 35 +++++++---------- lib/plugins/extension/lang/en/lang.php | 6 ++- 4 files changed, 126 insertions(+), 35 deletions(-) create mode 100644 lib/plugins/extension/helper/gui.php (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 6cad58595..4faafedb2 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -14,6 +14,17 @@ if(!defined('DOKU_INC')) die(); */ class admin_plugin_extension extends DokuWiki_Admin_Plugin { protected $infoFor = null; + /** @var helper_plugin_extension_gui */ + protected $gui; + + /** + * Constructor + * + * loads additional helpers + */ + public function __construct(){ + $this->gui = plugin_load('helper', 'extension_gui'); + } /** * @return int sort number in admin menu @@ -40,7 +51,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { $repository->init(); if(!$repository->hasAccess()){ - $url = helper_plugin_extension_list::tabURL('', array('purge'=>1)); + $url = $this->gui->tabURL('', array('purge'=>1)); msg('The DokuWiki extension repository can not be reached currently. Online Features are not available. [retry]', -1); @@ -109,21 +120,35 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { public function html() { /* @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; + global $INPUT; ptln('

    '.$this->getLang('menu').'

    '); ptln('
    '); - $pluginlist = $plugin_controller->getList('', true); - /* @var helper_plugin_extension_extension $extension */ - $extension = $this->loadHelper('extension_extension'); - /* @var helper_plugin_extension_list $list */ - $list = $this->loadHelper('extension_list'); - $list->start_form(); - foreach ($pluginlist as $name) { - $extension->setExtension($name, false); - $list->add_row($extension, $name == $this->infoFor); + $this->gui->tabNavigation(); + + switch($INPUT->str('tab','plugins')){ + case 'search': + echo 'search interface'; + break; + case 'plugins': + default: + // FIXME move to function? + + $pluginlist = $plugin_controller->getList('', true); + /* @var helper_plugin_extension_extension $extension */ + $extension = $this->loadHelper('extension_extension'); + /* @var helper_plugin_extension_list $list */ + $list = $this->loadHelper('extension_list'); + $list->start_form(); + foreach ($pluginlist as $name) { + $extension->setExtension($name, false); + $list->add_row($extension, $name == $this->infoFor); + } + $list->end_form(); + $list->render(); } - $list->end_form(); - $list->render(); + + ptln('
    '); } } diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php new file mode 100644 index 000000000..eba5fbc7f --- /dev/null +++ b/lib/plugins/extension/helper/gui.php @@ -0,0 +1,71 @@ + + */ + +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +/** + * Class helper_plugin_extension_list takes care of the overall GUI + */ +class helper_plugin_extension_gui extends DokuWiki_Plugin { + + protected $tabs = array('plugins', 'templates', 'search'); + + /** + * Print the tab navigation + * + * @fixme style active one + */ + public function tabNavigation() { + echo '
      '; + foreach(array('plugins', 'templates', 'search') as $tab) { + $url = $this->tabURL($tab); + if($this->currentTab() == $tab) { + $class = 'class="active"'; + } else { + $class = ''; + } + echo '
    • '.$this->getLang('tab_'.$tab).'
    • '; + } + echo '
    '; + } + + /** + * Return the currently selected tab + * + * @return string + */ + public function currentTab() { + global $INPUT; + + $tab = $INPUT->str('tab', 'plugins', true); + if(!in_array($tab, $this->tabs)) $tab = 'plugins'; + return $tab; + } + + /** + * Create an URL inside the extension manager + * + * @param string $tab tab to load, empty for current tab + * @param array $params associative array of parameter to set + * + * @return string + */ + public function tabURL($tab = '', $params = array()) { + global $ID; + + if(!$tab) $tab = $this->currentTab(); + $defaults = array( + 'do' => 'admin', + 'page' => 'extension', + 'tab' => $tab, + ); + return wl($ID, array_merge($defaults, $params)); + } + +} diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 816d4a444..1c337176d 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -14,6 +14,17 @@ if(!defined('DOKU_INC')) die(); */ class helper_plugin_extension_list extends DokuWiki_Plugin { protected $form = ''; + /** @var helper_plugin_extension_gui */ + protected $gui; + + /** + * Constructor + * + * loads additional helpers + */ + public function __construct(){ + $this->gui = plugin_load('helper', 'extension_gui'); + } function start_form() { $this->form .= '
    '; @@ -152,7 +163,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $mailid = $extension->getEmailID(); if($mailid){ - $url = $this->tabURL('search', array('q' => 'mailid:'.$mailid)); + $url = $this->gui->tabURL('search', array('q' => 'mailid:'.$mailid)); return ''.hsc($extension->getAuthor()).''; }else{ return ''.hsc($extension->getAuthor()).''; @@ -239,7 +250,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { }else{ $first = false; } - $url = $this->tabURL('search', array('q' => 'tag:'.$tag)); + $url = $this->gui->tabURL('search', array('q' => 'tag:'.$tag)); $return .= ''.hsc($tag).''; } echo ''; @@ -484,24 +495,4 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { return ''; } - - /** - * Create an URL inside the extension manager - * - * @param string tab tb to load, empty for current tab - * @param array $params associative array of parameter to set - * @return string - */ - static public function tabURL($tab='', $params=array()){ - global $ID; - global $INPUT; - - if(!$tab) $tab = $INPUT->str('tab', 'installed', true); - $defaults = array( - 'do' => 'admin', - 'page' => 'extension', - 'tab' => $tab, - ); - return wl($ID, array_merge($defaults, $params)); - } } diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index b3a451ecc..4439db879 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -7,7 +7,11 @@ */ // menu entry for admin plugins -$lang['menu'] = 'Extension manager'; +$lang['menu'] = 'Extension Manager'; + +$lang['tab_plugins'] = 'Installed Plugins'; +$lang['tab_templates'] = 'Installed Templates'; +$lang['tab_search'] = 'Search and Install'; // custom language strings for the plugin $lang['notimplemented'] = 'This feature hasn\'t been implemented yet'; -- cgit v1.2.3 From 5d7f3164ea4199d7cf1215a1a8a5785218c9e149 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 20:08:30 +0200 Subject: moved display stuff to gui class, added template list --- lib/plugins/extension/admin.php | 23 +++++----------------- lib/plugins/extension/helper/gui.php | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 4faafedb2..39ce9e947 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -118,34 +118,21 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { * Render HTML output */ public function html() { - /* @var Doku_Plugin_Controller $plugin_controller */ - global $plugin_controller; - global $INPUT; ptln('

    '.$this->getLang('menu').'

    '); ptln('
    '); $this->gui->tabNavigation(); - switch($INPUT->str('tab','plugins')){ + switch($this->gui->currentTab()){ case 'search': echo 'search interface'; break; + case 'templates': + $this->gui->templateList(); + break; case 'plugins': default: - // FIXME move to function? - - $pluginlist = $plugin_controller->getList('', true); - /* @var helper_plugin_extension_extension $extension */ - $extension = $this->loadHelper('extension_extension'); - /* @var helper_plugin_extension_list $list */ - $list = $this->loadHelper('extension_list'); - $list->start_form(); - foreach ($pluginlist as $name) { - $extension->setExtension($name, false); - $list->add_row($extension, $name == $this->infoFor); - } - $list->end_form(); - $list->render(); + $this->gui->pluginList(); } diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index eba5fbc7f..41afc2069 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -16,6 +16,43 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { protected $tabs = array('plugins', 'templates', 'search'); + + public function pluginList(){ + /* @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; + + $pluginlist = $plugin_controller->getList('', true); + /* @var helper_plugin_extension_extension $extension */ + $extension = $this->loadHelper('extension_extension'); + /* @var helper_plugin_extension_list $list */ + $list = $this->loadHelper('extension_list'); + $list->start_form(); + foreach ($pluginlist as $name) { + $extension->setExtension($name, false); + $list->add_row($extension, $name == $this->infoFor); + } + $list->end_form(); + $list->render(); + } + + public function templateList(){ + // FIXME do we have a real way? + $tpllist = glob(DOKU_INC.'lib/tpl/*', GLOB_ONLYDIR); + $tpllist = array_map('basename', $tpllist); + + /* @var helper_plugin_extension_extension $extension */ + $extension = $this->loadHelper('extension_extension'); + /* @var helper_plugin_extension_list $list */ + $list = $this->loadHelper('extension_list'); + $list->start_form(); + foreach ($tpllist as $name) { + $extension->setExtension($name, true); + $list->add_row($extension, $name == $this->infoFor); + } + $list->end_form(); + $list->render(); + } + /** * Print the tab navigation * -- cgit v1.2.3 From 1dd40c86eb47f24a2e7c7022592fd9cd25ff07f2 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 20:24:19 +0200 Subject: added intros --- lib/plugins/extension/admin.php | 6 +++--- lib/plugins/extension/helper/gui.php | 22 +++++++++++++++++++--- lib/plugins/extension/lang/en/intro_plugins.txt | 1 + lib/plugins/extension/lang/en/intro_search.txt | 1 + lib/plugins/extension/lang/en/intro_templates.txt | 1 + 5 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 lib/plugins/extension/lang/en/intro_plugins.txt create mode 100644 lib/plugins/extension/lang/en/intro_search.txt create mode 100644 lib/plugins/extension/lang/en/intro_templates.txt (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 39ce9e947..ee180192d 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -125,14 +125,14 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { switch($this->gui->currentTab()){ case 'search': - echo 'search interface'; + $this->gui->tabSearch(); break; case 'templates': - $this->gui->templateList(); + $this->gui->tabTemplates(); break; case 'plugins': default: - $this->gui->pluginList(); + $this->gui->tabPlugins(); } diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 41afc2069..7c83a3854 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -16,11 +16,15 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { protected $tabs = array('plugins', 'templates', 'search'); - - public function pluginList(){ + /** + * display the plugin tab + */ + public function tabPlugins(){ /* @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; + echo $this->locale_xhtml('intro_plugins'); + $pluginlist = $plugin_controller->getList('', true); /* @var helper_plugin_extension_extension $extension */ $extension = $this->loadHelper('extension_extension'); @@ -35,7 +39,12 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $list->render(); } - public function templateList(){ + /** + * Display the template tab + */ + public function tabTemplates(){ + echo $this->locale_xhtml('intro_templates'); + // FIXME do we have a real way? $tpllist = glob(DOKU_INC.'lib/tpl/*', GLOB_ONLYDIR); $tpllist = array_map('basename', $tpllist); @@ -53,6 +62,13 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $list->render(); } + /** + * Display the search tab + */ + public function tabSearch(){ + echo $this->locale_xhtml('intro_search'); + } + /** * Print the tab navigation * diff --git a/lib/plugins/extension/lang/en/intro_plugins.txt b/lib/plugins/extension/lang/en/intro_plugins.txt new file mode 100644 index 000000000..ef180135e --- /dev/null +++ b/lib/plugins/extension/lang/en/intro_plugins.txt @@ -0,0 +1 @@ +Here you can view, enable and disable installed plugins. \ No newline at end of file diff --git a/lib/plugins/extension/lang/en/intro_search.txt b/lib/plugins/extension/lang/en/intro_search.txt new file mode 100644 index 000000000..003c99c61 --- /dev/null +++ b/lib/plugins/extension/lang/en/intro_search.txt @@ -0,0 +1 @@ +Here you can search for available plugins and templates for DokuWiki. Be sure to read more about Plugin Security before installing FIXME add link \ No newline at end of file diff --git a/lib/plugins/extension/lang/en/intro_templates.txt b/lib/plugins/extension/lang/en/intro_templates.txt new file mode 100644 index 000000000..2b3af727b --- /dev/null +++ b/lib/plugins/extension/lang/en/intro_templates.txt @@ -0,0 +1 @@ +Here you can view, enable and disable installed templates. Note that only one template can be activated at a time. \ No newline at end of file -- cgit v1.2.3 From a218edff81be5cec78bfcb0f65042315ae4e656b Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 20:24:28 +0200 Subject: removed test repository again --- lib/plugins/extension/helper/repository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/repository.php b/lib/plugins/extension/helper/repository.php index a5012ccb5..21082c0d8 100644 --- a/lib/plugins/extension/helper/repository.php +++ b/lib/plugins/extension/helper/repository.php @@ -6,7 +6,7 @@ * @author Michael Hamann */ -define('EXTENSION_REPOSITORY_API', 'http://localhost/dokuwiki/lib/plugins/pluginrepo/api.php'); +#define('EXTENSION_REPOSITORY_API', 'http://localhost/dokuwiki/lib/plugins/pluginrepo/api.php'); if (!defined('EXTENSION_REPOSITORY_API_ENDPOINT')) define('EXTENSION_REPOSITORY_API', 'http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php'); -- cgit v1.2.3 From 7944abddde7619d8d59740cde19743c090d4fd3d Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 4 Aug 2013 20:34:12 +0200 Subject: translated error message --- lib/plugins/extension/admin.php | 4 +--- lib/plugins/extension/lang/en/lang.php | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index ee180192d..c9f37affb 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -52,9 +52,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { if(!$repository->hasAccess()){ $url = $this->gui->tabURL('', array('purge'=>1)); - - msg('The DokuWiki extension repository can not be reached currently. - Online Features are not available. [retry]', -1); + msg($this->getLang('repo_error').' ['.$this->getLang('repo_retry').']', -1); } /* @var helper_plugin_extension_extension $extension */ diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 4439db879..10bf2087f 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -56,6 +56,9 @@ $lang['donate'] = 'Donate'; $lang['bundled'] = 'bundled'; $lang['manual_install'] = 'manual install'; +$lang['repo_error'] = 'The DokuWiki extension repository can not be reached currently. Online Features are not available.'; +$lang['repo_retry'] = 'Retry'; + $lang['msg_tpl_uninstalled'] = 'Template %s uninstalled'; $lang['msg_tpl_uninstalled'] = 'Template %s could not be uninstalled'; $lang['msg_uninstalled'] = 'Plugin %s uninstalled'; -- cgit v1.2.3 From e8dda2c3faf5eb61b68d5afcbea13c5802484b4a Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 13:08:06 +0200 Subject: added gravatar images --- lib/plugins/extension/helper/list.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 1c337176d..843697667 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -164,7 +164,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $mailid = $extension->getEmailID(); if($mailid){ $url = $this->gui->tabURL('search', array('q' => 'mailid:'.$mailid)); - return ''.hsc($extension->getAuthor()).''; + return ' '.hsc($extension->getAuthor()).''; + }else{ return ''.hsc($extension->getAuthor()).''; } -- cgit v1.2.3 From 55332151e03b99bbfd15e0fbaae391aae454d9eb Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 13:43:35 +0200 Subject: some initial go at the search tab --- lib/plugins/extension/admin.php | 2 +- lib/plugins/extension/helper/extension.php | 29 +++++++++--- lib/plugins/extension/helper/gui.php | 49 +++++++++++++++---- lib/plugins/extension/helper/repository.php | 73 +++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index c9f37affb..51d4a8d1d 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -48,7 +48,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { // initialize the remote repository /* @var helper_plugin_extension_repository $repository */ $repository = $this->loadHelper('extension_repository'); - $repository->init(); + if(!$repository->hasAccess()){ $url = $this->gui->tabURL('', array('purge'=>1)); diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 296b81ac5..53753fcc1 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -14,8 +14,9 @@ if(!defined('DOKU_TPLLIB')) define('DOKU_TPLLIB', DOKU_INC.'lib/tpl/'); * Class helper_plugin_extension_extension represents a single extension (plugin or template) */ class helper_plugin_extension_extension extends DokuWiki_Plugin { + private $id; private $name; - private $is_template; + private $is_template = false; private $localInfo; private $remoteInfo; private $managerData; @@ -32,13 +33,18 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * Set the name of the extension this instance shall represents, triggers loading the local and remote data * - * @param string $name The base name of the extension - * @param bool $is_template If the extension is a template + * @param string $id The id of the extension (prefixed with template: for templates) * @return bool If some (local or remote) data was found */ - public function setExtension($name, $is_template) { - $this->name = $name; - $this->is_template = $is_template; + public function setExtension($id) { + $this->id = $id; + $this->name = $id; + + if(substr($id, 0 , 9) == 'template'){ + $this->name = substr($id, 10); + $this->is_template = true; + } + $this->localInfo = array(); $this->managerData = array(); $this->remoteInfo = array(); @@ -128,6 +134,17 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { return $this->is_template; } + /** + * Get the ID of the extension + * + * This is the same as getName() for plugins, for templates it's getName() prefixed with 'template:' + * + * @return string + */ + public function getID() { + return $this->id; + } + /** * Get the name of the installation directory * diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 7c83a3854..cf5b8a347 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -16,10 +16,13 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { protected $tabs = array('plugins', 'templates', 'search'); + /** @var string the extension that should have an open info window FIXME currently broken*/ + protected $infofor = ''; + /** * display the plugin tab */ - public function tabPlugins(){ + public function tabPlugins() { /* @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; @@ -31,8 +34,8 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { /* @var helper_plugin_extension_list $list */ $list = $this->loadHelper('extension_list'); $list->start_form(); - foreach ($pluginlist as $name) { - $extension->setExtension($name, false); + foreach($pluginlist as $name) { + $extension->setExtension($name); $list->add_row($extension, $name == $this->infoFor); } $list->end_form(); @@ -42,7 +45,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { /** * Display the template tab */ - public function tabTemplates(){ + public function tabTemplates() { echo $this->locale_xhtml('intro_templates'); // FIXME do we have a real way? @@ -54,8 +57,8 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { /* @var helper_plugin_extension_list $list */ $list = $this->loadHelper('extension_list'); $list->start_form(); - foreach ($tpllist as $name) { - $extension->setExtension($name, true); + foreach($tpllist as $name) { + $extension->setExtension("template:$name"); $list->add_row($extension, $name == $this->infoFor); } $list->end_form(); @@ -65,8 +68,34 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { /** * Display the search tab */ - public function tabSearch(){ + public function tabSearch() { + global $INPUT; echo $this->locale_xhtml('intro_search'); + + $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'))); + $form->addElement(form_makeTextField('q', $INPUT->str('q'), 'Search')); + $form->addElement(form_makeButton('submit', '', 'Search')); + $form->printForm(); + + if(!$INPUT->bool('q')) return; + + + /* @var helper_plugin_extension_repository $repository FIXME should we use some gloabl instance? */ + $repository = $this->loadHelper('extension_repository'); + $result = $repository->search($INPUT->str('q')); + + /* @var helper_plugin_extension_extension $extension */ + $extension = $this->loadHelper('extension_extension'); + /* @var helper_plugin_extension_list $list */ + $list = $this->loadHelper('extension_list'); + $list->start_form(); + foreach($result as $name) { + $extension->setExtension($name); + $list->add_row($extension, $name == $this->infoFor); + } + $list->end_form(); + $list->render(); + } /** @@ -106,10 +135,10 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * * @param string $tab tab to load, empty for current tab * @param array $params associative array of parameter to set - * + * @param string $sep seperator to build the URL * @return string */ - public function tabURL($tab = '', $params = array()) { + public function tabURL($tab = '', $params = array(), $sep = '&') { global $ID; if(!$tab) $tab = $this->currentTab(); @@ -118,7 +147,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { 'page' => 'extension', 'tab' => $tab, ); - return wl($ID, array_merge($defaults, $params)); + return wl($ID, array_merge($defaults, $params), false, $sep); } } diff --git a/lib/plugins/extension/helper/repository.php b/lib/plugins/extension/helper/repository.php index 21082c0d8..98128a9a3 100644 --- a/lib/plugins/extension/helper/repository.php +++ b/lib/plugins/extension/helper/repository.php @@ -109,6 +109,79 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { } return array(); } + + protected function cacheData($name, $data){ + + } + + /** + * Search for plugins or templates using the given query string + * + * @param string $q the query string + * @return array a list of matching extensions + */ + public function search($q){ + $query = $this->parse_query($q); + $query['fmt'] = 'php'; + + $httpclient = new DokuHTTPClient(); + $data = $httpclient->post(EXTENSION_REPOSITORY_API, $query); + if ($data === false) return array(); + $result = unserialize($data); + + $ids = array(); + + // store cache info for each extension + foreach($result as $ext){ + $name = $ext['name']; + $cache = new cache('##extension_manager##'.$name, 'repo'); + $cache->storeCache(serialize($ext)); + $ids[] = $name; + } + + return $ids; + } + + /** + * Parses special queries from the query string + * + * @param string $q + * @return array + */ + protected function parse_query($q){ + $parameters = array( + 'tag' => array(), + 'mail' => array(), + 'type' => array() + ); + + // extract tags + if(preg_match_all('/(^|\s)(tag:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ + foreach($matches as $m){ + $q = str_replace($m[2], '', $q); + $parameters['tag'][] = $m[3]; + } + } + // extract author ids + if(preg_match_all('/(^|\s)(authorid:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ + foreach($matches as $m){ + $q = str_replace($m[2], '', $q); + $parameters['mail'][] = $m[3]; + } + } + // extract types + if(preg_match_all('/(^|\s)(type:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ + foreach($matches as $m){ + $q = str_replace($m[2], '', $q); + $parameters['type'][] = $m[3]; + } + } + + // FIXME make integer from type value + + $parameters['q'] = trim($q); + return $parameters; + } } // vim:ts=4:sw=4:et: -- cgit v1.2.3 From 813d7e0910cdbb80dceef4d952adc551987c84e7 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 14:06:34 +0200 Subject: fixed some confusion between base, id and name --- lib/plugins/extension/admin.php | 8 +++--- lib/plugins/extension/helper/extension.php | 40 ++++++++++++++--------------- lib/plugins/extension/helper/list.php | 8 +++--- lib/plugins/extension/helper/repository.php | 6 +---- 4 files changed, 29 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 51d4a8d1d..7faed142d 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -76,7 +76,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { if ($status !== true) { msg($status, -1); } else { - msg(sprintf($this->getLang('msg_update_success'), hsc($extension->getName())), 1); + msg(sprintf($this->getLang('msg_update_success'), hsc($extension->getDisplayName())), 1); } break; case 'uninstall': @@ -85,7 +85,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { if ($status !== true) { msg($status, -1); } else { - msg(sprintf($this->getLang('msg_delete_success'), hsc($extension->getName())), 1); + msg(sprintf($this->getLang('msg_delete_success'), hsc($extension->getDisplayName())), 1); } break; case 'enable'; @@ -94,7 +94,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { if ($status !== true) { msg($status, -1); } else { - msg(sprintf($this->getLang('msg_enabled'), hsc($extension->getName())), 1); + msg(sprintf($this->getLang('msg_enabled'), hsc($extension->getDisplayName())), 1); } break; case 'disable'; @@ -103,7 +103,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { if ($status !== true) { msg($status, -1); } else { - msg(sprintf($this->getLang('msg_disabled'), hsc($extension->getName())), 1); + msg(sprintf($this->getLang('msg_disabled'), hsc($extension->getDisplayName())), 1); } break; } diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 53753fcc1..6a152b169 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -15,7 +15,7 @@ if(!defined('DOKU_TPLLIB')) define('DOKU_TPLLIB', DOKU_INC.'lib/tpl/'); */ class helper_plugin_extension_extension extends DokuWiki_Plugin { private $id; - private $name; + private $base; private $is_template = false; private $localInfo; private $remoteInfo; @@ -38,10 +38,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function setExtension($id) { $this->id = $id; - $this->name = $id; + $this->base = $id; - if(substr($id, 0 , 9) == 'template'){ - $this->name = substr($id, 10); + if(substr($id, 0 , 9) == 'template:'){ + $this->base = substr($id, 9); $this->is_template = true; } @@ -58,7 +58,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $this->repository = $this->loadHelper('extension_repository'); } - $this->remoteInfo = $this->repository->getData(($this->isTemplate() ? 'template:' : '').$this->getBase()); + $this->remoteInfo = $this->repository->getData($this->getID()); return ($this->localInfo || $this->remoteInfo); } @@ -79,7 +79,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function isBundled() { if (!empty($this->remoteInfo['bundled'])) return $this->remoteInfo['bundled']; - return in_array($this->name, + return in_array($this->base, array('acl', 'info', 'extension', 'test', 'revert', 'popularity', 'config', 'plugin', 'safefnrecode', 'authplain')); } @@ -89,7 +89,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool if the extension is protected */ public function isProtected() { - return in_array($this->name, array('acl', 'config', 'info', 'plugin', 'revert', 'usermanager')); + return in_array($this->base, array('acl', 'config', 'info', 'plugin', 'revert', 'usermanager')); } /** @@ -98,7 +98,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool If the extension is installed in the correct directory */ public function isInWrongFolder() { - return $this->name != $this->getBase(); + return $this->base != $this->getBase(); } /** @@ -109,7 +109,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { public function isEnabled() { /* @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; - return !$plugin_controller->isdisabled($this->name); + return !$plugin_controller->isdisabled($this->base); } /** @@ -151,7 +151,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return string The name of the installation directory */ public function getInstallName() { - return $this->name; + return $this->base; } // Data from plugin.info.txt/template.info.txt or the repo when not available locally @@ -162,7 +162,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function getBase() { if (!empty($this->localInfo['base'])) return $this->localInfo['base']; - return $this->name; + return $this->base; } /** @@ -170,10 +170,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @return string The display name */ - public function getName() { + public function getDisplayName() { if (!empty($this->localInfo['name'])) return $this->localInfo['name']; if (!empty($this->remoteInfo['name'])) return $this->remoteInfo['name']; - return $this->name; + return $this->base; } /** @@ -468,9 +468,9 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function getInstallDir() { if ($this->isTemplate()) { - return DOKU_TPLLIB.$this->name; + return DOKU_TPLLIB.$this->base; } else { - return DOKU_PLUGIN.$this->name; + return DOKU_PLUGIN.$this->base; } } @@ -518,7 +518,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { if (!isset($installed_extensions[$this->getBase()])) { $status = 'Error, the requested extension hasn\'t been installed or updated'; } - $this->setExtension($this->name, $this->isTemplate()); + $this->setExtension($this->getID()); $this->purgeCache(); } $this->dir_delete(dirname($path)); @@ -547,7 +547,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { global $plugin_controller; if (!$this->isInstalled()) return $this->getLang('notinstalled'); if ($this->isEnabled()) return $this->getLang('alreadyenabled'); - if ($plugin_controller->enable($this->name)) { + if ($plugin_controller->enable($this->base)) { $this->purgeCache(); return true; } else { @@ -567,7 +567,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { global $plugin_controller; if (!$this->isInstalled()) return $this->getLang('notinstalled'); if (!$this->isEnabled()) return $this->getLang('alreadydisabled'); - if ($plugin_controller->disable($this->name)) { + if ($plugin_controller->disable($this->base)) { $this->purgeCache(); return true; } else { @@ -605,7 +605,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { foreach($plugin_types as $type) { if(@file_exists($path.$type.'.php')) { - $plugin = plugin_load($type, $this->name); + $plugin = plugin_load($type, $this->base); if ($plugin) break; } @@ -613,7 +613,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { while(false !== ($cp = readdir($dh))) { if($cp == '.' || $cp == '..' || strtolower(substr($cp, -4)) != '.php') continue; - $plugin = plugin_load($type, $this->name.'_'.substr($cp, 0, -4)); + $plugin = plugin_load($type, $this->base.'_'.substr($cp, 0, -4)); if ($plugin) break; } if ($plugin) break; diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 843697667..12db5ea3c 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -163,7 +163,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $mailid = $extension->getEmailID(); if($mailid){ - $url = $this->gui->tabURL('search', array('q' => 'mailid:'.$mailid)); + $url = $this->gui->tabURL('search', array('q' => 'authorid:'.$mailid)); return ' '.hsc($extension->getAuthor()).''; }else{ @@ -181,8 +181,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { */ function make_screenshot(helper_plugin_extension_extension $extension) { if($extension->getScreenshotURL()) { - $img = ''. - ''.hsc($extension->getName()).''. + $img = ''. + ''.hsc($extension->getDisplayName()).''. ''; } elseif($extension->isTemplate()) { $img = 'template'; @@ -203,7 +203,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { function make_legend(helper_plugin_extension_extension $extension, $showinfo = false) { $return = '
    '; $return .= '

    '; - $return .= sprintf($this->getLang('extensionby'), hsc($extension->getName()), $this->make_author($extension)); + $return .= sprintf($this->getLang('extensionby'), hsc($extension->getDisplayName()), $this->make_author($extension)); $return .= '

    '; $return .= $this->make_screenshot($extension); diff --git a/lib/plugins/extension/helper/repository.php b/lib/plugins/extension/helper/repository.php index 98128a9a3..38e07786e 100644 --- a/lib/plugins/extension/helper/repository.php +++ b/lib/plugins/extension/helper/repository.php @@ -110,10 +110,6 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { return array(); } - protected function cacheData($name, $data){ - - } - /** * Search for plugins or templates using the given query string * @@ -133,7 +129,7 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { // store cache info for each extension foreach($result as $ext){ - $name = $ext['name']; + $name = $ext['plugin']; $cache = new cache('##extension_manager##'.$name, 'repo'); $cache->storeCache(serialize($ext)); $ids[] = $name; -- cgit v1.2.3 From 89275cfd7e4e8b88724a36ccf7ae7bd29342d494 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 15:22:18 +0200 Subject: added a first unit test --- lib/plugins/extension/_test/extension.test.php | 62 ++++++++++++++++++++++++++ lib/plugins/extension/helper/extension.php | 11 ++++- lib/plugins/extension/plugin.info.txt | 4 +- 3 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 lib/plugins/extension/_test/extension.test.php (limited to 'lib') diff --git a/lib/plugins/extension/_test/extension.test.php b/lib/plugins/extension/_test/extension.test.php new file mode 100644 index 000000000..6dfa49a46 --- /dev/null +++ b/lib/plugins/extension/_test/extension.test.php @@ -0,0 +1,62 @@ +setExtension('extension'); + $this->assertEquals('extension', $extension->getID()); + $this->assertEquals('extension', $extension->getBase()); + $this->assertEquals('Extension Manager', $extension->getDisplayName()); + $this->assertEquals('Michael Hamann', $extension->getAuthor()); + $this->assertEquals('michael@content-space.de', $extension->getEmail()); + $this->assertEquals(md5('michael@content-space.de'), $extension->getEmailID()); + $this->assertEquals('https://www.dokuwiki.org/plugin:extension', $extension->getURL()); + $this->assertEquals('Allows managing and installing plugins and templates', $extension->getDescription()); + $this->assertFalse($extension->isTemplate()); + $this->assertTrue($extension->isEnabled()); + $this->assertTrue($extension->isInstalled()); + $this->assertTrue($extension->isBundled()); + + $extension->setExtension('testing'); + $this->assertEquals('testing', $extension->getID()); + $this->assertEquals('testing', $extension->getBase()); + $this->assertEquals('Testing Plugin', $extension->getDisplayName()); + $this->assertEquals('Tobias Sarnowski', $extension->getAuthor()); + $this->assertEquals('tobias@trustedco.de', $extension->getEmail()); + $this->assertEquals(md5('tobias@trustedco.de'), $extension->getEmailID()); + $this->assertEquals('http://www.dokuwiki.org/plugin:testing', $extension->getURL()); + $this->assertEquals('Used to test the test framework. Should always be disabled.', $extension->getDescription()); + $this->assertFalse($extension->isTemplate()); + $this->assertFalse($extension->isEnabled()); + $this->assertTrue($extension->isInstalled()); + $this->assertTrue($extension->isBundled()); + + $extension->setExtension('template:dokuwiki'); + $this->assertEquals('template:dokuwiki', $extension->getID()); + $this->assertEquals('dokuwiki', $extension->getBase()); + $this->assertEquals('DokuWiki Template', $extension->getDisplayName()); + $this->assertEquals('Anika Henke', $extension->getAuthor()); + $this->assertEquals('anika@selfthinker.org', $extension->getEmail()); + $this->assertEquals(md5('anika@selfthinker.org'), $extension->getEmailID()); + $this->assertEquals('http://www.dokuwiki.org/template:dokuwiki', $extension->getURL()); + $this->assertEquals('DokuWiki\'s default template since 2012', $extension->getDescription()); + $this->assertTrue($extension->isTemplate()); + $this->assertTrue($extension->isEnabled()); + $this->assertTrue($extension->isInstalled()); + $this->assertTrue($extension->isBundled()); + + } + +} \ No newline at end of file diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 6a152b169..88fb5e229 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -80,7 +80,11 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { public function isBundled() { if (!empty($this->remoteInfo['bundled'])) return $this->remoteInfo['bundled']; return in_array($this->base, - array('acl', 'info', 'extension', 'test', 'revert', 'popularity', 'config', 'plugin', 'safefnrecode', 'authplain')); + array('acl', 'info', 'extension', 'test', 'revert', 'popularity', + 'config', 'plugin', 'safefnrecode', 'authplain', 'testing', + 'template:dokuwiki', 'template:default' + ) + ); } /** @@ -107,6 +111,11 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool If the extension is enabled */ public function isEnabled() { + global $conf; + if($this->isTemplate()){ + return ($conf['template'] == $this->getBase()); + } + /* @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; return !$plugin_controller->isdisabled($this->base); diff --git a/lib/plugins/extension/plugin.info.txt b/lib/plugins/extension/plugin.info.txt index 3c4469ad7..ef16d78a1 100644 --- a/lib/plugins/extension/plugin.info.txt +++ b/lib/plugins/extension/plugin.info.txt @@ -2,6 +2,6 @@ base extension author Michael Hamann email michael@content-space.de date 2013-08-01 -name extension plugin -desc Extension manager +name Extension Manager +desc Allows managing and installing plugins and templates url https://www.dokuwiki.org/plugin:extension -- cgit v1.2.3 From ea9f3f904d439e9af84bdbed8e1a0bba3ed286b2 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 15:31:45 +0200 Subject: added 4th tab for manual install --- lib/plugins/extension/admin.php | 3 +++ lib/plugins/extension/helper/extension.php | 2 +- lib/plugins/extension/helper/gui.php | 11 +++++++++-- lib/plugins/extension/lang/en/intro_install.txt | 1 + lib/plugins/extension/lang/en/lang.php | 1 + 5 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 lib/plugins/extension/lang/en/intro_install.txt (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 7faed142d..cf4eb79d7 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -128,6 +128,9 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { case 'templates': $this->gui->tabTemplates(); break; + case 'install': + $this->gui->tabInstall(); + break; case 'plugins': default: $this->gui->tabPlugins(); diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 88fb5e229..244ec9b9a 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -702,7 +702,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { public function download($url, &$path) { // check the url $matches = array(); - if(!preg_match("/[^\/]*$/", $url, $matches) || !$matches[0]) { + if(!preg_match('/[^\/]*$/', $url, $matches) || !$matches[0]) { return $this->getLang('baddownloadurl'); } $file = $matches[0]; diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index cf5b8a347..09cea7fcb 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -14,7 +14,7 @@ if(!defined('DOKU_INC')) die(); */ class helper_plugin_extension_gui extends DokuWiki_Plugin { - protected $tabs = array('plugins', 'templates', 'search'); + protected $tabs = array('plugins', 'templates', 'search', 'install'); /** @var string the extension that should have an open info window FIXME currently broken*/ protected $infofor = ''; @@ -98,6 +98,13 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { } + /** + * Display the template tab + */ + public function tabInstall() { + echo $this->locale_xhtml('intro_install'); + } + /** * Print the tab navigation * @@ -105,7 +112,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { */ public function tabNavigation() { echo '
      '; - foreach(array('plugins', 'templates', 'search') as $tab) { + foreach($this->tabs as $tab) { $url = $this->tabURL($tab); if($this->currentTab() == $tab) { $class = 'class="active"'; diff --git a/lib/plugins/extension/lang/en/intro_install.txt b/lib/plugins/extension/lang/en/intro_install.txt new file mode 100644 index 000000000..f68d2d909 --- /dev/null +++ b/lib/plugins/extension/lang/en/intro_install.txt @@ -0,0 +1 @@ +Here you can manual install plugins and templates by either uploading them or providing a direct download URL. \ No newline at end of file diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 10bf2087f..24cabe1fa 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -12,6 +12,7 @@ $lang['menu'] = 'Extension Manager'; $lang['tab_plugins'] = 'Installed Plugins'; $lang['tab_templates'] = 'Installed Templates'; $lang['tab_search'] = 'Search and Install'; +$lang['tab_install'] = 'Manual Install'; // custom language strings for the plugin $lang['notimplemented'] = 'This feature hasn\'t been implemented yet'; -- cgit v1.2.3 From 2d87f05b99091011a83d131724e9714f9c07f976 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 15:40:05 +0200 Subject: moved CSS to LESS file, removed angua compatibility --- lib/plugins/extension/style.css | 373 --------------------------------------- lib/plugins/extension/style.less | 345 ++++++++++++++++++++++++++++++++++++ 2 files changed, 345 insertions(+), 373 deletions(-) delete mode 100644 lib/plugins/extension/style.css create mode 100644 lib/plugins/extension/style.less (limited to 'lib') diff --git a/lib/plugins/extension/style.css b/lib/plugins/extension/style.css deleted file mode 100644 index 0a3a0cc0e..000000000 --- a/lib/plugins/extension/style.css +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Extension plugin styles - * - * @author Christopher Smith - * @author Piyush Mishra - * @author Håkan Sandell - * @author Anika Henke - */ - -/* - * tab support not included in "Angua", copied from _mediamanager.css - */ -#extension__manager .panelHeader { - background-color: __background_alt__; - margin-bottom: 10px; - padding: 10px; - text-align: left; - /* to counter partly missing border of ul.tabs: */ - border-top: 1px solid __border__; - margin-top: -1px; -} - -#extension__manager .panelHeader p { - float: left; - font-weight: normal; - font-size: 1em; - padding: 0; - margin: 0 0 3px; -} -[dir=rtl] #extension__manager .panelHeader p { - float: right; -} - -#extension__manager ul.tabs div.message { - display: inline; - margin: 0 .5em; -} - -/* - * general layout - */ -#extension__manager h2 { - margin-left: 0; -} - -#extension__manager a.taglink { - padding: 1px 4px; - background-color: __background_neu__; - border-radius: 3px; -} -[dir=rtl] #extension__manager a.taglink { - display: inline-block; - line-height: 1.2; -} - -#extension__manager .panelHeader div.error { - margin-top: 0; - float: left; -} -[dir=rtl] #extension__manager .panelHeader div.error { - float: right; -} - -/* - * search & url download forms - */ -#extension__manager form.search, -#extension__manager form.btn_reload { - float: right; -} -[dir=rtl] #extension__manager form.search, -[dir=rtl] #extension__manager form.btn_reload { - float: left; -} - -#extension__manager div.search form.search { - float: none; -} - -#extension__manager .tagcloud { - width: 55%; - float: left; - margin: 0 0.5em 1em 0; -} -[dir=rtl] #extension__manager .tagcloud { - float: right; - margin: 0 0 1em .5em; -} - -#extension__manager .tagcloud a.taglink { - background-color: inherit; -} - -#extension__manager div.search { - width: 44%; - float: left; -} -[dir=rtl] #extension__manager div.search { - float: right; -} - -#extension__manager fieldset { - margin-top: 0.5em; - width: auto; -} - -#extension__manager fieldset p { - margin: 0.5em; - text-align: justify; - font-size: 85%; -} - -/* tag cloud */ -#extension__manager a.cl0 { font-size: 0.7em; } -#extension__manager a.cl1 { font-size: 0.9em; } -#extension__manager a.cl2 { font-size: 1em; } -#extension__manager a.cl3 { font-size: 1.3em; } -#extension__manager a.cl4 { font-size: 1.6em; } -#extension__manager a.cl5 { font-size: 1.9em; } - - -#extension__manager .extensionList input.button { - margin: 0 .3em .3em 0; -} -[dir=rtl] #extension__manager .extensionList input.button { - margin: 0 0 .3em .3em; -} - -/* - * extensions table - */ -#extension__manager .extensionList { - margin-left: 0; - margin-right: 0; - padding: 0; - list-style: none; -} - -#extension__manager .extensionList li { - margin: 0 0 .5em; - padding: 0 0 .5em; - color: __text__; - border-bottom: 1px solid __border__; - overflow: hidden; -} - -#extension__manager .legend { - position: relative; - width: 75%; - float: left; -} -[dir=rtl] #extension__manager .legend { - float: right; -} - -#extension__manager .legend > div { - padding: 0 .5em 0 132px; - border-right: 1px solid __background_alt__; - overflow: hidden; -} -[dir=rtl] #extension__manager .legend > div { - padding: 0 132px 0 .5em; - border-left: 1px solid __background_alt__; - border-right-width: 0; -} - -#extension__manager .enabled div.screenshot span { - background: transparent url(images/enabled.png) no-repeat 2px 2px; -} - -#extension__manager .disabled div.screenshot span { - background: transparent url(images/disabled.png) no-repeat 2px 2px; -} - -#extension__manager div.screenshot img { - width: 120px; - height: 70px; -} - -#extension__manager .legend div.screenshot { - margin-top: 4px; - margin-left: -132px; - max-width: 120px; - float: left; -} -[dir=rtl] #extension__manager .legend div.screenshot { - margin-left: 0; - margin-right: -132px; - float: right; -} - -#extension__manager .legend div.screenshot span { - min-height: 24px; - min-width: 24px; - position: absolute; - left: 0; -} -[dir=rtl] #extension__manager .legend div.screenshot span { - left: auto; - right: 0; -} - -#extension__manager .legend h2 { - width: 100%; - float: right; - margin: 0.2em 0 0.5em; - font-size: 100%; - font-weight: normal; - border: none; -} -[dir=rtl] #extension__manager .legend h2 { - float: left; -} - -#extension__manager .legend h2 strong { - font-size: 120%; - font-weight: bold; - vertical-align: baseline; -} - -#extension__manager .legend p { - margin: 0 0 0.6em 0; -} - -#extension__manager .legend span.linkbar { - font-size: 85%; -} - -#extension__manager .legend span.linkbar a.urlextern + a.taglink, -#extension__manager .legend span.linkbar a.interwiki + a.taglink { - margin-left: 0.4em; -} -[dir=rtl] #extension__manager .legend span.linkbar a.urlextern + a.taglink, -[dir=rtl] #extension__manager .legend span.linkbar a.interwiki + a.taglink { - margin-left: 0; -} -[dir=rtl] #extension__manager .legend span.linkbar a.urlextern, -[dir=rtl] #extension__manager .legend span.linkbar a.interwiki { - margin-left: .4em; -} - -#extension__manager .legend input.button { - background: transparent url(images/up.png) no-repeat 0 0; - box-shadow: none; - border-width: 0; - height: 14px; - text-indent: -99999px; - float: right; - margin: .5em 0 0; -} -[dir=rtl] #extension__manager .legend input.button { - float: left; - margin: .5em 0 0; -} - -#extension__manager .legend input.button.close { - background: transparent url(images/down.png) no-repeat 0 0; -} - -#extension__manager .legend div.popularity { - background-color: __background__; - border: 1px solid silver; - height: .4em; - margin: 0 auto; - padding: 1px; - width: 5.5em; - position: absolute; - right: .5em; - top: 0.2em; -} -[dir=rtl] #extension__manager .legend div.popularity { - right: auto; - left: .5em; -} - -#extension__manager .legend div.popularity div { - background-color: __border__; - height: 100%; -} - -#extension__manager .legend div.popularity div span { - display: none;/* @todo: hide accessibly */ -} - -#extension__manager .actions { - padding: 0; - font-size: 95%; - width: 25%; - float: right; - text-align: right; -} -[dir=rtl] #extension__manager .actions { - float: left; - text-align: left; -} - -#extension__manager .actions .version { - display: block; -} - -#extension__manager .actions p { - margin: 0.2em 0; - text-align: center; -} - -/* - * extensions table, detailed info box - */ -#extension__manager dl.details { - margin: 0.4em 0 0 0; - font-size: 85%; - border-top: 1px solid __background_alt__; - clear: both; -} - -#extension__manager dl.details dt { - clear: left; - float: left; - width: 25%; - margin: 0; - text-align: right; - font-weight: normal; - padding: 0.2em 5px 0 0; -} -[dir=rtl] #extension__manager dl.details dt { - clear: right; - float: right; - text-align: left; - padding: 0.2em 0 0 5px; -} - -#extension__manager dl.details dd { - margin-left: 25%; - font-weight: bold; - padding: 0.2em 0 0 5px; -} -[dir=rtl] #extension__manager dl.details dd { - margin-left: 0; - margin-right: 25%; - padding: 0.2em 5px 0 0 ; -} - -#extension__manager dl.details dd a { - font-weight: normal; -} - -#extension__manager #info__popup { - z-index: 20; - overflow: hidden; - opacity: 0.9; - border: 1px solid __border__; - background-color: __border__; /*background_other__;*/ - text-align: left; - padding: 0.2em; -} -[dir=rtl] #extension__manager #info__popup { - text-align: right; -} - -#extension__manager div.msg { - margin: 0.4em 0 0 0; -} - -#extension__manager ul.tabs div.msg { - display: inline; - margin-left: 0.4em; -} -[dir=rtl] #extension__manager ul.tabs div.msg { - margin-left: 0; - margin-right: 0.4em; -} - -/* end admin plugin styles */ diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less new file mode 100644 index 000000000..40fdb6075 --- /dev/null +++ b/lib/plugins/extension/style.less @@ -0,0 +1,345 @@ +/* + * Extension plugin styles + * + * @author Christopher Smith + * @author Piyush Mishra + * @author Håkan Sandell + * @author Anika Henke + */ + + +/* + * general layout + */ +#extension__manager h2 { + margin-left: 0; +} + +#extension__manager a.taglink { + padding: 1px 4px; + background-color: @ini_background_neu; + border-radius: 3px; +} +[dir=rtl] #extension__manager a.taglink { + display: inline-block; + line-height: 1.2; +} + +#extension__manager .panelHeader div.error { + margin-top: 0; + float: left; +} +[dir=rtl] #extension__manager .panelHeader div.error { + float: right; +} + +/* + * search & url download forms + */ +#extension__manager form.search, +#extension__manager form.btn_reload { + float: right; +} +[dir=rtl] #extension__manager form.search, +[dir=rtl] #extension__manager form.btn_reload { + float: left; +} + +#extension__manager div.search form.search { + float: none; +} + +#extension__manager .tagcloud { + width: 55%; + float: left; + margin: 0 0.5em 1em 0; +} +[dir=rtl] #extension__manager .tagcloud { + float: right; + margin: 0 0 1em .5em; +} + +#extension__manager .tagcloud a.taglink { + background-color: inherit; +} + +#extension__manager div.search { + width: 44%; + float: left; +} +[dir=rtl] #extension__manager div.search { + float: right; +} + +#extension__manager fieldset { + margin-top: 0.5em; + width: auto; +} + +#extension__manager fieldset p { + margin: 0.5em; + text-align: justify; + font-size: 85%; +} + +/* tag cloud */ +#extension__manager a.cl0 { font-size: 0.7em; } +#extension__manager a.cl1 { font-size: 0.9em; } +#extension__manager a.cl2 { font-size: 1em; } +#extension__manager a.cl3 { font-size: 1.3em; } +#extension__manager a.cl4 { font-size: 1.6em; } +#extension__manager a.cl5 { font-size: 1.9em; } + + +#extension__manager .extensionList input.button { + margin: 0 .3em .3em 0; +} +[dir=rtl] #extension__manager .extensionList input.button { + margin: 0 0 .3em .3em; +} + +/* + * extensions table + */ +#extension__manager .extensionList { + margin-left: 0; + margin-right: 0; + padding: 0; + list-style: none; +} + +#extension__manager .extensionList li { + margin: 0 0 .5em; + padding: 0 0 .5em; + color: @ini_text; + border-bottom: 1px solid @ini_border; + overflow: hidden; +} + +#extension__manager .legend { + position: relative; + width: 75%; + float: left; +} +[dir=rtl] #extension__manager .legend { + float: right; +} + +#extension__manager .legend > div { + padding: 0 .5em 0 132px; + border-right: 1px solid @ini_background_alt; + overflow: hidden; +} +[dir=rtl] #extension__manager .legend > div { + padding: 0 132px 0 .5em; + border-left: 1px solid @ini_background_alt; + border-right-width: 0; +} + +#extension__manager .enabled div.screenshot span { + background: transparent url(images/enabled.png) no-repeat 2px 2px; +} + +#extension__manager .disabled div.screenshot span { + background: transparent url(images/disabled.png) no-repeat 2px 2px; +} + +#extension__manager div.screenshot img { + width: 120px; + height: 70px; +} + +#extension__manager .legend div.screenshot { + margin-top: 4px; + margin-left: -132px; + max-width: 120px; + float: left; +} +[dir=rtl] #extension__manager .legend div.screenshot { + margin-left: 0; + margin-right: -132px; + float: right; +} + +#extension__manager .legend div.screenshot span { + min-height: 24px; + min-width: 24px; + position: absolute; + left: 0; +} +[dir=rtl] #extension__manager .legend div.screenshot span { + left: auto; + right: 0; +} + +#extension__manager .legend h2 { + width: 100%; + float: right; + margin: 0.2em 0 0.5em; + font-size: 100%; + font-weight: normal; + border: none; +} +[dir=rtl] #extension__manager .legend h2 { + float: left; +} + +#extension__manager .legend h2 strong { + font-size: 120%; + font-weight: bold; + vertical-align: baseline; +} + +#extension__manager .legend p { + margin: 0 0 0.6em 0; +} + +#extension__manager .legend span.linkbar { + font-size: 85%; +} + +#extension__manager .legend span.linkbar a.urlextern + a.taglink, +#extension__manager .legend span.linkbar a.interwiki + a.taglink { + margin-left: 0.4em; +} +[dir=rtl] #extension__manager .legend span.linkbar a.urlextern + a.taglink, +[dir=rtl] #extension__manager .legend span.linkbar a.interwiki + a.taglink { + margin-left: 0; +} +[dir=rtl] #extension__manager .legend span.linkbar a.urlextern, +[dir=rtl] #extension__manager .legend span.linkbar a.interwiki { + margin-left: .4em; +} + +#extension__manager .legend input.button { + background: transparent url(images/up.png) no-repeat 0 0; + box-shadow: none; + border-width: 0; + height: 14px; + text-indent: -99999px; + float: right; + margin: .5em 0 0; +} +[dir=rtl] #extension__manager .legend input.button { + float: left; + margin: .5em 0 0; +} + +#extension__manager .legend input.button.close { + background: transparent url(images/down.png) no-repeat 0 0; +} + +#extension__manager .legend div.popularity { + background-color: @ini_background; + border: 1px solid silver; + height: .4em; + margin: 0 auto; + padding: 1px; + width: 5.5em; + position: absolute; + right: .5em; + top: 0.2em; +} +[dir=rtl] #extension__manager .legend div.popularity { + right: auto; + left: .5em; +} + +#extension__manager .legend div.popularity div { + background-color: @ini_border; + height: 100%; +} + +#extension__manager .legend div.popularity div span { + display: none;/* @todo: hide accessibly */ +} + +#extension__manager .actions { + padding: 0; + font-size: 95%; + width: 25%; + float: right; + text-align: right; +} +[dir=rtl] #extension__manager .actions { + float: left; + text-align: left; +} + +#extension__manager .actions .version { + display: block; +} + +#extension__manager .actions p { + margin: 0.2em 0; + text-align: center; +} + +/* + * extensions table, detailed info box + */ +#extension__manager dl.details { + margin: 0.4em 0 0 0; + font-size: 85%; + border-top: 1px solid @ini_background_alt; + clear: both; +} + +#extension__manager dl.details dt { + clear: left; + float: left; + width: 25%; + margin: 0; + text-align: right; + font-weight: normal; + padding: 0.2em 5px 0 0; +} +[dir=rtl] #extension__manager dl.details dt { + clear: right; + float: right; + text-align: left; + padding: 0.2em 0 0 5px; +} + +#extension__manager dl.details dd { + margin-left: 25%; + font-weight: bold; + padding: 0.2em 0 0 5px; +} +[dir=rtl] #extension__manager dl.details dd { + margin-left: 0; + margin-right: 25%; + padding: 0.2em 5px 0 0 ; +} + +#extension__manager dl.details dd a { + font-weight: normal; +} + +#extension__manager #info__popup { + z-index: 20; + overflow: hidden; + opacity: 0.9; + border: 1px solid @ini_border; + background-color: @ini_border; /*background_other__;*/ + text-align: left; + padding: 0.2em; +} +[dir=rtl] #extension__manager #info__popup { + text-align: right; +} + +#extension__manager div.msg { + margin: 0.4em 0 0 0; +} + +#extension__manager ul.tabs div.msg { + display: inline; + margin-left: 0.4em; +} +[dir=rtl] #extension__manager ul.tabs div.msg { + margin-left: 0; + margin-right: 0.4em; +} + +/* end admin plugin styles */ -- cgit v1.2.3 From 61746d5540723d7463a0c1d666decb9c164c6678 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 16:07:21 +0200 Subject: added a very simplistic lightbox --- lib/plugins/extension/helper/list.php | 2 +- lib/plugins/extension/images/overlay.png | Bin 0 -> 109 bytes lib/plugins/extension/script.js | 34 +++++++++++++++++++++++++++++++ lib/plugins/extension/style.less | 29 ++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 lib/plugins/extension/images/overlay.png create mode 100644 lib/plugins/extension/script.js (limited to 'lib') diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 12db5ea3c..62031a69b 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -181,7 +181,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { */ function make_screenshot(helper_plugin_extension_extension $extension) { if($extension->getScreenshotURL()) { - $img = ''. + $img = ''. ''.hsc($extension->getDisplayName()).''. ''; } elseif($extension->isTemplate()) { diff --git a/lib/plugins/extension/images/overlay.png b/lib/plugins/extension/images/overlay.png new file mode 100644 index 000000000..8f92c2fe7 Binary files /dev/null and b/lib/plugins/extension/images/overlay.png differ diff --git a/lib/plugins/extension/script.js b/lib/plugins/extension/script.js new file mode 100644 index 000000000..f2a6aae50 --- /dev/null +++ b/lib/plugins/extension/script.js @@ -0,0 +1,34 @@ +jQuery(function(){ + + + /** + * very simple lightbox + * @link http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/super-simple-lightbox-with-css-and-jquery/ + */ + jQuery('a.extension_screenshot').click(function(e) { + e.preventDefault(); + + //Get clicked link href + var image_href = jQuery(this).attr("href"); + + // create lightbox if needed + var $lightbox = jQuery('#plugin__extensionlightbox'); + if(!$lightbox.length){ + $lightbox = jQuery('

      Click to close

      ') + .appendTo(jQuery('body')) + .hide() + .click(function(){ + $lightbox.hide(); + }); + } + + // fill and show it + $lightbox + .show() + .find('div').html(''); + + + return false; + }); + +}); \ No newline at end of file diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index 40fdb6075..cd9eeaa74 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -7,6 +7,35 @@ * @author Anika Henke */ +/** + * very simple lightbox + * @link http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/super-simple-lightbox-with-css-and-jquery/ + */ +#plugin__extensionlightbox { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: url(images/overlay.png) repeat; + text-align: center; + cursor: pointer; + + p { + text-align: right; + color: #fff; + margin-right: 20px; + font-size: 12px; + } + + img { + box-shadow: 0 0 25px #111; + -webkit-box-shadow: 0 0 25px #111; + -moz-box-shadow: 0 0 25px #111; + max-width: 90%; + max-height: 90%; + } +} /* * general layout -- cgit v1.2.3 From 519895b5625277197a88748c515919515f1113b8 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 20:04:17 +0200 Subject: added tests for the find_folders method --- lib/plugins/extension/_test/extension.test.php | 234 ++++++++++++++++++++- .../extension/_test/testdata/either1/script.js | 0 .../_test/testdata/eithersub2/either2/script.js | 0 .../_test/testdata/plgfoo5/plugin.info.txt | 7 + .../_test/testdata/plgsub3/plugin3/syntax.php | 0 .../_test/testdata/plgsub4/plugin4/plugin.info.txt | 7 + .../_test/testdata/plgsub6/plgfoo6/plugin.info.txt | 7 + .../extension/_test/testdata/plugin1/syntax.php | 0 .../_test/testdata/plugin2/plugin.info.txt | 7 + .../extension/_test/testdata/template1/main.php | 0 .../extension/_test/testdata/template1/style.ini | 0 .../_test/testdata/template2/template.info.txt | 7 + .../_test/testdata/tplfoo5/template.info.txt | 7 + .../_test/testdata/tplsub3/template3/main.php | 0 .../_test/testdata/tplsub3/template3/style.ini | 0 .../testdata/tplsub4/template4/template.info.txt | 7 + .../testdata/tplsub6/tplfoo6/template.info.txt | 7 + lib/plugins/extension/admin.php | 10 +- lib/plugins/extension/helper/extension.php | 190 ++++++++--------- 19 files changed, 382 insertions(+), 108 deletions(-) create mode 100644 lib/plugins/extension/_test/testdata/either1/script.js create mode 100644 lib/plugins/extension/_test/testdata/eithersub2/either2/script.js create mode 100644 lib/plugins/extension/_test/testdata/plgfoo5/plugin.info.txt create mode 100644 lib/plugins/extension/_test/testdata/plgsub3/plugin3/syntax.php create mode 100644 lib/plugins/extension/_test/testdata/plgsub4/plugin4/plugin.info.txt create mode 100644 lib/plugins/extension/_test/testdata/plgsub6/plgfoo6/plugin.info.txt create mode 100644 lib/plugins/extension/_test/testdata/plugin1/syntax.php create mode 100644 lib/plugins/extension/_test/testdata/plugin2/plugin.info.txt create mode 100644 lib/plugins/extension/_test/testdata/template1/main.php create mode 100644 lib/plugins/extension/_test/testdata/template1/style.ini create mode 100644 lib/plugins/extension/_test/testdata/template2/template.info.txt create mode 100644 lib/plugins/extension/_test/testdata/tplfoo5/template.info.txt create mode 100644 lib/plugins/extension/_test/testdata/tplsub3/template3/main.php create mode 100644 lib/plugins/extension/_test/testdata/tplsub3/template3/style.ini create mode 100644 lib/plugins/extension/_test/testdata/tplsub4/template4/template.info.txt create mode 100644 lib/plugins/extension/_test/testdata/tplsub6/tplfoo6/template.info.txt (limited to 'lib') diff --git a/lib/plugins/extension/_test/extension.test.php b/lib/plugins/extension/_test/extension.test.php index 6dfa49a46..97726d212 100644 --- a/lib/plugins/extension/_test/extension.test.php +++ b/lib/plugins/extension/_test/extension.test.php @@ -1,10 +1,23 @@ setExtension('extension'); @@ -56,7 +68,225 @@ class helper_plugin_extension_extension_test extends DokuWikiTest { $this->assertTrue($extension->isEnabled()); $this->assertTrue($extension->isInstalled()); $this->assertTrue($extension->isBundled()); + } + + public function testFindFoldersPlugins() { + $extension = new mock_helper_plugin_extension_extension(); + $tdir = dirname(__FILE__).'/testdata'; + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/plugin1", 'plugin'); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('plugin', $result['old'][0]['type']); + $this->assertEquals('plugin1', $this->extdir($result['old'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/plugin2", 'plugin'); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('plugin', $result['new'][0]['type']); + $this->assertEquals('plugin2', $result['new'][0]['base']); + $this->assertEquals('plugin2', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/plgsub3", 'plugin'); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('plugin', $result['old'][0]['type']); + $this->assertEquals('plgsub3/plugin3', $this->extdir($result['old'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/plgsub4", 'plugin'); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('plugin', $result['new'][0]['type']); + $this->assertEquals('plugin4', $result['new'][0]['base']); + $this->assertEquals('plgsub4/plugin4', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/plgfoo5", 'plugin'); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('plugin', $result['new'][0]['type']); + $this->assertEquals('plugin5', $result['new'][0]['base']); + $this->assertEquals('plgfoo5', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/plgsub6/plgfoo6", 'plugin'); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('plugin', $result['new'][0]['type']); + $this->assertEquals('plugin6', $result['new'][0]['base']); + $this->assertEquals('plgsub6/plgfoo6', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/either1", 'plugin'); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('plugin', $result['old'][0]['type']); + $this->assertEquals('either1', $this->extdir($result['old'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/eithersub2/either2", 'plugin'); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('plugin', $result['old'][0]['type']); + $this->assertEquals('eithersub2/either2', $this->extdir($result['old'][0]['tmp'])); + } + + public function testFindFoldersTemplates() { + $extension = new mock_helper_plugin_extension_extension(); + $tdir = dirname(__FILE__).'/testdata'; + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/template1", 'template'); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('template', $result['old'][0]['type']); + $this->assertEquals('template1', $this->extdir($result['old'][0]['tmp'])); + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/template2", 'template'); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('template', $result['new'][0]['type']); + $this->assertEquals('template2', $result['new'][0]['base']); + $this->assertEquals('template2', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/tplsub3", 'template'); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('template', $result['old'][0]['type']); + $this->assertEquals('tplsub3/template3', $this->extdir($result['old'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/tplsub4", 'template'); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('template', $result['new'][0]['type']); + $this->assertEquals('template4', $result['new'][0]['base']); + $this->assertEquals('tplsub4/template4', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/tplfoo5", 'template'); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('template', $result['new'][0]['type']); + $this->assertEquals('template5', $result['new'][0]['base']); + $this->assertEquals('tplfoo5', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/tplsub6/tplfoo6", 'template'); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('template', $result['new'][0]['type']); + $this->assertEquals('template6', $result['new'][0]['base']); + $this->assertEquals('tplsub6/tplfoo6', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/either1", 'template'); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('template', $result['old'][0]['type']); + $this->assertEquals('either1', $this->extdir($result['old'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/eithersub2/either2", 'template'); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('template', $result['old'][0]['type']); + $this->assertEquals('eithersub2/either2', $this->extdir($result['old'][0]['tmp'])); + } + + public function testFindFoldersTemplatesAutodetect() { + $extension = new mock_helper_plugin_extension_extension(); + $tdir = dirname(__FILE__).'/testdata'; + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/template1"); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('template', $result['old'][0]['type']); + $this->assertEquals('template1', $this->extdir($result['old'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/template2"); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('template', $result['new'][0]['type']); + $this->assertEquals('template2', $result['new'][0]['base']); + $this->assertEquals('template2', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/tplsub3"); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('template', $result['old'][0]['type']); + $this->assertEquals('tplsub3/template3', $this->extdir($result['old'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/tplsub4"); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('template', $result['new'][0]['type']); + $this->assertEquals('template4', $result['new'][0]['base']); + $this->assertEquals('tplsub4/template4', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/tplfoo5"); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('template', $result['new'][0]['type']); + $this->assertEquals('template5', $result['new'][0]['base']); + $this->assertEquals('tplfoo5', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/tplsub6/tplfoo6"); + $this->assertTrue($ok); + $this->assertEquals(1, count($result['new'])); + $this->assertEquals('template', $result['new'][0]['type']); + $this->assertEquals('template6', $result['new'][0]['base']); + $this->assertEquals('tplsub6/tplfoo6', $this->extdir($result['new'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/either1"); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('plugin', $result['old'][0]['type']); + $this->assertEquals('either1', $this->extdir($result['old'][0]['tmp'])); + + $result = array('old' => array(), 'new' => array()); + $ok = $extension->find_folders($result, "$tdir/eithersub2/either2"); + $this->assertTrue($ok); + $this->assertEquals(0, count($result['new'])); + $this->assertEquals(1, count($result['old'])); + $this->assertEquals('plugin', $result['old'][0]['type']); + $this->assertEquals('eithersub2/either2', $this->extdir($result['old'][0]['tmp'])); } + /** + * remove the test data directory from a dir name for cross install comparison + * + * @param string $dir + * @return string + */ + protected function extdir($dir) { + $tdir = dirname(__FILE__).'/testdata'; + $len = strlen($tdir); + $dir = trim(substr($dir, $len), '/'); + return $dir; + } } \ No newline at end of file diff --git a/lib/plugins/extension/_test/testdata/either1/script.js b/lib/plugins/extension/_test/testdata/either1/script.js new file mode 100644 index 000000000..e69de29bb diff --git a/lib/plugins/extension/_test/testdata/eithersub2/either2/script.js b/lib/plugins/extension/_test/testdata/eithersub2/either2/script.js new file mode 100644 index 000000000..e69de29bb diff --git a/lib/plugins/extension/_test/testdata/plgfoo5/plugin.info.txt b/lib/plugins/extension/_test/testdata/plgfoo5/plugin.info.txt new file mode 100644 index 000000000..cc4532d29 --- /dev/null +++ b/lib/plugins/extension/_test/testdata/plgfoo5/plugin.info.txt @@ -0,0 +1,7 @@ +base plugin5 +author Andreas Gohr +email andi@splitbrain.org +date 2013-05-02 +name Dummy Plugin +desc Dummy plugin data +url http://example.com/plugin:plugin5 diff --git a/lib/plugins/extension/_test/testdata/plgsub3/plugin3/syntax.php b/lib/plugins/extension/_test/testdata/plgsub3/plugin3/syntax.php new file mode 100644 index 000000000..e69de29bb diff --git a/lib/plugins/extension/_test/testdata/plgsub4/plugin4/plugin.info.txt b/lib/plugins/extension/_test/testdata/plgsub4/plugin4/plugin.info.txt new file mode 100644 index 000000000..374b6bf24 --- /dev/null +++ b/lib/plugins/extension/_test/testdata/plgsub4/plugin4/plugin.info.txt @@ -0,0 +1,7 @@ +base plugin4 +author Andreas Gohr +email andi@splitbrain.org +date 2013-05-02 +name Dummy Plugin +desc Dummy plugin data +url http://example.com/plugin:plugin4 diff --git a/lib/plugins/extension/_test/testdata/plgsub6/plgfoo6/plugin.info.txt b/lib/plugins/extension/_test/testdata/plgsub6/plgfoo6/plugin.info.txt new file mode 100644 index 000000000..461ff8735 --- /dev/null +++ b/lib/plugins/extension/_test/testdata/plgsub6/plgfoo6/plugin.info.txt @@ -0,0 +1,7 @@ +base plugin6 +author Andreas Gohr +email andi@splitbrain.org +date 2013-05-02 +name Dummy Plugin +desc Dummy plugin data +url http://example.com/plugin:plugin6 diff --git a/lib/plugins/extension/_test/testdata/plugin1/syntax.php b/lib/plugins/extension/_test/testdata/plugin1/syntax.php new file mode 100644 index 000000000..e69de29bb diff --git a/lib/plugins/extension/_test/testdata/plugin2/plugin.info.txt b/lib/plugins/extension/_test/testdata/plugin2/plugin.info.txt new file mode 100644 index 000000000..d56758fe9 --- /dev/null +++ b/lib/plugins/extension/_test/testdata/plugin2/plugin.info.txt @@ -0,0 +1,7 @@ +base plugin2 +author Andreas Gohr +email andi@splitbrain.org +date 2013-05-02 +name Dummy Plugin +desc Dummy Plugin data +url http://example.com/plugin:plugin2 diff --git a/lib/plugins/extension/_test/testdata/template1/main.php b/lib/plugins/extension/_test/testdata/template1/main.php new file mode 100644 index 000000000..e69de29bb diff --git a/lib/plugins/extension/_test/testdata/template1/style.ini b/lib/plugins/extension/_test/testdata/template1/style.ini new file mode 100644 index 000000000..e69de29bb diff --git a/lib/plugins/extension/_test/testdata/template2/template.info.txt b/lib/plugins/extension/_test/testdata/template2/template.info.txt new file mode 100644 index 000000000..882a7b914 --- /dev/null +++ b/lib/plugins/extension/_test/testdata/template2/template.info.txt @@ -0,0 +1,7 @@ +base template2 +author Andreas Gohr +email andi@splitbrain.org +date 2013-05-02 +name Dummy Template +desc Dummy template data +url http://example.com/template:template2 diff --git a/lib/plugins/extension/_test/testdata/tplfoo5/template.info.txt b/lib/plugins/extension/_test/testdata/tplfoo5/template.info.txt new file mode 100644 index 000000000..4d7ecb8ef --- /dev/null +++ b/lib/plugins/extension/_test/testdata/tplfoo5/template.info.txt @@ -0,0 +1,7 @@ +base template5 +author Andreas Gohr +email andi@splitbrain.org +date 2013-05-02 +name Dummy Template +desc Dummy template data +url http://example.com/template:template5 diff --git a/lib/plugins/extension/_test/testdata/tplsub3/template3/main.php b/lib/plugins/extension/_test/testdata/tplsub3/template3/main.php new file mode 100644 index 000000000..e69de29bb diff --git a/lib/plugins/extension/_test/testdata/tplsub3/template3/style.ini b/lib/plugins/extension/_test/testdata/tplsub3/template3/style.ini new file mode 100644 index 000000000..e69de29bb diff --git a/lib/plugins/extension/_test/testdata/tplsub4/template4/template.info.txt b/lib/plugins/extension/_test/testdata/tplsub4/template4/template.info.txt new file mode 100644 index 000000000..f050555e5 --- /dev/null +++ b/lib/plugins/extension/_test/testdata/tplsub4/template4/template.info.txt @@ -0,0 +1,7 @@ +base template4 +author Andreas Gohr +email andi@splitbrain.org +date 2013-05-02 +name Dummy Template +desc Dummy template data +url http://example.com/template:template4 diff --git a/lib/plugins/extension/_test/testdata/tplsub6/tplfoo6/template.info.txt b/lib/plugins/extension/_test/testdata/tplsub6/tplfoo6/template.info.txt new file mode 100644 index 000000000..ea4dc230d --- /dev/null +++ b/lib/plugins/extension/_test/testdata/tplsub6/tplfoo6/template.info.txt @@ -0,0 +1,7 @@ +base template6 +author Andreas Gohr +email andi@splitbrain.org +date 2013-05-02 +name Dummy Template +desc Dummy template data +url http://example.com/template:template6 diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index cf4eb79d7..e28fd612c 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -67,11 +67,9 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { $this->infoFor = $extname; break; case 'install': - msg('Not implemented'); - break; case 'reinstall': case 'update': - $extension->setExtension($extname, false); + $extension->setExtension($extname); $status = $extension->installOrUpdate(); if ($status !== true) { msg($status, -1); @@ -80,7 +78,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { } break; case 'uninstall': - $extension->setExtension($extname, false); + $extension->setExtension($extname); $status = $extension->uninstall(); if ($status !== true) { msg($status, -1); @@ -89,7 +87,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { } break; case 'enable'; - $extension->setExtension($extname, false); + $extension->setExtension($extname); $status = $extension->enable(); if ($status !== true) { msg($status, -1); @@ -98,7 +96,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { } break; case 'disable'; - $extension->setExtension($extname, false); + $extension->setExtension($extname); $status = $extension->disable(); if ($status !== true) { msg($status, -1); diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 244ec9b9a..62f950cac 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -127,6 +127,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool If an update is available */ public function updateAvailable() { + if(!$this->isInstalled()) return false; $lastupdate = $this->getLastUpdate(); if ($lastupdate === false) return false; $installed = $this->getInstalledVersion(); @@ -518,21 +519,24 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * Install or update the extension * - * @return bool|string True or an error message + * @throws \Exception when something goes wrong + * @return array The list of installed extensions */ public function installOrUpdate() { - if (($status = $this->download($this->getDownloadURL(), $path)) === true) { - if (($status = $this->installArchive($path, $installed_extensions, $this->isInstalled(), $this->getBase())) == true) { - // refresh extension information - if (!isset($installed_extensions[$this->getBase()])) { - $status = 'Error, the requested extension hasn\'t been installed or updated'; - } - $this->setExtension($this->getID()); - $this->purgeCache(); + try { + $path = $this->download($this->getDownloadURL()); + $installed = $this->installArchive($path, $this->isInstalled(), $this->getBase()); + + // refresh extension information + if (!isset($installed[$this->getBase()])) { + throw new Exception('Error, the requested extension hasn\'t been installed or updated'); } - $this->dir_delete(dirname($path)); + $this->setExtension($this->getID()); + $this->purgeCache(); + }catch (Exception $e){ + throw $e; } - return $status; + return $installed; } /** @@ -695,112 +699,108 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * Download an archive to a protected path + * * @param string $url The url to get the archive from - * @param string $path The path where the archive was saved (output parameter) - * @return bool|string True on success, an error message on failure + * @throws Exception when something goes wrong + * @return string The path where the archive was saved */ - public function download($url, &$path) { + public function download($url) { // check the url $matches = array(); if(!preg_match('/[^\/]*$/', $url, $matches) || !$matches[0]) { - return $this->getLang('baddownloadurl'); + throw new Exception($this->getLang('baddownloadurl')); } $file = $matches[0]; // create tmp directory for download if(!($tmp = io_mktmpdir())) { - return $this->getLang('error_dircreate'); + throw new Exception($this->getLang('error_dircreate')); } // download - if(!$file = io_download($url, $tmp.'/', true, $file)) { + if(!$file = io_download($url, $tmp.'/', true, $file, 0)) { $this->dir_delete($tmp); - return sprintf($this->getLang('error_download'), $url); + throw new Exception(sprintf($this->getLang('error_download'), hsc($url))); } - $path = $tmp.'/'.$file; - - return true; + return $tmp.'/'.$file; } /** * @param string $file The path to the archive that shall be installed * @param bool $overwrite If an already installed plugin should be overwritten - * @param array $installed_extensions Array of all installed extensions in the form $base => ('type' => $type, 'action' => 'update'|'install') * @param string $base The basename of the plugin if it's known + * @throws Exception when something went wrong * @return bool|string True on success, an error message on failure */ - public function installArchive($file, &$installed_extensions, $overwrite=false, $base = '') { + public function installArchive($file, $overwrite=false, $base = '') { $error = false; // create tmp directory for decompression if(!($tmp = io_mktmpdir())) { - return $this->getLang('error_dircreate'); + throw new Exception($this->getLang('error_dircreate')); } // add default base folder if specified to handle case where zip doesn't contain this if($base && !@mkdir($tmp.'/'.$base)) { - $error = $this->getLang('error_dircreate'); + throw new Exception($this->getLang('error_dircreate')); } - if(!$error && !$this->decompress("$tmp/$file", "$tmp/".$base)) { - $error = sprintf($this->getLang('error_decompress'), $file); + // decompress + if(!$this->decompress("$tmp/$file", "$tmp/".$base)) { + throw new Exception(sprintf($this->getLang('error_decompress'), $file)); } // search $tmp/$base for the folder(s) that has been created // move the folder(s) to lib/.. - if(!$error) { - $result = array('old'=>array(), 'new'=>array()); - - if(!$this->find_folders($result, $tmp.'/'.$base, ($this->isTemplate() ? 'template' : 'plugin'))) { - $error = $this->getLang('error_findfolder'); + $result = array('old'=>array(), 'new'=>array()); + if(!$this->find_folders($result, $tmp.'/'.$base, ($this->isTemplate() ? 'template' : 'plugin'))) { + throw new Exception($this->getLang('error_findfolder')); + } - } else { - // choose correct result array - if(count($result['new'])) { - $install = $result['new']; - }else{ - $install = $result['old']; - } + // choose correct result array + if(count($result['new'])) { + $install = $result['new']; + }else{ + $install = $result['old']; + } - // now install all found items - foreach($install as $item) { - // where to install? - if($item['type'] == 'template') { - $target_base_dir = DOKU_TPLLIB; - }else{ - $target_base_dir = DOKU_PLUGIN; - } + // now install all found items + foreach($install as $item) { + // where to install? + if($item['type'] == 'template') { + $target_base_dir = DOKU_TPLLIB; + }else{ + $target_base_dir = DOKU_PLUGIN; + } - if(!empty($item['base'])) { - // use base set in info.txt - } elseif($base && count($install) == 1) { - $item['base'] = $base; - } else { - // default - use directory as found in zip - // plugins from github/master without *.info.txt will install in wrong folder - // but using $info->id will make 'code3' fail (which should install in lib/code/..) - $item['base'] = basename($item['tmp']); - } + if(!empty($item['base'])) { + // use base set in info.txt + } elseif($base && count($install) == 1) { + $item['base'] = $base; + } else { + // default - use directory as found in zip + // plugins from github/master without *.info.txt will install in wrong folder + // but using $info->id will make 'code3' fail (which should install in lib/code/..) + $item['base'] = basename($item['tmp']); + } - // check to make sure we aren't overwriting anything - $target = $target_base_dir.$item['base']; - if(!$overwrite && @file_exists($target)) { - // TODO remember our settings, ask the user to confirm overwrite - continue; - } + // check to make sure we aren't overwriting anything + $target = $target_base_dir.$item['base']; + if(!$overwrite && @file_exists($target)) { + // TODO remember our settings, ask the user to confirm overwrite + continue; + } - $action = @file_exists($target) ? 'update' : 'install'; + $action = @file_exists($target) ? 'update' : 'install'; - // copy action - if($this->dircopy($item['tmp'], $target)) { - // TODO: write manager.dat! - $installed_extensions[$item['base']] = array('type' => $item['type'], 'action' => $action); - } else { - $error = sprintf($this->getLang('error_copy').DOKU_LF, $item['base']); - break; - } - } + // copy action + if($this->dircopy($item['tmp'], $target)) { + // TODO: write manager.dat! + $installed_extensions[$item['base']] = array('type' => $item['type'], 'action' => $action); + } else { + $error = sprintf($this->getLang('error_copy').DOKU_LF, $item['base']); + break; } } @@ -830,25 +830,24 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * * @author Andreas Gohr * @param array $result - results are stored here - * @param string $base - the temp directory where the package was unpacked to + * @param string $directory - the temp directory where the package was unpacked to * @param string $default_type - type used if no info.txt available - * @param string $dir - a subdirectory. do not set. used by recursion + * @param string $subdir - a subdirectory. do not set. used by recursion * @return bool - false on error */ - private function find_folders(&$result, $base, $default_type, $dir='') { - $this_dir = "$base$dir"; + protected function find_folders(&$result, $directory, $default_type='plugin', $subdir='') { + $this_dir = "$directory$subdir"; $dh = @opendir($this_dir); if(!$dh) return false; $found_dirs = array(); $found_files = 0; $found_template_parts = 0; - $found_info_txt = false; while (false !== ($f = readdir($dh))) { if($f == '.' || $f == '..') continue; if(is_dir("$this_dir/$f")) { - $found_dirs[] = "$dir/$f"; + $found_dirs[] = "$subdir/$f"; } else { // it's a file -> check for config @@ -856,7 +855,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { switch ($f) { case 'plugin.info.txt': case 'template.info.txt': - $found_info_txt = true; + // we have found a clear marker, save and return $info = array(); $type = explode('.', $f, 2); $info['type'] = $type[0]; @@ -864,7 +863,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $conf = confToHash("$this_dir/$f"); $info['base'] = basename($conf['base']); $result['new'][] = $info; - break; + return true; case 'main.php': case 'details.php': @@ -877,33 +876,24 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } closedir($dh); - // URL downloads default to 'plugin', try extra hard to indentify templates - if(!$default_type && $found_template_parts > 2 && !$found_info_txt) { + // files where found but no info.txt - use old method + if($found_files){ $info = array(); - $info['type'] = 'template'; $info['tmp'] = $this_dir; - $result['new'][] = $info; - } + // does this look like a template or should we use the default type? + if($found_template_parts >= 2) { + $info['type'] = 'template'; + } else { + $info['type'] = $default_type; + } - // files in top level but no info.txt, assume this is zip missing a base directory - // works for all downloads unless direct URL where $base will be the tmp directory ($info->id was empty) - if(!$dir && $found_files > 0 && !$found_info_txt && $default_type) { - $info = array(); - $info['type'] = $default_type; - $info['tmp'] = $base; $result['old'][] = $info; return true; } + // we have no files yet -> recurse foreach ($found_dirs as $found_dir) { - // if top level add to dir list for old method, then recurse - if(!$dir) { - $info = array(); - $info['type'] = ($default_type ? $default_type : 'plugin'); - $info['tmp'] = "$base$found_dir"; - $result['old'][] = $info; - } - $this->find_folders($result, $base, $default_type, "$found_dir"); + $this->find_folders($result, $directory, $default_type, "$found_dir"); } return true; } -- cgit v1.2.3 From 5c0b30bf48d7f8e5f3d5764cfab94d0d09c0a8b1 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 21:26:20 +0200 Subject: installation now works --- lib/plugins/extension/admin.php | 14 +++++++------ lib/plugins/extension/helper/extension.php | 33 ++++++++++++++++++------------ lib/plugins/extension/lang/en/lang.php | 9 +++++++- 3 files changed, 36 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index e28fd612c..f1ed83591 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -69,12 +69,14 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { case 'install': case 'reinstall': case 'update': - $extension->setExtension($extname); - $status = $extension->installOrUpdate(); - if ($status !== true) { - msg($status, -1); - } else { - msg(sprintf($this->getLang('msg_update_success'), hsc($extension->getDisplayName())), 1); + try { + $extension->setExtension($extname); + $installed = $extension->installOrUpdate(); + foreach($installed as $extension => $info){ + msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); + } + }catch (Exception $e){ + msg($e->getMessage(), -1); } break; case 'uninstall': diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 62f950cac..8438253f9 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -528,7 +528,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $installed = $this->installArchive($path, $this->isInstalled(), $this->getBase()); // refresh extension information - if (!isset($installed[$this->getBase()])) { + if (!isset($installed[$this->getID()])) { throw new Exception('Error, the requested extension hasn\'t been installed or updated'); } $this->setExtension($this->getID()); @@ -734,7 +734,6 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool|string True on success, an error message on failure */ public function installArchive($file, $overwrite=false, $base = '') { - $error = false; // create tmp directory for decompression if(!($tmp = io_mktmpdir())) { @@ -747,14 +746,21 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } // decompress - if(!$this->decompress("$tmp/$file", "$tmp/".$base)) { + if(!$this->decompress($file, "$tmp/".$base)) { throw new Exception(sprintf($this->getLang('error_decompress'), $file)); } // search $tmp/$base for the folder(s) that has been created // move the folder(s) to lib/.. $result = array('old'=>array(), 'new'=>array()); - if(!$this->find_folders($result, $tmp.'/'.$base, ($this->isTemplate() ? 'template' : 'plugin'))) { + if($base){ + // when a base was set it came from the current extension setup #fixme this is a bit hacky + $default = ($this->isTemplate() ? 'template' : 'plugin'); + }else{ + // assume a default of plugin, find_folders will autodetect templates + $default = 'plugin'; + } + if(!$this->find_folders($result, $tmp.'/'.$base, $default)) { throw new Exception($this->getLang('error_findfolder')); } @@ -796,22 +802,23 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { // copy action if($this->dircopy($item['tmp'], $target)) { - // TODO: write manager.dat! - $installed_extensions[$item['base']] = array('type' => $item['type'], 'action' => $action); + // return info + $id = $item['base']; + if($item['type'] == 'template') $id = 'template:'.$id; + $installed_extensions[$id] = array( + 'base' => $item['base'], + 'type' => $item['type'], + 'action' => $action + ); } else { - $error = sprintf($this->getLang('error_copy').DOKU_LF, $item['base']); - break; + throw new Exception(sprintf($this->getLang('error_copy').DOKU_LF, $item['base'])); } } // cleanup if($tmp) $this->dir_delete($tmp); - if($error) { - return $error; - } - - return true; + return $installed_extensions; } /** diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 24cabe1fa..1a5c90923 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -73,11 +73,18 @@ $lang['msg_notenabled'] = 'Plugin %s could not be enabled, check file pe $lang['msg_disabled'] = 'Plugin %s disabled'; $lang['msg_notdisabled'] = 'Plugin %s could not be disabled, check file permissions'; + +$lang['msg_template_install_success'] = 'Template %s installed successfully'; +$lang['msg_template_update_success'] = 'Template %s updated successfully'; +$lang['msg_plugin_install_success'] = 'Plugin %s installed successfully'; +$lang['msg_plugin_update_success'] = 'Plugin %s updated successfully'; + + $lang['msg_url_failed'] = 'URL [%s] could not be downloaded.
      %s'; $lang['msg_download_failed'] = 'Plugin %s could not be downloaded.
      %s'; $lang['msg_download_success'] = 'Plugin %s installed successfully'; $lang['msg_tpl_download_failed'] = 'Template %s could not be downloaded.
      %s'; -$lang['msg_tpl_download_success'] = 'Template %s installed successfully'; + $lang['msg_download_pkg_success'] = '%s extension package successfully installed (%s)'; $lang['msg_tpl_download_pkg_success'] = '%s extension package successfully installed (%s)'; -- cgit v1.2.3 From 045d57189c1fb4e8775603cd39927557e3eddfd9 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 21:34:51 +0200 Subject: make sure temporary folders are cleaned up --- lib/plugins/extension/helper/extension.php | 32 ++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 8438253f9..dc570aa0d 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -23,6 +23,20 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** @var helper_plugin_extension_repository $repository */ private $repository = null; + /** @var array list of temporary directories */ + private $temporary = array(); + + /** + * Destructor + * + * deletes any dangling temporary directories + */ + public function __destruct() { + foreach($this->temporary as $dir){ + $this->dir_delete($dir); + } + } + /** * @return bool false, this component is not a singleton */ @@ -697,6 +711,20 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } } + /** + * Returns a temporary directory + * + * The directory is registered for cleanup when the class is destroyed + * + * @return bool|string + */ + protected function mkTmpDir(){ + $dir = io_mktmpdir(); + if(!$dir) return false; + $this->temporary[] = $dir; + return $dir; + } + /** * Download an archive to a protected path * @@ -713,7 +741,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $file = $matches[0]; // create tmp directory for download - if(!($tmp = io_mktmpdir())) { + if(!($tmp = $this->mkTmpDir())) { throw new Exception($this->getLang('error_dircreate')); } @@ -736,7 +764,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { public function installArchive($file, $overwrite=false, $base = '') { // create tmp directory for decompression - if(!($tmp = io_mktmpdir())) { + if(!($tmp = $this->mkTmpDir())) { throw new Exception($this->getLang('error_dircreate')); } -- cgit v1.2.3 From 341cc636324f216ddc217fc03f02004b8423b9f0 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 21:38:31 +0200 Subject: sort plugins --- lib/plugins/extension/helper/gui.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 09cea7fcb..57dfefab3 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -29,6 +29,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { echo $this->locale_xhtml('intro_plugins'); $pluginlist = $plugin_controller->getList('', true); + sort($pluginlist); /* @var helper_plugin_extension_extension $extension */ $extension = $this->loadHelper('extension_extension'); /* @var helper_plugin_extension_list $list */ @@ -51,6 +52,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { // FIXME do we have a real way? $tpllist = glob(DOKU_INC.'lib/tpl/*', GLOB_ONLYDIR); $tpllist = array_map('basename', $tpllist); + sort($tpllist); /* @var helper_plugin_extension_extension $extension */ $extension = $this->loadHelper('extension_extension'); -- cgit v1.2.3 From 8251e9612a372ea2e25e0d896fb0c3b8e4c3af73 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 21:54:37 +0200 Subject: some style changes --- lib/plugins/extension/helper/list.php | 8 +++++--- lib/plugins/extension/images/tag.png | Bin 0 -> 753 bytes lib/plugins/extension/style.less | 30 +++++++++--------------------- 3 files changed, 14 insertions(+), 24 deletions(-) create mode 100644 lib/plugins/extension/images/tag.png (limited to 'lib') diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 62031a69b..79728b5ca 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -244,7 +244,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { } if($extension->getTags()){ $first = true; - echo ''; + $return .= ''; foreach ($extension->getTags() as $tag) { if(!$first){ $return .= ', '; @@ -254,7 +254,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $url = $this->gui->tabURL('search', array('q' => 'tag:'.$tag)); $return .= ''.hsc($tag).''; } - echo ''; + $return .= ''; } $return .= ''; return $return; @@ -451,7 +451,9 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { } if (!$extension->isProtected()) { if ($extension->isEnabled()) { - $return .= $this->make_action('disable', $extension); + if(!$extension->isTemplate()){ // templates can't be disabled, only anothe can be enabled + $return .= $this->make_action('disable', $extension); + } } else { $return .= $this->make_action('enable', $extension); } diff --git a/lib/plugins/extension/images/tag.png b/lib/plugins/extension/images/tag.png new file mode 100644 index 000000000..155dbb3dd Binary files /dev/null and b/lib/plugins/extension/images/tag.png differ diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index cd9eeaa74..53c260f8d 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -20,6 +20,7 @@ background: url(images/overlay.png) repeat; text-align: center; cursor: pointer; + z-index: 9999; p { text-align: right; @@ -44,16 +45,6 @@ margin-left: 0; } -#extension__manager a.taglink { - padding: 1px 4px; - background-color: @ini_background_neu; - border-radius: 3px; -} -[dir=rtl] #extension__manager a.taglink { - display: inline-block; - line-height: 1.2; -} - #extension__manager .panelHeader div.error { margin-top: 0; float: left; @@ -173,6 +164,10 @@ background: transparent url(images/disabled.png) no-repeat 2px 2px; } +#extension__manager .disabled .legend { + opacity: 0.7; +} + #extension__manager div.screenshot img { width: 120px; height: 70px; @@ -227,19 +222,12 @@ font-size: 85%; } -#extension__manager .legend span.linkbar a.urlextern + a.taglink, -#extension__manager .legend span.linkbar a.interwiki + a.taglink { - margin-left: 0.4em; -} -[dir=rtl] #extension__manager .legend span.linkbar a.urlextern + a.taglink, -[dir=rtl] #extension__manager .legend span.linkbar a.interwiki + a.taglink { - margin-left: 0; -} -[dir=rtl] #extension__manager .legend span.linkbar a.urlextern, -[dir=rtl] #extension__manager .legend span.linkbar a.interwiki { - margin-left: .4em; +#extension__manager .legend span.linkbar span.tags { + padding-left: 18px; + background: transparent url(images/tag.png) no-repeat 0 0; } + #extension__manager .legend input.button { background: transparent url(images/up.png) no-repeat 0 0; box-shadow: none; -- cgit v1.2.3 From 1e0eea17dc60dc6f5ec81ffcca313db353c88c44 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 22:11:52 +0200 Subject: fixed popularity display --- lib/plugins/extension/helper/extension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index dc570aa0d..b3bce082f 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -349,7 +349,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return float|bool The popularity information or false if it isn't available */ public function getPopularity() { - if (!empty($this->remoteInfo['popularity'])) return $this->remoteInfo['popularity']/200.0; + if (!empty($this->remoteInfo['popularity'])) return $this->remoteInfo['popularity']; return false; } -- cgit v1.2.3 From 75e063084d865a011e074c29c5edb8569fe2cfe1 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 22:58:01 +0200 Subject: made info mechanism work again --- lib/plugins/extension/admin.php | 3 -- lib/plugins/extension/helper/gui.php | 21 +++++++++++--- lib/plugins/extension/helper/list.php | 43 ++++++++++++++--------------- lib/plugins/extension/helper/repository.php | 12 ++++++-- lib/plugins/extension/style.less | 11 ++++---- 5 files changed, 54 insertions(+), 36 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index f1ed83591..3237a26e5 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -63,9 +63,6 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { foreach ($actions as $action => $extensions) { foreach ($extensions as $extname => $label) { switch ($action) { - case 'info': - $this->infoFor = $extname; - break; case 'install': case 'reinstall': case 'update': diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 57dfefab3..6a0cdb22e 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -17,7 +17,18 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { protected $tabs = array('plugins', 'templates', 'search', 'install'); /** @var string the extension that should have an open info window FIXME currently broken*/ - protected $infofor = ''; + protected $infoFor = ''; + + /** + * Constructor + * + * initializes requested info window + */ + public function __construct(){ + global $INPUT; + $this->infoFor = $INPUT->str('info'); + } + /** * display the plugin tab @@ -37,7 +48,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $list->start_form(); foreach($pluginlist as $name) { $extension->setExtension($name); - $list->add_row($extension, $name == $this->infoFor); + $list->add_row($extension, $extension->getID() == $this->infoFor); } $list->end_form(); $list->render(); @@ -61,7 +72,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $list->start_form(); foreach($tpllist as $name) { $extension->setExtension("template:$name"); - $list->add_row($extension, $name == $this->infoFor); + $list->add_row($extension, $extension->getID() == $this->infoFor); } $list->end_form(); $list->render(); @@ -93,7 +104,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { $list->start_form(); foreach($result as $name) { $extension->setExtension($name); - $list->add_row($extension, $name == $this->infoFor); + $list->add_row($extension, $extension->getID() == $this->infoFor); } $list->end_form(); $list->render(); @@ -149,12 +160,14 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { */ public function tabURL($tab = '', $params = array(), $sep = '&') { global $ID; + global $INPUT; if(!$tab) $tab = $this->currentTab(); $defaults = array( 'do' => 'admin', 'page' => 'extension', 'tab' => $tab, + 'q' => $INPUT->str('q') ); return wl($ID, array_merge($defaults, $params), false, $sep); } diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 79728b5ca..767a8ed40 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -101,7 +101,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * @param helper_plugin_extension_extension $extension The extension */ private function start_row(helper_plugin_extension_extension $extension) { - $this->form .= '
    • '; + $this->form .= '
    • '; } /** @@ -221,7 +221,15 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $return .= '

      '; $return .= $this->make_linkbar($extension); - $return .= $this->make_action('info', $extension, $showinfo); + + if($showinfo){ + $url = $this->gui->tabURL(''); + $return .= ''.$this->getLang('btn_info').''; + }else{ + $url = $this->gui->tabURL('', array('info' => $extension->getID())); + $return .= ''.$this->getLang('btn_info').''; + } + if ($showinfo) { $return .= $this->make_info($extension); } @@ -415,15 +423,14 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { /** * Generate a list of links for extensions - * @param array $links The links + * + * @param array $ext The extensions * @return string The HTML code */ - function make_linklist($links) { + function make_linklist($ext) { $return = ''; - foreach ($links as $link) { - $dokulink = hsc($link); - if (strpos($link, 'template:') !== 0) $dokulink = 'plugin:'.$dokulink; - $return .= ''.$link.' '; + foreach ($ext as $link) { + $return .= ''.hsc($link).' '; } return $return; } @@ -438,7 +445,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $return = ''; if (!$extension->isInstalled() && $extension->canModify() === true) { $return .= $this->make_action('install', $extension); - } elseif ($extension->canModify()) { + } elseif ($extension->canModify() === true) { if (!$extension->isBundled()) { $return .= $this->make_action('uninstall', $extension); if ($extension->getDownloadURL()) { @@ -451,7 +458,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { } if (!$extension->isProtected()) { if ($extension->isEnabled()) { - if(!$extension->isTemplate()){ // templates can't be disabled, only anothe can be enabled + if(!$extension->isTemplate()){ // templates can't be disabled, only another can be enabled $return .= $this->make_action('disable', $extension); } } else { @@ -473,28 +480,20 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { * * @param string $action The action * @param helper_plugin_extension_extension $extension The extension - * @param bool $showinfo If the info block is shown * @return string The HTML code */ - function make_action($action, $extension, $showinfo = false) { - $title = $revertAction = $extraClass = ''; + function make_action($action, $extension) { + $title = ''; switch ($action) { - case 'info': - $title = 'title="'.$this->getLang('btn_info').'"'; - if ($showinfo) { - $revertAction = '-'; - $extraClass = 'close'; - } - break; case 'install': case 'reinstall': $title = 'title="'.$extension->getDownloadURL().'"'; break; } - $classes = 'button '.$action.' '.$extraClass; - $name = 'fn['.$action.']['.$revertAction.hsc($extension->getInstallName()).']'; + $classes = 'button '.$action; + $name = 'fn['.$action.']['.hsc($extension->getID()).']'; return ''; } diff --git a/lib/plugins/extension/helper/repository.php b/lib/plugins/extension/helper/repository.php index 38e07786e..1f603a866 100644 --- a/lib/plugins/extension/helper/repository.php +++ b/lib/plugins/extension/helper/repository.php @@ -146,9 +146,10 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { */ protected function parse_query($q){ $parameters = array( - 'tag' => array(), + 'tag' => array(), 'mail' => array(), - 'type' => array() + 'type' => array(), + 'ext' => array() ); // extract tags @@ -165,6 +166,13 @@ class helper_plugin_extension_repository extends DokuWiki_Plugin { $parameters['mail'][] = $m[3]; } } + // extract extensions + if(preg_match_all('/(^|\s)(ext:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ + foreach($matches as $m){ + $q = str_replace($m[2], '', $q); + $parameters['ext'][] = $m[3]; + } + } // extract types if(preg_match_all('/(^|\s)(type:([\S]+))/', $q, $matches, PREG_SET_ORDER)){ foreach($matches as $m){ diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index 53c260f8d..fc5613044 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -228,21 +228,22 @@ } -#extension__manager .legend input.button { +#extension__manager .legend a.info { background: transparent url(images/up.png) no-repeat 0 0; - box-shadow: none; border-width: 0; - height: 14px; + height: 13px; + width: 13px; text-indent: -99999px; float: right; margin: .5em 0 0; + overflow: hidden; } -[dir=rtl] #extension__manager .legend input.button { +[dir=rtl] #extension__manager .legend a.info { float: left; margin: .5em 0 0; } -#extension__manager .legend input.button.close { +#extension__manager .legend a.info.close { background: transparent url(images/down.png) no-repeat 0 0; } -- cgit v1.2.3 From 72dda0b4378651b271f5fb516fb8e21a80ac3ebf Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Fri, 9 Aug 2013 23:55:39 +0200 Subject: added AJAX detail infos --- lib/plugins/extension/action.php | 51 +++++++++++++++++++++++++++++++++++ lib/plugins/extension/helper/list.php | 5 ++-- lib/plugins/extension/script.js | 29 +++++++++++++++++++- 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 lib/plugins/extension/action.php (limited to 'lib') diff --git a/lib/plugins/extension/action.php b/lib/plugins/extension/action.php new file mode 100644 index 000000000..b35c1cb13 --- /dev/null +++ b/lib/plugins/extension/action.php @@ -0,0 +1,51 @@ + + */ + +// must be run within Dokuwiki +if(!defined('DOKU_INC')) die(); + +class action_plugin_extension extends DokuWiki_Action_Plugin { + + /** + * Registers a callback function for a given event + * + * @param Doku_Event_Handler $controller DokuWiki's event controller object + * @return void + */ + public function register(Doku_Event_Handler &$controller) { + + $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'info'); + + } + + public function info(Doku_Event &$event, $param){ + global $INPUT; + if($event->data != 'plugin_extension') return; + $event->preventDefault(); + $event->stopPropagation(); + + header('Content-Type: text/html; charset=utf-8'); + + $ext = $INPUT->str('ext'); + if(!$ext) { + echo 'no extension given'; + return; + } + + /** @var helper_plugin_extension_extension $extension */ + $extension = plugin_load('helper', 'extension_extension'); + $extension->setExtension($ext); + + /** @var helper_plugin_extension_list $list */ + $list = plugin_load('helper', 'extension_list'); + + + echo $list->make_info($extension); + } + +} + diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 767a8ed40..6b1d41f78 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -224,11 +224,12 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { if($showinfo){ $url = $this->gui->tabURL(''); - $return .= ''.$this->getLang('btn_info').''; + $class = 'close'; }else{ $url = $this->gui->tabURL('', array('info' => $extension->getID())); - $return .= ''.$this->getLang('btn_info').''; + $class = ''; } + $return .= ''.$this->getLang('btn_info').''; if ($showinfo) { $return .= $this->make_info($extension); diff --git a/lib/plugins/extension/script.js b/lib/plugins/extension/script.js index f2a6aae50..7480801ac 100644 --- a/lib/plugins/extension/script.js +++ b/lib/plugins/extension/script.js @@ -5,7 +5,7 @@ jQuery(function(){ * very simple lightbox * @link http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/super-simple-lightbox-with-css-and-jquery/ */ - jQuery('a.extension_screenshot').click(function(e) { + jQuery('#extension__manager a.extension_screenshot').click(function(e) { e.preventDefault(); //Get clicked link href @@ -31,4 +31,31 @@ jQuery(function(){ return false; }); + /** + * AJAX detail infos + */ + jQuery('#extension__manager a.info').click(function(e){ + e.preventDefault(); + + var $link = jQuery(this); + var $details = $link.parent().find('dl.details'); + if($details.length){ + $link.toggleClass('close'); + $details.toggle(); + return; + } + + $link.addClass('close'); + jQuery.get( + DOKU_BASE + 'lib/exe/ajax.php', + { + call: 'plugin_extension', + ext: $link.data('extid') + }, + function(data){ + $link.parent().append(data); + } + ); + }); + }); \ No newline at end of file -- cgit v1.2.3 From fee60c9e19860de9edb1dd146ec7063bb9eda392 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 10 Aug 2013 10:23:04 +0200 Subject: manual install tab now works --- lib/plugins/extension/admin.php | 46 +++++++++----- lib/plugins/extension/helper/extension.php | 98 +++++++++++++++++++++++++----- lib/plugins/extension/helper/gui.php | 14 +++-- lib/plugins/extension/lang/en/lang.php | 4 +- 4 files changed, 127 insertions(+), 35 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 3237a26e5..62d94e899 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -22,7 +22,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { * * loads additional helpers */ - public function __construct(){ + public function __construct() { $this->gui = plugin_load('helper', 'extension_gui'); } @@ -49,37 +49,36 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { /* @var helper_plugin_extension_repository $repository */ $repository = $this->loadHelper('extension_repository'); - - if(!$repository->hasAccess()){ - $url = $this->gui->tabURL('', array('purge'=>1)); + if(!$repository->hasAccess()) { + $url = $this->gui->tabURL('', array('purge' => 1)); msg($this->getLang('repo_error').' ['.$this->getLang('repo_retry').']', -1); } /* @var helper_plugin_extension_extension $extension */ $extension = $this->loadHelper('extension_extension'); - if ($INPUT->post->has('fn')) { + if($INPUT->post->has('fn') && checkSecurityToken()) { $actions = $INPUT->post->arr('fn'); - foreach ($actions as $action => $extensions) { - foreach ($extensions as $extname => $label) { - switch ($action) { + foreach($actions as $action => $extensions) { + foreach($extensions as $extname => $label) { + switch($action) { case 'install': case 'reinstall': case 'update': try { $extension->setExtension($extname); $installed = $extension->installOrUpdate(); - foreach($installed as $extension => $info){ + foreach($installed as $ext => $info) { msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); } - }catch (Exception $e){ + } catch(Exception $e) { msg($e->getMessage(), -1); } break; case 'uninstall': $extension->setExtension($extname); $status = $extension->uninstall(); - if ($status !== true) { + if($status !== true) { msg($status, -1); } else { msg(sprintf($this->getLang('msg_delete_success'), hsc($extension->getDisplayName())), 1); @@ -88,7 +87,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { case 'enable'; $extension->setExtension($extname); $status = $extension->enable(); - if ($status !== true) { + if($status !== true) { msg($status, -1); } else { msg(sprintf($this->getLang('msg_enabled'), hsc($extension->getDisplayName())), 1); @@ -97,7 +96,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { case 'disable'; $extension->setExtension($extname); $status = $extension->disable(); - if ($status !== true) { + if($status !== true) { msg($status, -1); } else { msg(sprintf($this->getLang('msg_disabled'), hsc($extension->getDisplayName())), 1); @@ -106,6 +105,24 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { } } } + } elseif($INPUT->post->str('installurl') && checkSecurityToken()) { + try { + $installed = $extension->installFromURL($INPUT->post->str('installurl')); + foreach($installed as $ext => $info) { + msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); + } + } catch(Exception $e) { + msg($e->getMessage(), -1); + } + } elseif(isset($_FILES['installfile']) && checkSecurityToken()) { + try { + $installed = $extension->installFromUpload('installfile'); + foreach($installed as $ext => $info) { + msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); + } + } catch(Exception $e) { + msg($e->getMessage(), -1); + } } } @@ -118,7 +135,7 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { $this->gui->tabNavigation(); - switch($this->gui->currentTab()){ + switch($this->gui->currentTab()) { case 'search': $this->gui->tabSearch(); break; @@ -133,7 +150,6 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { $this->gui->tabPlugins(); } - ptln('
    '); } } diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index b3bce082f..550fc33fb 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -530,6 +530,67 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { return true; } + /** + * Install an extension from a user upload + * + * @param string $field name of the upload file + * @throws Exception when something goes wrong + * @return array The list of installed extensions + */ + public function installFromUpload($field){ + if($_FILES[$field]['error']){ + throw new Exception($this->getLang('msg_upload_failed').' ('.$_FILES[$field]['error'].')'); + } + + $tmp = $this->mkTmpDir(); + if(!$tmp) throw new Exception($this->getLang('error_dircreate')); + + // filename may contain the plugin name for old style plugins... + $basename = basename($_FILES[$field]['name']); + $basename = preg_replace('/\.(tar\.gz|tar\.bz|tar\.bz2|tar|tgz|tbz|zip)$/', '', $basename); + $basename = preg_replace('/[\W]+/', '', $basename); + + if(!move_uploaded_file($_FILES[$field]['tmp_name'], "$tmp/upload.archive")){ + throw new Exception($this->getLang('msg_upload_failed')); + } + + try { + $installed = $this->installArchive("$tmp/upload.archive", true, $basename); + + // purge caches + foreach($installed as $ext => $info){ + $this->setExtension($ext); + $this->purgeCache(); + } + }catch (Exception $e){ + throw $e; + } + return $installed; + } + + /** + * Install an extension from a remote URL + * + * @param string $url + * @throws Exception when something goes wrong + * @return array The list of installed extensions + */ + public function installFromURL($url){ + try { + $path = $this->download($url); + $installed = $this->installArchive($path, true); + + // purge caches + foreach($installed as $ext => $info){ + $this->setExtension($ext); + $this->purgeCache(); + } + }catch (Exception $e){ + throw $e; + } + return $installed; + } + /** * Install or update the extension * @@ -759,9 +820,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @param bool $overwrite If an already installed plugin should be overwritten * @param string $base The basename of the plugin if it's known * @throws Exception when something went wrong - * @return bool|string True on success, an error message on failure + * @return array list of installed extensions */ public function installArchive($file, $overwrite=false, $base = '') { + $installed_extensions = array(); // create tmp directory for decompression if(!($tmp = $this->mkTmpDir())) { @@ -774,20 +836,16 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } // decompress - if(!$this->decompress($file, "$tmp/".$base)) { - throw new Exception(sprintf($this->getLang('error_decompress'), $file)); + try{ + $this->decompress($file, "$tmp/".$base); + } catch (Exception $e) { + throw $e; } // search $tmp/$base for the folder(s) that has been created // move the folder(s) to lib/.. $result = array('old'=>array(), 'new'=>array()); - if($base){ - // when a base was set it came from the current extension setup #fixme this is a bit hacky - $default = ($this->isTemplate() ? 'template' : 'plugin'); - }else{ - // assume a default of plugin, find_folders will autodetect templates - $default = 'plugin'; - } + $default = ($this->isTemplate() ? 'template' : 'plugin'); if(!$this->find_folders($result, $tmp.'/'.$base, $default)) { throw new Exception($this->getLang('error_findfolder')); } @@ -799,6 +857,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $install = $result['old']; } + if(!count($install)){ + throw new Exception($this->getLang('error_findfolder')); + } + // now install all found items foreach($install as $item) { // where to install? @@ -933,11 +995,15 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { return true; } - /** * Decompress a given file to the given target directory * * Determines the compression type from the file extension + * + * @param string $file archive to extract + * @param string $target directory to extract to + * @throws Exception + * @return bool */ private function decompress($file, $target) { // decompression library doesn't like target folders ending in "/" @@ -961,7 +1027,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $tar->open($file, $compress_type); $tar->extract($target); } catch (Exception $e) { - return $e->getMessage(); + throw new Exception($this->getLang('error_decompress').' '.$e->getMessage()); } return true; @@ -970,11 +1036,15 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $zip = new ZipLib(); $ok = $zip->Extract($file, $target); - return ($ok==-1 ? 'Error extracting the zip archive' : true); + if($ok == -1){ + throw new Exception($this->getLang('error_decompress').' Error extracting the zip archive'); + } + + return true; } // the only case when we don't get one of the recognized archive types is when the archive file can't be read - return 'Couldn\'t read archive file'; + throw new Exception($this->getLang('error_decompress').' Couldn\'t read archive file'); } /** diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 6a0cdb22e..8577a1696 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -16,7 +16,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { protected $tabs = array('plugins', 'templates', 'search', 'install'); - /** @var string the extension that should have an open info window FIXME currently broken*/ + /** @var string the extension that should have an open info window FIXME currently broken */ protected $infoFor = ''; /** @@ -24,12 +24,11 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * * initializes requested info window */ - public function __construct(){ + public function __construct() { global $INPUT; $this->infoFor = $INPUT->str('info'); } - /** * display the plugin tab */ @@ -92,10 +91,9 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { if(!$INPUT->bool('q')) return; - /* @var helper_plugin_extension_repository $repository FIXME should we use some gloabl instance? */ $repository = $this->loadHelper('extension_repository'); - $result = $repository->search($INPUT->str('q')); + $result = $repository->search($INPUT->str('q')); /* @var helper_plugin_extension_extension $extension */ $extension = $this->loadHelper('extension_extension'); @@ -116,6 +114,12 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { */ public function tabInstall() { echo $this->locale_xhtml('intro_install'); + + $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'), 'enctype' => 'multipart/form-data')); + $form->addElement(form_makeTextField('installurl', '', 'Install from URL:', '', 'block')); + $form->addElement(form_makeFileField('installfile', 'Upload Extension:', '', 'block')); + $form->addElement(form_makeButton('submit', '', 'Install')); + $form->printForm(); } /** diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 1a5c90923..0c4582124 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -79,6 +79,8 @@ $lang['msg_template_update_success'] = 'Template %s updated successfully'; $lang['msg_plugin_install_success'] = 'Plugin %s installed successfully'; $lang['msg_plugin_update_success'] = 'Plugin %s updated successfully'; +$lang['msg_upload_failed'] = 'Uploading the file failed'; + $lang['msg_url_failed'] = 'URL [%s] could not be downloaded.
    %s'; $lang['msg_download_failed'] = 'Plugin %s could not be downloaded.
    %s'; @@ -130,7 +132,7 @@ $lang['no_manager'] = 'Could not find manager.dat file'; $lang['error_badurl'] = 'URL ends with slash - unable to determine file name from the url'; $lang['error_dircreate'] = 'Unable to create temporary folder to receive download'; $lang['error_download'] = 'Unable to download the file: %s'; -$lang['error_decompress'] = 'Unable to decompress the downloaded file. This maybe as a result of a bad download, in which case you should try again; or the compression format may be unknown, in which case you will need to download and install manually'; +$lang['error_decompress'] = 'Unable to decompress the downloaded file. This maybe as a result of a bad download, in which case you should try again; or the compression format may be unknown, in which case you will need to download and install manually.'; $lang['error_findfolder'] = 'Unable to identify extension directory, you need to download and install manually'; $lang['error_copy'] = 'There was a file copy error while attempting to install files for directory %s: the disk could be full or file access permissions may be incorrect. This may have resulted in a partially installed plugin and leave your wiki installation unstable'; //Setup VIM: ex: et ts=4 : -- cgit v1.2.3 From df7751c6c456e0107b11d547c159266b470470d9 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 10 Aug 2013 10:45:29 +0200 Subject: nicer tabs --- lib/plugins/extension/helper/gui.php | 8 ++++++++ lib/plugins/extension/lang/en/intro_install.txt | 2 +- lib/plugins/extension/lang/en/intro_plugins.txt | 2 +- lib/plugins/extension/lang/en/intro_search.txt | 2 +- lib/plugins/extension/lang/en/intro_templates.txt | 2 +- lib/plugins/extension/style.less | 20 ++++++++++++++++++++ 6 files changed, 32 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 8577a1696..7ad238af4 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -36,7 +36,9 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { /* @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; + echo '
    '; echo $this->locale_xhtml('intro_plugins'); + echo '
    '; $pluginlist = $plugin_controller->getList('', true); sort($pluginlist); @@ -57,7 +59,9 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * Display the template tab */ public function tabTemplates() { + echo '
    '; echo $this->locale_xhtml('intro_templates'); + echo '
    '; // FIXME do we have a real way? $tpllist = glob(DOKU_INC.'lib/tpl/*', GLOB_ONLYDIR); @@ -82,7 +86,9 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { */ public function tabSearch() { global $INPUT; + echo '
    '; echo $this->locale_xhtml('intro_search'); + echo '
    '; $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'))); $form->addElement(form_makeTextField('q', $INPUT->str('q'), 'Search')); @@ -113,7 +119,9 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * Display the template tab */ public function tabInstall() { + echo '
    '; echo $this->locale_xhtml('intro_install'); + echo '
    '; $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'), 'enctype' => 'multipart/form-data')); $form->addElement(form_makeTextField('installurl', '', 'Install from URL:', '', 'block')); diff --git a/lib/plugins/extension/lang/en/intro_install.txt b/lib/plugins/extension/lang/en/intro_install.txt index f68d2d909..0556c8048 100644 --- a/lib/plugins/extension/lang/en/intro_install.txt +++ b/lib/plugins/extension/lang/en/intro_install.txt @@ -1 +1 @@ -Here you can manual install plugins and templates by either uploading them or providing a direct download URL. \ No newline at end of file +Here you can manually install plugins and templates by either uploading them or providing a direct download URL. \ No newline at end of file diff --git a/lib/plugins/extension/lang/en/intro_plugins.txt b/lib/plugins/extension/lang/en/intro_plugins.txt index ef180135e..4e42efee1 100644 --- a/lib/plugins/extension/lang/en/intro_plugins.txt +++ b/lib/plugins/extension/lang/en/intro_plugins.txt @@ -1 +1 @@ -Here you can view, enable and disable installed plugins. \ No newline at end of file +These are the plugins currently installed in your DokuWiki. You can enable or disable or even completely uninstall them here. Plugin updates are shown here as well, be sure to read the plugin's documentation before updating. \ No newline at end of file diff --git a/lib/plugins/extension/lang/en/intro_search.txt b/lib/plugins/extension/lang/en/intro_search.txt index 003c99c61..244cd6812 100644 --- a/lib/plugins/extension/lang/en/intro_search.txt +++ b/lib/plugins/extension/lang/en/intro_search.txt @@ -1 +1 @@ -Here you can search for available plugins and templates for DokuWiki. Be sure to read more about Plugin Security before installing FIXME add link \ No newline at end of file +This tab gives you access to all available 3rd party plugins and templates for DokuWiki. Please be aware that installing 3rd party code may pose a **security risk**, you may want to read about [[doku>security#plugin_security|plugin security]] first. \ No newline at end of file diff --git a/lib/plugins/extension/lang/en/intro_templates.txt b/lib/plugins/extension/lang/en/intro_templates.txt index 2b3af727b..d42180cc4 100644 --- a/lib/plugins/extension/lang/en/intro_templates.txt +++ b/lib/plugins/extension/lang/en/intro_templates.txt @@ -1 +1 @@ -Here you can view, enable and disable installed templates. Note that only one template can be activated at a time. \ No newline at end of file +These are the templates currently installed in your DokuWiki. Note that only one template can be activated at a time. diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index fc5613044..8c85bec46 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -38,6 +38,26 @@ } } +#extension__manager { + /* tab layout - most of it is in the main template */ + ul.tabs li.active a { + background-color: @ini_background_alt; + border-bottom: solid 1px @ini_background_alt; + z-index: 2; + } + .panelHeader { + background-color: @ini_background_alt; + margin: 0 0 10px 0; + padding: 10px 10px 8px; + text-align: left; + overflow: hidden; + } +} + +/* ------- FIXME everything below needs to be checked for usage ---------- */ + + + /* * general layout */ -- cgit v1.2.3 From 32fdfac2cd446733436dc1b344d7f73b78655cb1 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 10 Aug 2013 11:11:14 +0200 Subject: changed exception handling, redirect after post actions --- lib/plugins/extension/admin.php | 98 +++++++++++++++++----------------- lib/plugins/extension/helper/gui.php | 5 +- lib/plugins/extension/lang/en/lang.php | 2 + 3 files changed, 53 insertions(+), 52 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/admin.php b/lib/plugins/extension/admin.php index 62d94e899..99c74848b 100644 --- a/lib/plugins/extension/admin.php +++ b/lib/plugins/extension/admin.php @@ -57,73 +57,71 @@ class admin_plugin_extension extends DokuWiki_Admin_Plugin { /* @var helper_plugin_extension_extension $extension */ $extension = $this->loadHelper('extension_extension'); - if($INPUT->post->has('fn') && checkSecurityToken()) { - $actions = $INPUT->post->arr('fn'); - foreach($actions as $action => $extensions) { - foreach($extensions as $extname => $label) { - switch($action) { - case 'install': - case 'reinstall': - case 'update': - try { + try { + if($INPUT->post->has('fn') && checkSecurityToken()) { + $actions = $INPUT->post->arr('fn'); + foreach($actions as $action => $extensions) { + foreach($extensions as $extname => $label) { + switch($action) { + case 'install': + case 'reinstall': + case 'update': $extension->setExtension($extname); $installed = $extension->installOrUpdate(); foreach($installed as $ext => $info) { msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); } - } catch(Exception $e) { - msg($e->getMessage(), -1); - } - break; - case 'uninstall': - $extension->setExtension($extname); - $status = $extension->uninstall(); - if($status !== true) { - msg($status, -1); - } else { - msg(sprintf($this->getLang('msg_delete_success'), hsc($extension->getDisplayName())), 1); - } - break; - case 'enable'; - $extension->setExtension($extname); - $status = $extension->enable(); - if($status !== true) { - msg($status, -1); - } else { - msg(sprintf($this->getLang('msg_enabled'), hsc($extension->getDisplayName())), 1); - } - break; - case 'disable'; - $extension->setExtension($extname); - $status = $extension->disable(); - if($status !== true) { - msg($status, -1); - } else { - msg(sprintf($this->getLang('msg_disabled'), hsc($extension->getDisplayName())), 1); - } - break; + break; + case 'uninstall': + $extension->setExtension($extname); + $status = $extension->uninstall(); + if($status !== true) { + msg($status, -1); + } else { + msg(sprintf($this->getLang('msg_delete_success'), hsc($extension->getDisplayName())), 1); + } + break; + case 'enable'; + $extension->setExtension($extname); + $status = $extension->enable(); + if($status !== true) { + msg($status, -1); + } else { + msg(sprintf($this->getLang('msg_enabled'), hsc($extension->getDisplayName())), 1); + } + break; + case 'disable'; + $extension->setExtension($extname); + $status = $extension->disable(); + if($status !== true) { + msg($status, -1); + } else { + msg(sprintf($this->getLang('msg_disabled'), hsc($extension->getDisplayName())), 1); + } + break; + } } } - } - } elseif($INPUT->post->str('installurl') && checkSecurityToken()) { - try { + send_redirect($this->gui->tabURL('', array(), '&', true)); + } elseif($INPUT->post->str('installurl') && checkSecurityToken()) { $installed = $extension->installFromURL($INPUT->post->str('installurl')); foreach($installed as $ext => $info) { msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); } - } catch(Exception $e) { - msg($e->getMessage(), -1); - } - } elseif(isset($_FILES['installfile']) && checkSecurityToken()) { - try { + send_redirect($this->gui->tabURL('', array(), '&', true)); + } elseif(isset($_FILES['installfile']) && checkSecurityToken()) { $installed = $extension->installFromUpload('installfile'); foreach($installed as $ext => $info) { msg(sprintf($this->getLang('msg_'.$info['type'].'_'.$info['action'].'_success'), $info['base']), 1); } - } catch(Exception $e) { - msg($e->getMessage(), -1); + send_redirect($this->gui->tabURL('', array(), '&', true)); } + + } catch(Exception $e) { + msg($e->getMessage(), -1); + send_redirect($this->gui->tabURL('', array(), '&', true)); } + } /** diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 7ad238af4..2c2a19bf8 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -168,9 +168,10 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { * @param string $tab tab to load, empty for current tab * @param array $params associative array of parameter to set * @param string $sep seperator to build the URL + * @param bool $absolute create absolute URLs? * @return string */ - public function tabURL($tab = '', $params = array(), $sep = '&') { + public function tabURL($tab = '', $params = array(), $sep = '&', $absolute=false) { global $ID; global $INPUT; @@ -181,7 +182,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { 'tab' => $tab, 'q' => $INPUT->str('q') ); - return wl($ID, array_merge($defaults, $params), false, $sep); + return wl($ID, array_merge($defaults, $params), $absolute, $sep); } } diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 0c4582124..8aaa0d8d2 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -74,6 +74,8 @@ $lang['msg_disabled'] = 'Plugin %s disabled'; $lang['msg_notdisabled'] = 'Plugin %s could not be disabled, check file permissions'; +$lang['msg_delete_success'] = 'Extension uninstalled'; + $lang['msg_template_install_success'] = 'Template %s installed successfully'; $lang['msg_template_update_success'] = 'Template %s updated successfully'; $lang['msg_plugin_install_success'] = 'Plugin %s installed successfully'; -- cgit v1.2.3 From 8d295da079a559bf0f254f0db383e0b3188f9985 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 10 Aug 2013 11:46:09 +0200 Subject: language cleanup removed all unused strings --- lib/plugins/extension/helper/extension.php | 2 +- lib/plugins/extension/lang/en/lang.php | 195 ++++++++++------------------- lib/plugins/extension/style.less | 6 +- 3 files changed, 70 insertions(+), 133 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 550fc33fb..d912a44c0 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -797,7 +797,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { // check the url $matches = array(); if(!preg_match('/[^\/]*$/', $url, $matches) || !$matches[0]) { - throw new Exception($this->getLang('baddownloadurl')); + throw new Exception($this->getLang('error_badurl')); } $file = $matches[0]; diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 8aaa0d8d2..db1449ae0 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -6,135 +6,68 @@ * @author Christopher Smith */ -// menu entry for admin plugins -$lang['menu'] = 'Extension Manager'; - -$lang['tab_plugins'] = 'Installed Plugins'; -$lang['tab_templates'] = 'Installed Templates'; -$lang['tab_search'] = 'Search and Install'; -$lang['tab_install'] = 'Manual Install'; - -// custom language strings for the plugin -$lang['notimplemented'] = 'This feature hasn\'t been implemented yet'; -$lang['alreadyenabled'] = 'This extension has already been enabled'; -$lang['alreadydisabled'] = 'This extension has already been disabled'; -$lang['pluginlistsaveerror'] = 'There was an error saving the plugin list'; -$lang['unknownauthor'] = 'Unknown author'; -$lang['unknownversion'] = 'Unknown version'; - -// extension list -$lang['btn_info'] = 'Show more info'; -$lang['btn_update'] = 'Update'; -$lang['btn_uninstall'] = 'Uninstall'; -$lang['btn_enable'] = 'Enable'; -$lang['btn_disable'] = 'Disable'; -//$lang['btn_disable_all'] = 'Disable all'; -//$lang['btn_settings'] = 'Settings'; -$lang['btn_install'] = 'Install'; -$lang['btn_reinstall'] = 'Re-install'; -//$lang['btn_disdown'] = 'Download as Disabled'; -//$lang['btn_dependown'] = 'Download with dependencies'; - -$lang['extensionby'] = '%s by %s'; -$lang['popularity'] = 'Popularity: %s'; -$lang['homepage_link'] = 'Docs'; -$lang['bugs_features'] = 'Bugs'; -$lang['author_hint'] = 'Search extensions by this author'; -$lang['tag_hint'] = 'Search extensions with this tag'; -$lang['installed'] = 'Installed:'; -$lang['lastupdate'] = 'Last updated:'; -$lang['downloadurl'] = 'Download URL:'; -$lang['repository'] = 'Repository:'; -$lang['unknown'] = 'unknown'; -$lang['installed_version'] = 'Installed version:'; -$lang['install_date'] = 'Your last update:'; -$lang['available_version'] = 'Version:'; -$lang['compatible'] = 'Compatible with:'; -$lang['depends'] = 'Depends on:'; -$lang['similar'] = 'Similar to:'; -$lang['conflicts'] = 'Conflicts with:'; -$lang['donate'] = 'Donate'; -$lang['bundled'] = 'bundled'; -$lang['manual_install'] = 'manual install'; - -$lang['repo_error'] = 'The DokuWiki extension repository can not be reached currently. Online Features are not available.'; -$lang['repo_retry'] = 'Retry'; - -$lang['msg_tpl_uninstalled'] = 'Template %s uninstalled'; -$lang['msg_tpl_uninstalled'] = 'Template %s could not be uninstalled'; -$lang['msg_uninstalled'] = 'Plugin %s uninstalled'; -$lang['msg_uninstalled'] = 'Plugin %s could not be uninstalled'; - -$lang['msg_tpl_enabled'] = 'Template %s enabled'; -$lang['msg_tpl_notenabled'] = 'Template %s could not be enabled, check file permissions'; -$lang['msg_enabled'] = 'Plugin %s enabled'; -$lang['msg_notenabled'] = 'Plugin %s could not be enabled, check file permissions'; - -$lang['msg_disabled'] = 'Plugin %s disabled'; -$lang['msg_notdisabled'] = 'Plugin %s could not be disabled, check file permissions'; - - -$lang['msg_delete_success'] = 'Extension uninstalled'; - +$lang['menu'] = 'Extension Manager'; + +$lang['tab_plugins'] = 'Installed Plugins'; +$lang['tab_templates'] = 'Installed Templates'; +$lang['tab_search'] = 'Search and Install'; +$lang['tab_install'] = 'Manual Install'; + +$lang['notimplemented'] = 'This feature hasn\'t been implemented yet'; +$lang['notinstalled'] = 'This extension is not installed'; +$lang['alreadyenabled'] = 'This extension has already been enabled'; +$lang['alreadydisabled'] = 'This extension has already been disabled'; +$lang['pluginlistsaveerror'] = 'There was an error saving the plugin list'; +$lang['unknownauthor'] = 'Unknown author'; +$lang['unknownversion'] = 'Unknown version'; + +$lang['btn_info'] = 'Show more info'; +$lang['btn_update'] = 'Update'; +$lang['btn_uninstall'] = 'Uninstall'; +$lang['btn_enable'] = 'Enable'; +$lang['btn_disable'] = 'Disable'; +$lang['btn_install'] = 'Install'; +$lang['btn_reinstall'] = 'Re-install'; + +$lang['extensionby'] = '%s by %s'; +$lang['popularity'] = 'Popularity: %s'; +$lang['homepage_link'] = 'Docs'; +$lang['bugs_features'] = 'Bugs'; +$lang['author_hint'] = 'Search extensions by this author'; +$lang['installed'] = 'Installed:'; +$lang['downloadurl'] = 'Download URL:'; +$lang['repository'] = 'Repository:'; +$lang['unknown'] = 'unknown'; +$lang['installed_version'] = 'Installed version:'; +$lang['install_date'] = 'Your last update:'; +$lang['available_version'] = 'Version:'; +$lang['compatible'] = 'Compatible with:'; +$lang['depends'] = 'Depends on:'; +$lang['similar'] = 'Similar to:'; +$lang['conflicts'] = 'Conflicts with:'; +$lang['donate'] = 'Donate'; +$lang['repo_retry'] = 'Retry'; + +$lang['msg_enabled'] = 'Plugin %s enabled'; +$lang['msg_disabled'] = 'Plugin %s disabled'; +$lang['msg_delete_success'] = 'Extension uninstalled'; $lang['msg_template_install_success'] = 'Template %s installed successfully'; -$lang['msg_template_update_success'] = 'Template %s updated successfully'; -$lang['msg_plugin_install_success'] = 'Plugin %s installed successfully'; -$lang['msg_plugin_update_success'] = 'Plugin %s updated successfully'; - -$lang['msg_upload_failed'] = 'Uploading the file failed'; - - -$lang['msg_url_failed'] = 'URL [%s] could not be downloaded.
    %s'; -$lang['msg_download_failed'] = 'Plugin %s could not be downloaded.
    %s'; -$lang['msg_download_success'] = 'Plugin %s installed successfully'; -$lang['msg_tpl_download_failed'] = 'Template %s could not be downloaded.
    %s'; - -$lang['msg_download_pkg_success'] = '%s extension package successfully installed (%s)'; -$lang['msg_tpl_download_pkg_success'] = '%s extension package successfully installed (%s)'; - -$lang['msg_update_success'] = 'Plugin %s successfully updated'; -$lang['msg_update_failed'] = 'Update of plugin %s failed.
    %s'; -$lang['msg_tpl_update_success'] = 'Template %s successfully updated'; -$lang['msg_tpl_update_failed'] = 'Update of template %s failed.
    %s'; -$lang['msg_update_pkg_success'] = '%s extension package successfully updated (%s)'; -$lang['msg_tpl_update_pkg_success'] = '%s extension package successfully updated (%s)'; - -$lang['msg_reinstall_success'] = 'Plugin %s re-installed successfully'; -$lang['msg_reinstall_failed'] = 'Failed to re-install plugin %s.
    %s'; -$lang['msg_tpl_reinstall_success'] = 'Template %s re-installed successfully'; -$lang['msg_tpl_reinstall_failed'] = 'Failed to re-install template %s.
    %s'; -$lang['msg_reinstall_pkg_success'] = '%s extension package successfully reinstalled (%s)'; -$lang['msg_tpl_reinstall_pkg_success'] = '%s extension package successfully reinstalled (%s)'; - -// info titles -$lang['plugin'] = 'Plugin'; -$lang['provides'] = 'Provides:'; -$lang['noinfo'] = 'This plugin returned no information, it may be invalid.'; -$lang['name'] = 'Name:'; -$lang['date'] = 'Date:'; -$lang['type'] = 'Type:'; -$lang['desc'] = 'Description:'; -$lang['author'] = 'Author:'; -$lang['www'] = 'Web:'; - -// error messages -$lang['needed_by'] = 'Needed by:'; -$lang['not_writable'] = 'DokuWiki can not write to the folder'; -$lang['missing_dependency'] = 'Missing or disabled dependency: %s'; -$lang['security_issue'] = 'Security Issue: %s'; -$lang['security_warning'] = 'Security Warning: %s'; -$lang['update_available'] = 'Update: New version %s is available.'; -$lang['wrong_folder'] = 'Plugin installed incorrectly: Rename plugin directory "%s" to "%s".'; -$lang['url_change'] = 'URL changed: Download URL has changed since last download. Check if the new URL is valid before updating the extension.
    New: %s
    Old: %s'; -$lang['gitmanaged'] = 'Extension installed with git'; -$lang['bundled_source'] = 'Bundled with DokuWiki source'; -$lang['no_url'] = 'No download URL'; -$lang['no_manager'] = 'Could not find manager.dat file'; - -$lang['error_badurl'] = 'URL ends with slash - unable to determine file name from the url'; -$lang['error_dircreate'] = 'Unable to create temporary folder to receive download'; -$lang['error_download'] = 'Unable to download the file: %s'; -$lang['error_decompress'] = 'Unable to decompress the downloaded file. This maybe as a result of a bad download, in which case you should try again; or the compression format may be unknown, in which case you will need to download and install manually.'; -$lang['error_findfolder'] = 'Unable to identify extension directory, you need to download and install manually'; -$lang['error_copy'] = 'There was a file copy error while attempting to install files for directory %s: the disk could be full or file access permissions may be incorrect. This may have resulted in a partially installed plugin and leave your wiki installation unstable'; -//Setup VIM: ex: et ts=4 : +$lang['msg_template_update_success'] = 'Template %s updated successfully'; +$lang['msg_plugin_install_success'] = 'Plugin %s installed successfully'; +$lang['msg_plugin_update_success'] = 'Plugin %s updated successfully'; +$lang['msg_upload_failed'] = 'Uploading the file failed'; + +$lang['provides'] = 'Provides:'; +$lang['missing_dependency'] = 'Missing or disabled dependency: %s'; +$lang['security_issue'] = 'Security Issue: %s'; +$lang['security_warning'] = 'Security Warning: %s'; +$lang['update_available'] = 'Update: New version %s is available.'; +$lang['wrong_folder'] = 'Plugin installed incorrectly: Rename plugin directory "%s" to "%s".'; +$lang['url_change'] = 'URL changed: Download URL has changed since last download. Check if the new URL is valid before updating the extension.
    New: %s
    Old: %s'; + +$lang['error_badurl'] = 'URL ends with slash - unable to determine file name from the url'; +$lang['error_dircreate'] = 'Unable to create temporary folder to receive download'; +$lang['error_download'] = 'Unable to download the file: %s'; +$lang['error_decompress'] = 'Unable to decompress the downloaded file. This maybe as a result of a bad download, in which case you should try again; or the compression format may be unknown, in which case you will need to download and install manually.'; +$lang['error_findfolder'] = 'Unable to identify extension directory, you need to download and install manually'; +$lang['error_copy'] = 'There was a file copy error while attempting to install files for directory %s: the disk could be full or file access permissions may be incorrect. This may have resulted in a partially installed plugin and leave your wiki installation unstable'; diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index 8c85bec46..4a036f067 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -191,6 +191,8 @@ #extension__manager div.screenshot img { width: 120px; height: 70px; + border-radius: 12px; + box-shadow: 2px 2px 2px #ccc; } #extension__manager .legend div.screenshot { @@ -198,6 +200,7 @@ margin-left: -132px; max-width: 120px; float: left; + position: relative; } [dir=rtl] #extension__manager .legend div.screenshot { margin-left: 0; @@ -209,7 +212,8 @@ min-height: 24px; min-width: 24px; position: absolute; - left: 0; + left: 0px; + top: 0px; } [dir=rtl] #extension__manager .legend div.screenshot span { left: auto; -- cgit v1.2.3 From f910b299e4bbc59cfbe4e68af5d34ea2e5815574 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 10 Aug 2013 14:29:40 +0200 Subject: updated styles RTL styles need to be readded --- lib/plugins/extension/helper/gui.php | 16 +- lib/plugins/extension/images/icons.xcf | Bin 43016 -> 67195 bytes lib/plugins/extension/images/plugin.png | Bin 6259 -> 6824 bytes lib/plugins/extension/images/template.png | Bin 6802 -> 7547 bytes lib/plugins/extension/lang/en/lang.php | 3 + lib/plugins/extension/style.less | 477 ++++++++++++------------------ 6 files changed, 199 insertions(+), 297 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 2c2a19bf8..139a1a16a 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -90,9 +90,9 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { echo $this->locale_xhtml('intro_search'); echo '
    '; - $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'))); - $form->addElement(form_makeTextField('q', $INPUT->str('q'), 'Search')); - $form->addElement(form_makeButton('submit', '', 'Search')); + $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'), 'class' => 'search')); + $form->addElement(form_makeTextField('q', $INPUT->str('q'), $this->getLang('search_for'))); + $form->addElement(form_makeButton('submit', '', $this->getLang('search'))); $form->printForm(); if(!$INPUT->bool('q')) return; @@ -123,7 +123,7 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { echo $this->locale_xhtml('intro_install'); echo ''; - $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'), 'enctype' => 'multipart/form-data')); + $form = new Doku_Form(array('action' => $this->tabURL('', array(), '&'), 'enctype' => 'multipart/form-data', 'class' => 'install')); $form->addElement(form_makeTextField('installurl', '', 'Install from URL:', '', 'block')); $form->addElement(form_makeFileField('installfile', 'Upload Extension:', '', 'block')); $form->addElement(form_makeButton('submit', '', 'Install')); @@ -165,13 +165,13 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { /** * Create an URL inside the extension manager * - * @param string $tab tab to load, empty for current tab - * @param array $params associative array of parameter to set - * @param string $sep seperator to build the URL + * @param string $tab tab to load, empty for current tab + * @param array $params associative array of parameter to set + * @param string $sep seperator to build the URL * @param bool $absolute create absolute URLs? * @return string */ - public function tabURL($tab = '', $params = array(), $sep = '&', $absolute=false) { + public function tabURL($tab = '', $params = array(), $sep = '&', $absolute = false) { global $ID; global $INPUT; diff --git a/lib/plugins/extension/images/icons.xcf b/lib/plugins/extension/images/icons.xcf index a99747d81..ab69b3099 100644 Binary files a/lib/plugins/extension/images/icons.xcf and b/lib/plugins/extension/images/icons.xcf differ diff --git a/lib/plugins/extension/images/plugin.png b/lib/plugins/extension/images/plugin.png index b9133681f..e4a2d3be6 100644 Binary files a/lib/plugins/extension/images/plugin.png and b/lib/plugins/extension/images/plugin.png differ diff --git a/lib/plugins/extension/images/template.png b/lib/plugins/extension/images/template.png index 383c4d0a3..ee74bc1d5 100644 Binary files a/lib/plugins/extension/images/template.png and b/lib/plugins/extension/images/template.png differ diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index db1449ae0..11c5caa2b 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -29,6 +29,9 @@ $lang['btn_disable'] = 'Disable'; $lang['btn_install'] = 'Install'; $lang['btn_reinstall'] = 'Re-install'; +$lang['search_for'] = 'Search Extension:'; +$lang['search'] = 'Search'; + $lang['extensionby'] = '%s by %s'; $lang['popularity'] = 'Popularity: %s'; $lang['homepage_link'] = 'Docs'; diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index 4a036f067..e1a7a1d7b 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -38,8 +38,11 @@ } } +/** + * general styles + */ #extension__manager { - /* tab layout - most of it is in the main template */ + // tab layout - most of it is in the main template ul.tabs li.active a { background-color: @ini_background_alt; border-bottom: solid 1px @ini_background_alt; @@ -52,336 +55,232 @@ text-align: left; overflow: hidden; } -} - -/* ------- FIXME everything below needs to be checked for usage ---------- */ - - - -/* - * general layout - */ -#extension__manager h2 { - margin-left: 0; -} -#extension__manager .panelHeader div.error { - margin-top: 0; - float: left; -} -[dir=rtl] #extension__manager .panelHeader div.error { - float: right; + // message spacing + div.msg { + margin: 0.4em 0 0 0; + } } /* - * search & url download forms + * extensions table */ -#extension__manager form.search, -#extension__manager form.btn_reload { - float: right; -} -[dir=rtl] #extension__manager form.search, -[dir=rtl] #extension__manager form.btn_reload { - float: left; -} - -#extension__manager div.search form.search { - float: none; -} - -#extension__manager .tagcloud { - width: 55%; - float: left; - margin: 0 0.5em 1em 0; -} -[dir=rtl] #extension__manager .tagcloud { - float: right; - margin: 0 0 1em .5em; -} - -#extension__manager .tagcloud a.taglink { - background-color: inherit; -} - -#extension__manager div.search { - width: 44%; - float: left; -} -[dir=rtl] #extension__manager div.search { - float: right; -} - -#extension__manager fieldset { - margin-top: 0.5em; - width: auto; -} - -#extension__manager fieldset p { - margin: 0.5em; - text-align: justify; - font-size: 85%; -} - -/* tag cloud */ -#extension__manager a.cl0 { font-size: 0.7em; } -#extension__manager a.cl1 { font-size: 0.9em; } -#extension__manager a.cl2 { font-size: 1em; } -#extension__manager a.cl3 { font-size: 1.3em; } -#extension__manager a.cl4 { font-size: 1.6em; } -#extension__manager a.cl5 { font-size: 1.9em; } +#extension__list { + ul.extensionList { + margin-left: 0; + margin-right: 0; + padding: 0; + list-style: none; + } + ul.extensionList li { + margin: 0 0 .5em; + padding: 0 0 .5em; + color: @ini_text; + border-bottom: 1px solid @ini_border; + overflow: hidden; + } -#extension__manager .extensionList input.button { - margin: 0 .3em .3em 0; -} -[dir=rtl] #extension__manager .extensionList input.button { - margin: 0 0 .3em .3em; + input.button { + margin: 0 .3em .3em 0; + } } -/* - * extensions table +/** + * extension table left column */ -#extension__manager .extensionList { - margin-left: 0; - margin-right: 0; - padding: 0; - list-style: none; -} - -#extension__manager .extensionList li { - margin: 0 0 .5em; - padding: 0 0 .5em; - color: @ini_text; - border-bottom: 1px solid @ini_border; - overflow: hidden; -} - -#extension__manager .legend { +#extension__list .legend { position: relative; width: 75%; float: left; -} -[dir=rtl] #extension__manager .legend { - float: right; -} -#extension__manager .legend > div { - padding: 0 .5em 0 132px; - border-right: 1px solid @ini_background_alt; - overflow: hidden; -} -[dir=rtl] #extension__manager .legend > div { - padding: 0 132px 0 .5em; - border-left: 1px solid @ini_background_alt; - border-right-width: 0; -} - -#extension__manager .enabled div.screenshot span { - background: transparent url(images/enabled.png) no-repeat 2px 2px; -} - -#extension__manager .disabled div.screenshot span { - background: transparent url(images/disabled.png) no-repeat 2px 2px; -} - -#extension__manager .disabled .legend { - opacity: 0.7; -} - -#extension__manager div.screenshot img { - width: 120px; - height: 70px; - border-radius: 12px; - box-shadow: 2px 2px 2px #ccc; -} - -#extension__manager .legend div.screenshot { - margin-top: 4px; - margin-left: -132px; - max-width: 120px; - float: left; - position: relative; -} -[dir=rtl] #extension__manager .legend div.screenshot { - margin-left: 0; - margin-right: -132px; - float: right; -} + // padding + > div { + padding: 0 .5em 0 132px; + border-right: 1px solid @ini_background_alt; + overflow: hidden; + } -#extension__manager .legend div.screenshot span { - min-height: 24px; - min-width: 24px; - position: absolute; - left: 0px; - top: 0px; -} -[dir=rtl] #extension__manager .legend div.screenshot span { - left: auto; - right: 0; -} + // screenshot + div.screenshot { + margin-top: 4px; + margin-left: -132px; + max-width: 120px; + float: left; + position: relative; + + img { + width: 120px; + height: 70px; + border-radius: 5px; + box-shadow: 2px 2px 2px #666; + } + + span { + min-height: 24px; + min-width: 24px; + position: absolute; + left: 0px; + top: 0px; + } + } -#extension__manager .legend h2 { - width: 100%; - float: right; - margin: 0.2em 0 0.5em; - font-size: 100%; - font-weight: normal; - border: none; -} -[dir=rtl] #extension__manager .legend h2 { - float: left; -} + // plugin headline + h2 { + width: 100%; + float: right; + margin: 0.2em 0 0.5em; + font-size: 100%; + font-weight: normal; + border: none; + + strong { + font-size: 120%; + font-weight: bold; + vertical-align: baseline; + } + } -#extension__manager .legend h2 strong { - font-size: 120%; - font-weight: bold; - vertical-align: baseline; -} + // description + p { + margin: 0 0 0.6em 0; + } -#extension__manager .legend p { - margin: 0 0 0.6em 0; -} + // popularity bar + div.popularity { + background-color: @ini_background; + border: 1px solid silver; + height: .4em; + margin: 0 auto; + padding: 1px; + width: 5.5em; + position: absolute; + right: .5em; + top: 0.2em; + + div { + background-color: @ini_border; + height: 100%; + + span { + display: none;// @todo: hide accessibly + } + } + } -#extension__manager .legend span.linkbar { - font-size: 85%; -} + // Docs, Bugs, Tags + span.linkbar { + font-size: 85%; -#extension__manager .legend span.linkbar span.tags { - padding-left: 18px; - background: transparent url(images/tag.png) no-repeat 0 0; -} + span.tags { + padding-left: 18px; + background: transparent url(images/tag.png) no-repeat 0 0; + } + } + // more info button + a.info { + background: transparent url(images/up.png) no-repeat 0 0; + border-width: 0; + height: 13px; + width: 13px; + text-indent: -9999px; + float: right; + margin: .5em 0 0; + overflow: hidden; -#extension__manager .legend a.info { - background: transparent url(images/up.png) no-repeat 0 0; - border-width: 0; - height: 13px; - width: 13px; - text-indent: -99999px; - float: right; - margin: .5em 0 0; - overflow: hidden; -} -[dir=rtl] #extension__manager .legend a.info { - float: left; - margin: .5em 0 0; -} + &.close { + background: transparent url(images/down.png) no-repeat 0 0; + } + } -#extension__manager .legend a.info.close { - background: transparent url(images/down.png) no-repeat 0 0; + // detailed info box + dl.details { + margin: 0.4em 0 0 0; + font-size: 85%; + border-top: 1px solid @ini_background_alt; + clear: both; + + dt { + clear: left; + float: left; + width: 25%; + margin: 0; + text-align: right; + font-weight: normal; + padding: 0.2em 5px 0 0; + } + + dd { + margin-left: 25%; + font-weight: bold; + padding: 0.2em 0 0 5px; + + a { + font-weight: normal; + } + } + } } -#extension__manager .legend div.popularity { - background-color: @ini_background; - border: 1px solid silver; - height: .4em; - margin: 0 auto; - padding: 1px; - width: 5.5em; - position: absolute; - right: .5em; - top: 0.2em; -} -[dir=rtl] #extension__manager .legend div.popularity { - right: auto; - left: .5em; -} +/* + * Enabled/Disabled overrides + */ +#extension__list { + .enabled div.screenshot span { + background: transparent url(images/enabled.png) no-repeat 2px 2px; + } -#extension__manager .legend div.popularity div { - background-color: @ini_border; - height: 100%; -} + .disabled div.screenshot span { + background: transparent url(images/disabled.png) no-repeat 2px 2px; + } -#extension__manager .legend div.popularity div span { - display: none;/* @todo: hide accessibly */ + .disabled .legend { + opacity: 0.7; + } } +/** + * extension table right column + */ #extension__manager .actions { padding: 0; font-size: 95%; width: 25%; float: right; text-align: right; -} -[dir=rtl] #extension__manager .actions { - float: left; - text-align: left; -} -#extension__manager .actions .version { - display: block; -} + .version { + display: block; + } -#extension__manager .actions p { - margin: 0.2em 0; - text-align: center; + p { + margin: 0.2em 0; + text-align: center; + } } -/* - * extensions table, detailed info box +/** + * Search form */ -#extension__manager dl.details { - margin: 0.4em 0 0 0; - font-size: 85%; - border-top: 1px solid @ini_background_alt; - clear: both; -} - -#extension__manager dl.details dt { - clear: left; - float: left; - width: 25%; - margin: 0; - text-align: right; - font-weight: normal; - padding: 0.2em 5px 0 0; -} -[dir=rtl] #extension__manager dl.details dt { - clear: right; - float: right; - text-align: left; - padding: 0.2em 0 0 5px; -} - -#extension__manager dl.details dd { - margin-left: 25%; - font-weight: bold; - padding: 0.2em 0 0 5px; -} -[dir=rtl] #extension__manager dl.details dd { - margin-left: 0; - margin-right: 25%; - padding: 0.2em 5px 0 0 ; -} - -#extension__manager dl.details dd a { - font-weight: normal; -} +#extension__manager form.search { + display: block; + margin-bottom: 2em; -#extension__manager #info__popup { - z-index: 20; - overflow: hidden; - opacity: 0.9; - border: 1px solid @ini_border; - background-color: @ini_border; /*background_other__;*/ - text-align: left; - padding: 0.2em; -} -[dir=rtl] #extension__manager #info__popup { - text-align: right; -} + span { + font-weight: bold; + } -#extension__manager div.msg { - margin: 0.4em 0 0 0; + input.edit { + width: 25em; + } } -#extension__manager ul.tabs div.msg { - display: inline; - margin-left: 0.4em; -} -[dir=rtl] #extension__manager ul.tabs div.msg { - margin-left: 0; - margin-right: 0.4em; +/** + * Install form + */ +#extension__manager form.install { + text-align: center; + display: block; + width: 60%; } - -/* end admin plugin styles */ -- cgit v1.2.3 From 347e1146ca6a08dc90247a3f7da31cbc3a409aa0 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 10 Aug 2013 14:43:12 +0200 Subject: fixed screenshots --- lib/plugins/extension/helper/list.php | 4 ++-- lib/plugins/extension/lang/en/intro_install.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 6b1d41f78..16ef71569 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -181,8 +181,8 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { */ function make_screenshot(helper_plugin_extension_extension $extension) { if($extension->getScreenshotURL()) { - $img = ''. - ''.hsc($extension->getDisplayName()).''. + $img = ''. + ''.hsc($extension->getDisplayName()).''. ''; } elseif($extension->isTemplate()) { $img = 'template'; diff --git a/lib/plugins/extension/lang/en/intro_install.txt b/lib/plugins/extension/lang/en/intro_install.txt index 0556c8048..a5d5ab008 100644 --- a/lib/plugins/extension/lang/en/intro_install.txt +++ b/lib/plugins/extension/lang/en/intro_install.txt @@ -1 +1 @@ -Here you can manually install plugins and templates by either uploading them or providing a direct download URL. \ No newline at end of file +Here you can manually install plugins and templates by either uploading them or providing a direct download URL. -- cgit v1.2.3 From e445eeb3b675b350b4cebeeea610d4f7cd2e8f19 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 11 Aug 2013 11:19:34 +0200 Subject: fixed button logic --- lib/plugins/extension/helper/extension.php | 19 ++++++++++--------- lib/plugins/extension/helper/list.php | 26 ++++++++++++++++++++------ lib/plugins/extension/images/warning.png | Bin 0 -> 613 bytes lib/plugins/extension/lang/en/lang.php | 4 ++++ lib/plugins/extension/style.less | 9 +++++++++ 5 files changed, 43 insertions(+), 15 deletions(-) create mode 100644 lib/plugins/extension/images/warning.png (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index d912a44c0..6136c3c9a 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -107,7 +107,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool if the extension is protected */ public function isProtected() { - return in_array($this->base, array('acl', 'config', 'info', 'plugin', 'revert', 'usermanager')); + return in_array($this->id, array('acl', 'config', 'info', 'plugin', 'revert', 'usermanager', 'template:dokuwiki')); } /** @@ -513,20 +513,21 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * If the extension can probably be installed/updated or uninstalled * - * @return bool|string True or one of "nourl", "noparentperms" (template/plugin install path not writable), "noperms" (extension itself not writable) + * @return bool|string True or error string */ public function canModify() { - if ($this->isInstalled()) { - if (!is_writable($this->getInstallDir())) { + if($this->isInstalled()) { + if(!is_writable($this->getInstallDir())) { return 'noperms'; } } - $parent_path = ($this->isTemplate() ? DOKU_TPLLIB : DOKU_PLUGIN); - if (!is_writable($parent_path)) { - return 'noparentperms'; - } - if (!$this->getDownloadURL()) return 'nourl'; + if($this->isTemplate() && !is_writable(DOKU_TPLLIB)) { + return 'notplperms'; + + } elseif(!is_writable(DOKU_PLUGIN)) { + return 'nopluginperms'; + } return true; } diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 16ef71569..7ecd5b267 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -444,11 +444,13 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { */ function make_actions(helper_plugin_extension_extension $extension) { $return = ''; - if (!$extension->isInstalled() && $extension->canModify() === true) { - $return .= $this->make_action('install', $extension); - } elseif ($extension->canModify() === true) { - if (!$extension->isBundled()) { - $return .= $this->make_action('uninstall', $extension); + $errors = ''; + + if ($extension->isInstalled()) { + if (($canmod = $extension->canModify()) === true) { + if (!$extension->isProtected()) { + $return .= $this->make_action('uninstall', $extension); + } if ($extension->getDownloadURL()) { if ($extension->updateAvailable()) { $return .= $this->make_action('update', $extension); @@ -456,7 +458,10 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $return .= $this->make_action('reinstall', $extension); } } + }else{ + $errors .= '

    '.$this->getLang($canmod).'

    '; } + if (!$extension->isProtected()) { if ($extension->isEnabled()) { if(!$extension->isTemplate()){ // templates can't be disabled, only another can be enabled @@ -466,6 +471,15 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $return .= $this->make_action('enable', $extension); } } + + }else{ + if (($canmod = $extension->canModify()) === true) { + if ($extension->getDownloadURL()) { + $return .= $this->make_action('install', $extension); + } + }else{ + $errors .= '
    '.$this->getLang($canmod).'
    '; + } } if (!$extension->isInstalled()) { @@ -473,7 +487,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $return .= ($extension->getLastUpdate() ? hsc($extension->getLastUpdate()) : $this->getLang('unknown')).''; } - return $return; + return $return.' '.$errors; } /** diff --git a/lib/plugins/extension/images/warning.png b/lib/plugins/extension/images/warning.png new file mode 100644 index 000000000..c5e482f84 Binary files /dev/null and b/lib/plugins/extension/images/warning.png differ diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 11c5caa2b..53ce597dd 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -74,3 +74,7 @@ $lang['error_download'] = 'Unable to download the file: %s'; $lang['error_decompress'] = 'Unable to decompress the downloaded file. This maybe as a result of a bad download, in which case you should try again; or the compression format may be unknown, in which case you will need to download and install manually.'; $lang['error_findfolder'] = 'Unable to identify extension directory, you need to download and install manually'; $lang['error_copy'] = 'There was a file copy error while attempting to install files for directory %s: the disk could be full or file access permissions may be incorrect. This may have resulted in a partially installed plugin and leave your wiki installation unstable'; + +$lang['noperms'] = 'Extension directory is not writable'; +$lang['notplperms'] = 'Template directory is not writable'; +$lang['nopluginperms'] = 'Plugin directory is not writable'; \ No newline at end of file diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index e1a7a1d7b..762968611 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -258,6 +258,15 @@ margin: 0.2em 0; text-align: center; } + + p.permerror { + margin-left: 0.4em; + text-align: left; + padding-left: 19px; + background: transparent url(images/warning.png) center left no-repeat; + line-height: 18px; + font-size: 12px; + } } /** -- cgit v1.2.3 From 7ca0915cf61dd8ff297bf1d3ebd6aafcab88a618 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 11 Aug 2013 11:52:47 +0200 Subject: fixed donation link --- lib/plugins/extension/helper/list.php | 18 ++++++++++++------ lib/plugins/extension/images/donate.png | Bin 1293 -> 724 bytes lib/plugins/extension/lang/en/lang.php | 3 ++- lib/plugins/extension/style.less | 7 ++++--- 4 files changed, 18 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index 7ecd5b267..ef589dedd 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -343,6 +343,14 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $default = $this->getLang('unknown'); $return = '
    '; + if ($extension->getDonationURL()) { + $return .= '
    '.$this->getLang('donate').'
    '; + $return .= '
    '; + $return .= ''; + $return .= '
    '; + } + + if (!$extension->isBundled()) { $return .= '
    '.$this->getLang('downloadurl').'
    '; $return .= '
    '; @@ -393,6 +401,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { foreach ($extension->getCompatibleVersions() as $date => $version) { $return .= $version['label'].' ('.$date.'), '; } + $return = rtrim($return, ', '); $return .= '
    '; } if($extension->getDependencies()) { @@ -415,9 +424,6 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $return .= $this->make_linklist($extension->getConflicts()); $return .= ''; } - if ($extension->getDonationURL()) { - $return .= ''; - } $return .= '
    '; return $return; } @@ -431,9 +437,9 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { function make_linklist($ext) { $return = ''; foreach ($ext as $link) { - $return .= ''.hsc($link).' '; + $return .= ''.hsc($link).', '; } - return $return; + return rtrim($return, ', '); } /** @@ -482,7 +488,7 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { } } - if (!$extension->isInstalled()) { + if (!$extension->isInstalled() && $extension->getDownloadURL()) { $return .= ' '.$this->getLang('available_version').' '; $return .= ($extension->getLastUpdate() ? hsc($extension->getLastUpdate()) : $this->getLang('unknown')).''; } diff --git a/lib/plugins/extension/images/donate.png b/lib/plugins/extension/images/donate.png index b26ceb66e..9e234da1c 100644 Binary files a/lib/plugins/extension/images/donate.png and b/lib/plugins/extension/images/donate.png differ diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 53ce597dd..684ff2bad 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -48,7 +48,8 @@ $lang['compatible'] = 'Compatible with:'; $lang['depends'] = 'Depends on:'; $lang['similar'] = 'Similar to:'; $lang['conflicts'] = 'Conflicts with:'; -$lang['donate'] = 'Donate'; +$lang['donate'] = 'Like this?'; +$lang['donate_action'] = 'Buy the author a coffee!'; $lang['repo_retry'] = 'Retry'; $lang['msg_enabled'] = 'Plugin %s enabled'; diff --git a/lib/plugins/extension/style.less b/lib/plugins/extension/style.less index 762968611..0d86f5419 100644 --- a/lib/plugins/extension/style.less +++ b/lib/plugins/extension/style.less @@ -209,15 +209,16 @@ text-align: right; font-weight: normal; padding: 0.2em 5px 0 0; + font-weight: bold; } dd { margin-left: 25%; - font-weight: bold; padding: 0.2em 0 0 5px; - a { - font-weight: normal; + a.donate { + padding-left: 18px; + background: transparent url(images/donate.png) left center no-repeat; } } } -- cgit v1.2.3 From 9597c3b83b2dbf2787bf9046c911f0cc17d29481 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 11 Aug 2013 12:05:09 +0200 Subject: just not handle enable/disable for templates for now --- lib/plugins/extension/helper/extension.php | 5 +++-- lib/plugins/extension/helper/list.php | 6 ++---- lib/plugins/extension/lang/en/intro_templates.txt | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 6136c3c9a..6ad8f5185 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -632,10 +632,11 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function enable() { if ($this->isTemplate()) return $this->getLang('notimplemented'); - /* @var Doku_Plugin_Controller $plugin_controller */ - global $plugin_controller; if (!$this->isInstalled()) return $this->getLang('notinstalled'); if ($this->isEnabled()) return $this->getLang('alreadyenabled'); + + /* @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; if ($plugin_controller->enable($this->base)) { $this->purgeCache(); return true; diff --git a/lib/plugins/extension/helper/list.php b/lib/plugins/extension/helper/list.php index ef589dedd..e33dbfa04 100644 --- a/lib/plugins/extension/helper/list.php +++ b/lib/plugins/extension/helper/list.php @@ -468,11 +468,9 @@ class helper_plugin_extension_list extends DokuWiki_Plugin { $errors .= '

    '.$this->getLang($canmod).'

    '; } - if (!$extension->isProtected()) { + if (!$extension->isProtected() && !$extension->isTemplate()) { // no enable/disable for templates if ($extension->isEnabled()) { - if(!$extension->isTemplate()){ // templates can't be disabled, only another can be enabled - $return .= $this->make_action('disable', $extension); - } + $return .= $this->make_action('disable', $extension); } else { $return .= $this->make_action('enable', $extension); } diff --git a/lib/plugins/extension/lang/en/intro_templates.txt b/lib/plugins/extension/lang/en/intro_templates.txt index d42180cc4..8bc04631d 100644 --- a/lib/plugins/extension/lang/en/intro_templates.txt +++ b/lib/plugins/extension/lang/en/intro_templates.txt @@ -1 +1 @@ -These are the templates currently installed in your DokuWiki. Note that only one template can be activated at a time. +These are the templates currently installed in your DokuWiki. You can select template to be used in the [[?do=admin&page=config|Configuration Manager]]. -- cgit v1.2.3 From 8ecc39810428baa07bb322c5f515f56bac533746 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 11 Aug 2013 12:14:17 +0200 Subject: confirm uninstalling of extensions --- lib/plugins/extension/lang/en/lang.php | 2 ++ lib/plugins/extension/script.js | 10 ++++++++++ 2 files changed, 12 insertions(+) (limited to 'lib') diff --git a/lib/plugins/extension/lang/en/lang.php b/lib/plugins/extension/lang/en/lang.php index 684ff2bad..3b2d2f38d 100644 --- a/lib/plugins/extension/lang/en/lang.php +++ b/lib/plugins/extension/lang/en/lang.php @@ -29,6 +29,8 @@ $lang['btn_disable'] = 'Disable'; $lang['btn_install'] = 'Install'; $lang['btn_reinstall'] = 'Re-install'; +$lang['js']['reallydel'] = 'Really uninstall this extension?'; + $lang['search_for'] = 'Search Extension:'; $lang['search'] = 'Search'; diff --git a/lib/plugins/extension/script.js b/lib/plugins/extension/script.js index 7480801ac..bd3c97758 100644 --- a/lib/plugins/extension/script.js +++ b/lib/plugins/extension/script.js @@ -1,5 +1,15 @@ jQuery(function(){ + /** + * Confirm uninstalling + */ + jQuery('#extension__manager input.uninstall').click(function(e){ + if(!window.confirm(LANG.plugins.extension.reallydel)){ + e.preventDefault(); + return false; + } + return true; + }); /** * very simple lightbox -- cgit v1.2.3 From 2e308c3608bea50e07aacf51b232eaedbda6eb20 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 11 Aug 2013 12:14:44 +0200 Subject: only carry the q to search tab --- lib/plugins/extension/helper/gui.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/extension/helper/gui.php b/lib/plugins/extension/helper/gui.php index 139a1a16a..76651515c 100644 --- a/lib/plugins/extension/helper/gui.php +++ b/lib/plugins/extension/helper/gui.php @@ -180,8 +180,9 @@ class helper_plugin_extension_gui extends DokuWiki_Plugin { 'do' => 'admin', 'page' => 'extension', 'tab' => $tab, - 'q' => $INPUT->str('q') ); + if($tab == 'search') $defaults['q'] = $INPUT->str('q'); + return wl($ID, array_merge($defaults, $params), $absolute, $sep); } -- cgit v1.2.3 From b090397b36856aa72a3c87dc391f5fea13c68571 Mon Sep 17 00:00:00 2001 From: Benedikt Fey Date: Mon, 18 Nov 2013 11:21:02 +0100 Subject: translation update --- lib/plugins/authad/lang/de/settings.php | 2 +- lib/plugins/usermanager/lang/de/lang.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/plugins/authad/lang/de/settings.php b/lib/plugins/authad/lang/de/settings.php index 6bc86dc01..8105fb6f2 100644 --- a/lib/plugins/authad/lang/de/settings.php +++ b/lib/plugins/authad/lang/de/settings.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Frank Loizzi * @author Matthias Schulte * @author Ben Fey diff --git a/lib/plugins/usermanager/lang/de/lang.php b/lib/plugins/usermanager/lang/de/lang.php index d1b9b908b..4b297b0dc 100644 --- a/lib/plugins/usermanager/lang/de/lang.php +++ b/lib/plugins/usermanager/lang/de/lang.php @@ -2,7 +2,7 @@ /** * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * + * * @author Matthias Grimm * @author Andreas Gohr * @author Michael Klier -- cgit v1.2.3 From dce9cd11f94321df5bde479e72fd8a01257b59d3 Mon Sep 17 00:00:00 2001 From: Gerrit Uitslag Date: Mon, 18 Nov 2013 17:11:10 +0100 Subject: translation update --- lib/plugins/authad/lang/nl/settings.php | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/plugins/authad/lang/nl/settings.php b/lib/plugins/authad/lang/nl/settings.php index 69d67be9a..591d72941 100644 --- a/lib/plugins/authad/lang/nl/settings.php +++ b/lib/plugins/authad/lang/nl/settings.php @@ -4,6 +4,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * * @author Remon + * @author Gerrit Uitslag */ $lang['account_suffix'] = 'Je account domeinnaam. Bijv @mijn.domein.org'; $lang['base_dn'] = 'Je basis DN. Bijv. DC=mijn,DC=domein,DC=org'; @@ -11,6 +12,7 @@ $lang['domain_controllers'] = 'Eeen kommagescheiden lijst van domeinservers. $lang['admin_username'] = 'Een geprivilegeerde Active Directory gebruiker die bij alle gebruikersgegevens kan komen. Dit is optioneel maar kan nodig zijn voor bepaalde acties, zoals het versturen van abonnementsmailtjes.'; $lang['admin_password'] = 'Het wachtwoord van bovenstaande gebruiker.'; $lang['sso'] = 'Wordt voor Single-Sign-on Kerberos of NTLM gebruikt?'; +$lang['sso_charset'] = 'Het tekenset waarin je webserver de Kerberos of NTLM gebruikersnaam doorsturen. Leeglaten voor UTF-8 of latin-1. Vereist de iconv extensie.'; $lang['real_primarygroup'] = 'Moet de echte primaire groep worden opgezocht in plaats van het aannemen van "Domeingebruikers" (langzamer)'; $lang['use_ssl'] = 'SSL verbinding gebruiken? Zo ja, activeer dan niet de TLS optie hieronder.'; $lang['use_tls'] = 'TLS verbinding gebruiken? Zo ja, activeer dan niet de SSL verbinding hierboven.'; -- cgit v1.2.3 From 32f730b04ba68c7ca7c2d32208dfac042e6ffffd Mon Sep 17 00:00:00 2001 From: Satoshi Sahara Date: Tue, 19 Nov 2013 08:11:04 +0100 Subject: translation update --- lib/plugins/authmysql/lang/ja/settings.php | 2 +- lib/plugins/authpgsql/lang/ja/settings.php | 2 +- lib/plugins/usermanager/lang/ja/import.txt | 2 +- lib/plugins/usermanager/lang/ja/lang.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/plugins/authmysql/lang/ja/settings.php b/lib/plugins/authmysql/lang/ja/settings.php index 0dc5f1ad8..e5d5689df 100644 --- a/lib/plugins/authmysql/lang/ja/settings.php +++ b/lib/plugins/authmysql/lang/ja/settings.php @@ -11,7 +11,7 @@ $lang['password'] = 'MySQL 接続用ユーザーのパスワード' $lang['database'] = '使用するデータベース名'; $lang['charset'] = 'データベースの文字コード'; $lang['debug'] = 'デバック情報を表示する'; -$lang['forwardClearPass'] = '以下で定義する SQL ステートメントにおいて, パスワード変数 %{pass} を平文とする(DokiWiki側で暗号化しない)'; +$lang['forwardClearPass'] = '以下で定義する SQL ステートメントにおいて, パスワード変数 %{pass} を平文とする(DokiWiki側で暗号化しない)'; $lang['TablesToLock'] = '書き込み時にロックするテーブル(コンマ区切りで列挙)'; $lang['checkPass'] = 'パスワードの照合に用いる SQL ステートメント'; $lang['getUserInfo'] = 'ユーザー情報の取得に用いる SQL ステートメント'; diff --git a/lib/plugins/authpgsql/lang/ja/settings.php b/lib/plugins/authpgsql/lang/ja/settings.php index 2ce63a34a..d7a5f6cf2 100644 --- a/lib/plugins/authpgsql/lang/ja/settings.php +++ b/lib/plugins/authpgsql/lang/ja/settings.php @@ -11,7 +11,7 @@ $lang['user'] = 'PostgreSQL 接続用ユーザー名'; $lang['password'] = 'PostgreSQL 接続用ユーザーのパスワード'; $lang['database'] = '使用するデータベース名'; $lang['debug'] = 'デバック情報を表示する'; -$lang['forwardClearPass'] = '以下で定義する SQL ステートメントにおいて, パスワード変数 %{pass} を平文とする(DokiWiki側で暗号化しない)'; +$lang['forwardClearPass'] = '以下で定義する SQL ステートメントにおいて, パスワード変数 %{pass} を平文とする(DokiWiki側で暗号化しない)'; $lang['checkPass'] = 'パスワードの照合に用いる SQL ステートメント'; $lang['getUserInfo'] = 'ユーザー情報の取得に用いる SQL ステートメント'; $lang['getGroups'] = 'ユーザーが所属する全てのグループの取得に用いる SQL ステートメント'; diff --git a/lib/plugins/usermanager/lang/ja/import.txt b/lib/plugins/usermanager/lang/ja/import.txt index d4f7d08bf..751e515ac 100644 --- a/lib/plugins/usermanager/lang/ja/import.txt +++ b/lib/plugins/usermanager/lang/ja/import.txt @@ -4,7 +4,7 @@ 列の順序:ユーザーID、氏名、電子メールアドレス、グループ。 CSVフィールドはカンマ(,)区切り、文字列は引用符("")区切りです。 エスケープにバックスラッシュ(\)を使用できます。 -適切なファイル例は、上記の"エクスポートユーザー"機能で試して下さい。 +適切なファイル例は、上記の"エクスポートユーザー"機能で試して下さい。 重複するユーザーIDは無視されます。 正常にインポートされたユーザー毎に、パスワードを作成し、電子メールで送付します。 \ No newline at end of file diff --git a/lib/plugins/usermanager/lang/ja/lang.php b/lib/plugins/usermanager/lang/ja/lang.php index 0830416f3..23109f2a2 100644 --- a/lib/plugins/usermanager/lang/ja/lang.php +++ b/lib/plugins/usermanager/lang/ja/lang.php @@ -54,7 +54,7 @@ $lang['edit_usermissing'] = '選択したユーザーは見つかりませ $lang['user_notify'] = 'ユーザーに通知する'; $lang['note_notify'] = '通知メールは、ユーザーに新たなパスワードが設定された場合のみ送信されます。'; $lang['note_group'] = 'グループを指定しない場合は、既定のグループ(%s)に配属されます。'; -$lang['note_pass'] = 'パスワードを空欄とした場合は、(”ユーザーに通知する”がチェックされていなくとも)自動生成したパスワードの通知がユーザー宛てに送信されます。'; +$lang['note_pass'] = '”ユーザーに通知する”をチェックしてパスワードを空欄にすると、パスワードは自動生成されます。'; $lang['add_ok'] = 'ユーザーを登録しました'; $lang['add_fail'] = 'ユーザーの登録に失敗しました'; $lang['notify_ok'] = '通知メールを送信しました'; -- cgit v1.2.3 From a6c758f14a44f0415d89385e5612bb9ae32d6daa Mon Sep 17 00:00:00 2001 From: Myeongjin Date: Sun, 24 Nov 2013 11:37:45 +0100 Subject: translation update --- lib/plugins/usermanager/lang/ko/lang.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/usermanager/lang/ko/lang.php b/lib/plugins/usermanager/lang/ko/lang.php index ccc7f9059..a01cbbdba 100644 --- a/lib/plugins/usermanager/lang/ko/lang.php +++ b/lib/plugins/usermanager/lang/ko/lang.php @@ -68,5 +68,5 @@ $lang['import_error_badmail'] = '잘못된 이메일 주소'; $lang['import_error_upload'] = '가져오기를 실패했습니다. csv 파일을 올릴 수 없거나 비어 있습니다.'; $lang['import_error_readfail'] = '가져오기를 실패했습니다. 올린 파일을 읽을 수 없습니다.'; $lang['import_error_create'] = '사용자를 만들 수 없습니다.'; -$lang['import_notify_fail'] = '알림 메시지를 가져온 %2$s (이메일: %1$s ) 사용자에게 보낼 수 없습니다.'; +$lang['import_notify_fail'] = '알림 메시지를 가져온 %s (이메일: %s ) 사용자에게 보낼 수 없습니다.'; $lang['import_downloadfailures'] = '교정을 위한 CSV로 다운로드 실패'; -- cgit v1.2.3 From 853aa1550199223a46b55e9563790b9ef6a1d234 Mon Sep 17 00:00:00 2001 From: Rami Lehti Date: Sun, 24 Nov 2013 11:38:46 +0100 Subject: translation update --- lib/plugins/acl/lang/fi/lang.php | 5 +++-- lib/plugins/plugin/lang/fi/lang.php | 5 +++-- lib/plugins/popularity/lang/fi/lang.php | 5 +++-- lib/plugins/revert/lang/fi/lang.php | 5 +++-- lib/plugins/usermanager/lang/fi/lang.php | 5 +++-- 5 files changed, 15 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/plugins/acl/lang/fi/lang.php b/lib/plugins/acl/lang/fi/lang.php index 4f145e0f6..50224dfb4 100644 --- a/lib/plugins/acl/lang/fi/lang.php +++ b/lib/plugins/acl/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila diff --git a/lib/plugins/plugin/lang/fi/lang.php b/lib/plugins/plugin/lang/fi/lang.php index 923029a6f..f51746faa 100644 --- a/lib/plugins/plugin/lang/fi/lang.php +++ b/lib/plugins/plugin/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila diff --git a/lib/plugins/popularity/lang/fi/lang.php b/lib/plugins/popularity/lang/fi/lang.php index d7c230742..ec0fc4071 100644 --- a/lib/plugins/popularity/lang/fi/lang.php +++ b/lib/plugins/popularity/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila * @author Sami Olmari diff --git a/lib/plugins/revert/lang/fi/lang.php b/lib/plugins/revert/lang/fi/lang.php index fdf9bb81c..d14f527f9 100644 --- a/lib/plugins/revert/lang/fi/lang.php +++ b/lib/plugins/revert/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila diff --git a/lib/plugins/usermanager/lang/fi/lang.php b/lib/plugins/usermanager/lang/fi/lang.php index 1db4bd7fb..de243133a 100644 --- a/lib/plugins/usermanager/lang/fi/lang.php +++ b/lib/plugins/usermanager/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila -- cgit v1.2.3 From a8bca8a644cdcea093acf51a543cbff261ef0b8a Mon Sep 17 00:00:00 2001 From: Otto Vainio Date: Sun, 24 Nov 2013 18:01:23 +0100 Subject: translation update --- lib/plugins/acl/lang/fi/lang.php | 5 +++-- lib/plugins/authad/lang/fi/settings.php | 7 +++++-- lib/plugins/authldap/lang/fi/settings.php | 9 +++++++-- lib/plugins/plugin/lang/fi/lang.php | 5 +++-- lib/plugins/popularity/lang/fi/lang.php | 5 +++-- lib/plugins/revert/lang/fi/lang.php | 5 +++-- lib/plugins/usermanager/lang/fi/lang.php | 5 +++-- 7 files changed, 27 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/plugins/acl/lang/fi/lang.php b/lib/plugins/acl/lang/fi/lang.php index 4f145e0f6..50224dfb4 100644 --- a/lib/plugins/acl/lang/fi/lang.php +++ b/lib/plugins/acl/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila diff --git a/lib/plugins/authad/lang/fi/settings.php b/lib/plugins/authad/lang/fi/settings.php index d3aa13e07..e2f432f36 100644 --- a/lib/plugins/authad/lang/fi/settings.php +++ b/lib/plugins/authad/lang/fi/settings.php @@ -1,6 +1,9 @@ */ +$lang['debug'] = 'Näytä lisää debug-koodia virheistä?'; +$lang['expirywarn'] = 'Montako päivää etukäteen varoitetaan salasanan vanhenemissta. 0 poistaa.'; diff --git a/lib/plugins/authldap/lang/fi/settings.php b/lib/plugins/authldap/lang/fi/settings.php index d3aa13e07..b15d8c676 100644 --- a/lib/plugins/authldap/lang/fi/settings.php +++ b/lib/plugins/authldap/lang/fi/settings.php @@ -1,6 +1,11 @@ */ +$lang['starttls'] = 'Käytä TLS yhteyttä'; +$lang['bindpw'] = 'Ylläolevan käyttäjän salasana'; +$lang['userscope'] = 'Etsi vain käyttäjiä'; +$lang['groupscope'] = 'Etsi vain ryhmiä'; diff --git a/lib/plugins/plugin/lang/fi/lang.php b/lib/plugins/plugin/lang/fi/lang.php index 923029a6f..f51746faa 100644 --- a/lib/plugins/plugin/lang/fi/lang.php +++ b/lib/plugins/plugin/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila diff --git a/lib/plugins/popularity/lang/fi/lang.php b/lib/plugins/popularity/lang/fi/lang.php index d7c230742..ec0fc4071 100644 --- a/lib/plugins/popularity/lang/fi/lang.php +++ b/lib/plugins/popularity/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila * @author Sami Olmari diff --git a/lib/plugins/revert/lang/fi/lang.php b/lib/plugins/revert/lang/fi/lang.php index fdf9bb81c..d14f527f9 100644 --- a/lib/plugins/revert/lang/fi/lang.php +++ b/lib/plugins/revert/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila diff --git a/lib/plugins/usermanager/lang/fi/lang.php b/lib/plugins/usermanager/lang/fi/lang.php index 1db4bd7fb..de243133a 100644 --- a/lib/plugins/usermanager/lang/fi/lang.php +++ b/lib/plugins/usermanager/lang/fi/lang.php @@ -1,7 +1,8 @@ * @author Teemu Mattila -- cgit v1.2.3 From 94070874cc8d8702821161dbaa291e8b2d043ad3 Mon Sep 17 00:00:00 2001 From: Thomas Juberg Date: Sun, 24 Nov 2013 18:02:23 +0100 Subject: translation update --- lib/plugins/acl/lang/no/lang.php | 6 +++--- lib/plugins/plugin/lang/no/lang.php | 7 ++++--- lib/plugins/popularity/lang/no/lang.php | 7 ++++--- lib/plugins/revert/lang/no/lang.php | 8 +++++--- lib/plugins/usermanager/lang/no/lang.php | 7 ++++--- 5 files changed, 20 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/plugins/acl/lang/no/lang.php b/lib/plugins/acl/lang/no/lang.php index 09d71937a..82cdd5eef 100644 --- a/lib/plugins/acl/lang/no/lang.php +++ b/lib/plugins/acl/lang/no/lang.php @@ -1,8 +1,8 @@ * @author Jorge Barrera Grandon * @author Thomas Nygreen @@ -10,7 +10,7 @@ * @author Torkill Bruland * @author Rune M. Andersen * @author Jakob Vad Nielsen (me@jakobnielsen.net) - * @author Kjell Tore Næsgaard + * @author Kjell Tore Næsgaard * @author Knut Staring * @author Lisa Ditlefsen * @author Erik Pedersen diff --git a/lib/plugins/plugin/lang/no/lang.php b/lib/plugins/plugin/lang/no/lang.php index 829d29387..2b890f972 100644 --- a/lib/plugins/plugin/lang/no/lang.php +++ b/lib/plugins/plugin/lang/no/lang.php @@ -1,13 +1,14 @@ * @author Arild Burud * @author Torkill Bruland * @author Rune M. Andersen * @author Jakob Vad Nielsen (me@jakobnielsen.net) - * @author Kjell Tore Næsgaard + * @author Kjell Tore Næsgaard * @author Knut Staring * @author Lisa Ditlefsen * @author Erik Pedersen diff --git a/lib/plugins/popularity/lang/no/lang.php b/lib/plugins/popularity/lang/no/lang.php index df38f6e0e..dfa99d824 100644 --- a/lib/plugins/popularity/lang/no/lang.php +++ b/lib/plugins/popularity/lang/no/lang.php @@ -1,10 +1,11 @@ * @author Jakob Vad Nielsen (me@jakobnielsen.net) - * @author Kjell Tore Næsgaard + * @author Kjell Tore Næsgaard * @author Knut Staring * @author Lisa Ditlefsen * @author Erik Pedersen diff --git a/lib/plugins/revert/lang/no/lang.php b/lib/plugins/revert/lang/no/lang.php index 299b12ea7..e7887a07e 100644 --- a/lib/plugins/revert/lang/no/lang.php +++ b/lib/plugins/revert/lang/no/lang.php @@ -1,13 +1,14 @@ * @author Arild Burud * @author Torkill Bruland * @author Rune M. Andersen * @author Jakob Vad Nielsen (me@jakobnielsen.net) - * @author Kjell Tore Næsgaard + * @author Kjell Tore Næsgaard * @author Knut Staring * @author Lisa Ditlefsen * @author Erik Pedersen @@ -15,6 +16,7 @@ * @author Rune Rasmussen syntaxerror.no@gmail.com * @author Jon Bøe * @author Egil Hansen + * @author Thomas Juberg */ $lang['menu'] = 'Tilbakestillingsbehandler'; $lang['filter'] = 'Søk etter søppelmeldinger'; diff --git a/lib/plugins/usermanager/lang/no/lang.php b/lib/plugins/usermanager/lang/no/lang.php index 7124e4811..83823b2b8 100644 --- a/lib/plugins/usermanager/lang/no/lang.php +++ b/lib/plugins/usermanager/lang/no/lang.php @@ -1,13 +1,14 @@ * @author Arild Burud * @author Torkill Bruland * @author Rune M. Andersen * @author Jakob Vad Nielsen (me@jakobnielsen.net) - * @author Kjell Tore Næsgaard + * @author Kjell Tore Næsgaard * @author Knut Staring * @author Lisa Ditlefsen * @author Erik Pedersen -- cgit v1.2.3 From 8d6ec7dd27c536bbaf7d7c0c4f5f99ae20860f3b Mon Sep 17 00:00:00 2001 From: Tomasz Bosak Date: Sun, 24 Nov 2013 18:03:51 +0100 Subject: translation update --- lib/plugins/acl/lang/pl/lang.php | 4 ++-- lib/plugins/authad/lang/pl/settings.php | 7 +++++-- lib/plugins/authldap/lang/pl/settings.php | 5 +++-- lib/plugins/authmysql/lang/pl/settings.php | 5 +++-- lib/plugins/plugin/lang/pl/lang.php | 4 ++-- lib/plugins/popularity/lang/pl/lang.php | 5 +++-- lib/plugins/revert/lang/pl/lang.php | 4 +++- lib/plugins/usermanager/lang/pl/lang.php | 5 +++-- 8 files changed, 24 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/plugins/acl/lang/pl/lang.php b/lib/plugins/acl/lang/pl/lang.php index bef2d2615..42ce7fdaf 100644 --- a/lib/plugins/acl/lang/pl/lang.php +++ b/lib/plugins/acl/lang/pl/lang.php @@ -1,8 +1,8 @@ * @author Mariusz Kujawski * @author Maciej Kurczewski diff --git a/lib/plugins/authad/lang/pl/settings.php b/lib/plugins/authad/lang/pl/settings.php index 9113c0e51..ad051b0ac 100644 --- a/lib/plugins/authad/lang/pl/settings.php +++ b/lib/plugins/authad/lang/pl/settings.php @@ -1,9 +1,12 @@ */ $lang['account_suffix'] = 'Przyrostek twojej nazwy konta np. @my.domain.org'; +$lang['base_dn'] = 'Twoje bazowe DN. Na przykład: DC=my,DC=domain,DC=org'; $lang['admin_password'] = 'Hasło dla powyższego użytkownika.'; $lang['use_ssl'] = 'Użyć połączenie SSL? Jeśli tak to nie aktywuj TLS poniżej.'; $lang['use_tls'] = 'Użyć połączenie TLS? Jeśli tak to nie aktywuj SSL powyżej.'; diff --git a/lib/plugins/authldap/lang/pl/settings.php b/lib/plugins/authldap/lang/pl/settings.php index 44641f514..084521e0d 100644 --- a/lib/plugins/authldap/lang/pl/settings.php +++ b/lib/plugins/authldap/lang/pl/settings.php @@ -1,7 +1,8 @@ * @author Grzegorz Żur * @author Mariusz Kujawski diff --git a/lib/plugins/popularity/lang/pl/lang.php b/lib/plugins/popularity/lang/pl/lang.php index 76a9464bd..045574a69 100644 --- a/lib/plugins/popularity/lang/pl/lang.php +++ b/lib/plugins/popularity/lang/pl/lang.php @@ -1,7 +1,8 @@ * @author Mariusz Kujawski * @author Maciej Kurczewski diff --git a/lib/plugins/revert/lang/pl/lang.php b/lib/plugins/revert/lang/pl/lang.php index 462841292..d2d53b87e 100644 --- a/lib/plugins/revert/lang/pl/lang.php +++ b/lib/plugins/revert/lang/pl/lang.php @@ -1,6 +1,8 @@ * @author Mariusz Kujawski * @author Maciej Kurczewski diff --git a/lib/plugins/usermanager/lang/pl/lang.php b/lib/plugins/usermanager/lang/pl/lang.php index cfc0ba327..2e063d2bb 100644 --- a/lib/plugins/usermanager/lang/pl/lang.php +++ b/lib/plugins/usermanager/lang/pl/lang.php @@ -1,7 +1,8 @@ * @author Mariusz Kujawski * @author Maciej Kurczewski -- cgit v1.2.3 From eb1d4fdee478e7cd379c3dd4a89f81ad096155c6 Mon Sep 17 00:00:00 2001 From: Claudio Lanconelli Date: Mon, 25 Nov 2013 02:00:56 +0100 Subject: translation update --- lib/plugins/authldap/lang/it/settings.php | 4 ++++ lib/plugins/authmysql/lang/it/settings.php | 7 +++++-- lib/plugins/usermanager/lang/it/lang.php | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/plugins/authldap/lang/it/settings.php b/lib/plugins/authldap/lang/it/settings.php index 023159489..eba7cde6e 100644 --- a/lib/plugins/authldap/lang/it/settings.php +++ b/lib/plugins/authldap/lang/it/settings.php @@ -4,6 +4,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * * @author Edmondo Di Tucci + * @author Claudio Lanconelli */ $lang['server'] = 'Il tuo server LDAP. Inserire o l\'hostname (localhost) oppure un URL completo (ldap://server.tld:389)'; $lang['port'] = 'Porta del server LDAP se non è stato fornito un URL completo più sopra.'; @@ -13,3 +14,6 @@ $lang['userfilter'] = 'Filtro per cercare l\'account utente LDAP. Eg. $lang['groupfilter'] = 'Filtro per cercare i gruppi LDAP. Eg. (&(objectClass=posixGroup)(|(gidNumber=%{gid})(memberUID=%{user})))'; $lang['version'] = 'Versione protocollo da usare. Pu3'; $lang['starttls'] = 'Usare la connessione TSL?'; +$lang['userscope'] = 'Limita il contesto di ricerca per la ricerca degli utenti'; +$lang['groupscope'] = 'Limita il contesto di ricerca per la ricerca dei gruppi'; +$lang['debug'] = 'In caso di errori mostra ulteriori informazioni di debug'; diff --git a/lib/plugins/authmysql/lang/it/settings.php b/lib/plugins/authmysql/lang/it/settings.php index 10ae72f87..e493ec7e9 100644 --- a/lib/plugins/authmysql/lang/it/settings.php +++ b/lib/plugins/authmysql/lang/it/settings.php @@ -1,5 +1,8 @@ */ +$lang['debug'] = 'Mostra ulteriori informazioni di debug'; diff --git a/lib/plugins/usermanager/lang/it/lang.php b/lib/plugins/usermanager/lang/it/lang.php index dfacc6545..6c6789442 100644 --- a/lib/plugins/usermanager/lang/it/lang.php +++ b/lib/plugins/usermanager/lang/it/lang.php @@ -15,6 +15,7 @@ * @author Jacopo Corbetta * @author Matteo Pasotti * @author snarchio@gmail.com + * @author Claudio Lanconelli */ $lang['menu'] = 'Gestione Utenti'; $lang['noauth'] = '(autenticazione non disponibile)'; @@ -37,6 +38,8 @@ $lang['search'] = 'Cerca'; $lang['search_prompt'] = 'Esegui ricerca'; $lang['clear'] = 'Azzera filtro di ricerca'; $lang['filter'] = 'Filtro'; +$lang['export_all'] = 'Esporta tutti gli utenti (CSV)'; +$lang['export_filtered'] = 'Esporta elenco utenti filtrati (CSV)'; $lang['summary'] = 'Visualizzazione utenti %1$d-%2$d di %3$d trovati. %4$d utenti totali.'; $lang['nonefound'] = 'Nessun utente trovato. %d utenti totali.'; $lang['delete_ok'] = '%d utenti eliminati'; -- cgit v1.2.3 From 79c64e955bca6f4339fafa21543e532b11f341cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Brandt?= Date: Mon, 25 Nov 2013 08:31:02 +0100 Subject: translation update --- lib/plugins/usermanager/lang/fr/lang.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/plugins/usermanager/lang/fr/lang.php b/lib/plugins/usermanager/lang/fr/lang.php index 7c24ef900..dd0e64fc4 100644 --- a/lib/plugins/usermanager/lang/fr/lang.php +++ b/lib/plugins/usermanager/lang/fr/lang.php @@ -23,6 +23,7 @@ * @author Bruno Veilleux * @author Antoine Turmel * @author schplurtz + * @author Jérôme Brandt */ $lang['menu'] = 'Gestion des utilisateurs'; $lang['noauth'] = '(authentification de l\'utilisateur non disponible)'; @@ -70,6 +71,8 @@ $lang['add_ok'] = 'Utilisateur ajouté avec succès'; $lang['add_fail'] = 'Échec de l\'ajout de l\'utilisateur'; $lang['notify_ok'] = 'Courriel de notification expédié'; $lang['notify_fail'] = 'Échec de l\'expédition du courriel de notification'; +$lang['import_userlistcsv'] = 'Liste utilisateur (fichier CSV)'; +$lang['import_header'] = 'Erreurs d\'import les plus récentes'; $lang['import_success_count'] = 'Import d’utilisateurs : %d utilisateurs trouvés, %d utilisateurs importés avec succès.'; $lang['import_failure_count'] = 'Import d\'utilisateurs : %d ont échoué. Les erreurs sont listées ci-dessous.'; $lang['import_error_fields'] = 'Nombre de champs insuffisant, %d trouvé, 4 requis.'; @@ -80,3 +83,4 @@ $lang['import_error_upload'] = 'L\'import a échoué. Le fichier csv n\'a pas $lang['import_error_readfail'] = 'L\'import a échoué. Impossible de lire le fichier téléchargé.'; $lang['import_error_create'] = 'Impossible de créer l\'utilisateur'; $lang['import_notify_fail'] = 'Impossible d\'expédier une notification à l\'utilisateur importé %s, adresse %s.'; +$lang['import_downloadfailures'] = 'Télécharger les erreurs au format CSV pour correction'; -- cgit v1.2.3 From 356106d54d31e84089087217b4895a87900b3fe0 Mon Sep 17 00:00:00 2001 From: Boris Date: Mon, 25 Nov 2013 14:05:53 +0100 Subject: translation update --- lib/plugins/revert/lang/no/lang.php | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/plugins/revert/lang/no/lang.php b/lib/plugins/revert/lang/no/lang.php index e7887a07e..c58300dc0 100644 --- a/lib/plugins/revert/lang/no/lang.php +++ b/lib/plugins/revert/lang/no/lang.php @@ -17,6 +17,7 @@ * @author Jon Bøe * @author Egil Hansen * @author Thomas Juberg + * @author Boris */ $lang['menu'] = 'Tilbakestillingsbehandler'; $lang['filter'] = 'Søk etter søppelmeldinger'; -- cgit v1.2.3 From 53afdafe30f20e091aff7b0cf6bbb86aa7b50078 Mon Sep 17 00:00:00 2001 From: Garam Date: Mon, 25 Nov 2013 20:05:58 +0100 Subject: translation update --- lib/plugins/authmysql/lang/ko/settings.php | 9 +++++---- lib/plugins/authpgsql/lang/ko/settings.php | 9 +++++---- lib/plugins/usermanager/lang/ko/lang.php | 3 ++- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/plugins/authmysql/lang/ko/settings.php b/lib/plugins/authmysql/lang/ko/settings.php index 2175c1eea..b3479ad41 100644 --- a/lib/plugins/authmysql/lang/ko/settings.php +++ b/lib/plugins/authmysql/lang/ko/settings.php @@ -4,6 +4,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * * @author Myeongjin + * @author Garam */ $lang['server'] = 'MySQL 서버'; $lang['user'] = 'MySQL 사용자 이름'; @@ -17,10 +18,10 @@ $lang['checkPass'] = '비밀번호를 확인하기 위한 SQL 문'; $lang['getUserInfo'] = '사용자 정보를 가져오기 위한 SQL 문'; $lang['getGroups'] = '사용자의 그룹 구성원을 가져오기 위한 SQL 문'; $lang['getUsers'] = '모든 사용자를 나타낼 SQL 문'; -$lang['FilterLogin'] = '로그인 이름 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterName'] = '전체 이름 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterEmail'] = '이메일 주소 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterGroup'] = '그룹 구성원 별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterLogin'] = '로그인 이름별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterName'] = '전체 이름별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterEmail'] = '이메일 주소별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterGroup'] = '그룹 구성원별로 사용자를 필터하기 위한 SQL 조항'; $lang['SortOrder'] = '사용자를 정렬할 SQL 조항'; $lang['addUser'] = '새 사용자를 추가할 SQL 문'; $lang['addGroup'] = '새 그룹을 추가할 SQL 문'; diff --git a/lib/plugins/authpgsql/lang/ko/settings.php b/lib/plugins/authpgsql/lang/ko/settings.php index bdd8c2718..bdf38b3c7 100644 --- a/lib/plugins/authpgsql/lang/ko/settings.php +++ b/lib/plugins/authpgsql/lang/ko/settings.php @@ -4,6 +4,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * * @author Myeongjin + * @author Garam */ $lang['server'] = 'PostgreSQL 서버'; $lang['port'] = 'PostgreSQL 서버의 포트'; @@ -16,10 +17,10 @@ $lang['checkPass'] = '비밀번호를 확인하기 위한 SQL 문'; $lang['getUserInfo'] = '사용자 정보를 가져오기 위한 SQL 문'; $lang['getGroups'] = '사용자의 그룹 구성원을 가져오기 위한 SQL 문'; $lang['getUsers'] = '모든 사용자를 나타낼 SQL 문'; -$lang['FilterLogin'] = '로그인 이름 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterName'] = '전체 이름 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterEmail'] = '이메일 주소 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterGroup'] = '그룹 구성원 별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterLogin'] = '로그인 이름별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterName'] = '전체 이름별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterEmail'] = '이메일 주소별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterGroup'] = '그룹 구성원별로 사용자를 필터하기 위한 SQL 조항'; $lang['SortOrder'] = '사용자를 정렬할 SQL 조항'; $lang['addUser'] = '새 사용자를 추가할 SQL 문'; $lang['addGroup'] = '새 그룹을 추가할 SQL 문'; diff --git a/lib/plugins/usermanager/lang/ko/lang.php b/lib/plugins/usermanager/lang/ko/lang.php index a01cbbdba..3656a1698 100644 --- a/lib/plugins/usermanager/lang/ko/lang.php +++ b/lib/plugins/usermanager/lang/ko/lang.php @@ -10,6 +10,7 @@ * @author erial2@gmail.com * @author Myeongjin * @author Gerrit Uitslag + * @author Garam */ $lang['menu'] = '사용자 관리자'; $lang['noauth'] = '(사용자 인증이 불가능합니다)'; @@ -33,7 +34,7 @@ $lang['search_prompt'] = '검색 수행'; $lang['clear'] = '검색 필터 재설정'; $lang['filter'] = '필터'; $lang['export_all'] = '모든 사용자 목록 내보내기 (CSV)'; -$lang['export_filtered'] = '필터된 사용자 목록 내보내기 (CSV)'; +$lang['export_filtered'] = '필터된 사용자 목록 내보내기(CSV)'; $lang['import'] = '새 사용자 목록 가져오기'; $lang['line'] = '줄 번호'; $lang['error'] = '오류 메시지'; -- cgit v1.2.3 From ffe35fe919de6c9f52316dd272e6e22c4bde8d81 Mon Sep 17 00:00:00 2001 From: Garam Date: Mon, 25 Nov 2013 20:50:59 +0100 Subject: translation update --- lib/plugins/acl/lang/ko/lang.php | 5 +++-- lib/plugins/authad/lang/ko/settings.php | 3 ++- lib/plugins/authpgsql/lang/ko/settings.php | 9 +++++---- lib/plugins/plugin/lang/ko/lang.php | 15 ++++++++------- lib/plugins/popularity/lang/ko/lang.php | 3 ++- lib/plugins/usermanager/lang/ko/lang.php | 11 ++++++----- 6 files changed, 26 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/plugins/acl/lang/ko/lang.php b/lib/plugins/acl/lang/ko/lang.php index 2f1ba2311..37cec307c 100644 --- a/lib/plugins/acl/lang/ko/lang.php +++ b/lib/plugins/acl/lang/ko/lang.php @@ -12,6 +12,7 @@ * @author Seung-Chul Yoo * @author erial2@gmail.com * @author Myeongjin + * @author Garam */ $lang['admin_acl'] = '접근 제어 목록 관리'; $lang['acl_group'] = '그룹'; @@ -27,7 +28,7 @@ $lang['p_group_ns'] = '%s 그룹 구성원은 $lang['p_choose_id'] = '%s 문서 접근 권한을 보거나 바꾸려면 사용자그룹을 위 양식에 입력하세요.'; $lang['p_choose_ns'] = '%s 이름공간 접근 권한을 보거나 바꾸려면 사용자그룹을 위 양식에 입력하세요.'; $lang['p_inherited'] = '참고: 권한이 명시적으로 설정되지 않았으므로 다른 그룹이나 상위 이름공간으로부터 가져왔습니다.'; -$lang['p_isadmin'] = '참고: 슈퍼유저로 설정되어 있으므로 선택된 그룹이나 사용자는 언제나 모든 접근 권한을 가집니다.'; +$lang['p_isadmin'] = '참고: 슈퍼 사용자로 설정되어 있으므로 선택된 그룹이나 사용자는 언제나 모든 접근 권한을 가집니다.'; $lang['p_include'] = '더 높은 접근 권한은 하위를 포함합니다. 문서가 아닌 이름공간에는 만들기, 올리기, 삭제 권한만 적용됩니다.'; $lang['current'] = '현재 ACL 규칙'; $lang['where'] = '문서/이름공간'; @@ -38,6 +39,6 @@ $lang['acl_perm1'] = '읽기'; $lang['acl_perm2'] = '편집'; $lang['acl_perm4'] = '만들기'; $lang['acl_perm8'] = '올리기'; -$lang['acl_perm16'] = '삭제'; +$lang['acl_perm16'] = '지우기'; $lang['acl_new'] = '새 항목 추가'; $lang['acl_mod'] = '항목 수정'; diff --git a/lib/plugins/authad/lang/ko/settings.php b/lib/plugins/authad/lang/ko/settings.php index 053823508..6c00950bf 100644 --- a/lib/plugins/authad/lang/ko/settings.php +++ b/lib/plugins/authad/lang/ko/settings.php @@ -4,6 +4,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * * @author Myeongjin + * @author Garam */ $lang['account_suffix'] = '계정 접미어. 예를 들어 @my.domain.org'; $lang['base_dn'] = '기본 DN. 예를 들어 DC=my,DC=domain,DC=org'; @@ -12,7 +13,7 @@ $lang['admin_username'] = '다른 모든 사용자의 데이터에 접근 $lang['admin_password'] = '위 사용자의 비밀번호.'; $lang['sso'] = 'Kerberos나 NTLM을 통해 Single-Sign-On을 사용해야 합니까?'; $lang['sso_charset'] = '당신의 웹서버의 문자집합은 Kerberos나 NTLM 사용자 이름으로 전달됩니다. UTF-8이나 라린-1이 비어 있습니다. icov 확장 기능이 필요합니다.'; -$lang['real_primarygroup'] = '실제 기본 그룹은 "도메인 사용자"를 가정하는 대신 해결될 것입니다 (느림)'; +$lang['real_primarygroup'] = '실제 기본 그룹은 "도메인 사용자"를 가정하는 대신 해결될 것입니다(느림)'; $lang['use_ssl'] = 'SSL 연결을 사용합니까? 사용한다면 아래 TLS을 활성화하지 마세요.'; $lang['use_tls'] = 'TLS 연결을 사용합니까? 사용한다면 위 SSL을 활성화하지 마세요.'; $lang['debug'] = '오류에 대한 추가적인 디버그 정보를 보이겠습니까?'; diff --git a/lib/plugins/authpgsql/lang/ko/settings.php b/lib/plugins/authpgsql/lang/ko/settings.php index bdd8c2718..bdf38b3c7 100644 --- a/lib/plugins/authpgsql/lang/ko/settings.php +++ b/lib/plugins/authpgsql/lang/ko/settings.php @@ -4,6 +4,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * * @author Myeongjin + * @author Garam */ $lang['server'] = 'PostgreSQL 서버'; $lang['port'] = 'PostgreSQL 서버의 포트'; @@ -16,10 +17,10 @@ $lang['checkPass'] = '비밀번호를 확인하기 위한 SQL 문'; $lang['getUserInfo'] = '사용자 정보를 가져오기 위한 SQL 문'; $lang['getGroups'] = '사용자의 그룹 구성원을 가져오기 위한 SQL 문'; $lang['getUsers'] = '모든 사용자를 나타낼 SQL 문'; -$lang['FilterLogin'] = '로그인 이름 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterName'] = '전체 이름 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterEmail'] = '이메일 주소 별로 사용자를 필터하기 위한 SQL 조항'; -$lang['FilterGroup'] = '그룹 구성원 별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterLogin'] = '로그인 이름별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterName'] = '전체 이름별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterEmail'] = '이메일 주소별로 사용자를 필터하기 위한 SQL 조항'; +$lang['FilterGroup'] = '그룹 구성원별로 사용자를 필터하기 위한 SQL 조항'; $lang['SortOrder'] = '사용자를 정렬할 SQL 조항'; $lang['addUser'] = '새 사용자를 추가할 SQL 문'; $lang['addGroup'] = '새 그룹을 추가할 SQL 문'; diff --git a/lib/plugins/plugin/lang/ko/lang.php b/lib/plugins/plugin/lang/ko/lang.php index 6ef9cd69a..8d2006672 100644 --- a/lib/plugins/plugin/lang/ko/lang.php +++ b/lib/plugins/plugin/lang/ko/lang.php @@ -9,6 +9,7 @@ * @author Seung-Chul Yoo * @author erial2@gmail.com * @author Myeongjin + * @author Garam */ $lang['menu'] = '플러그인 관리'; $lang['download'] = '새 플러그인을 다운로드하고 설치'; @@ -33,16 +34,16 @@ $lang['deleted'] = '%s 플러그인이 삭제되었습니다.'; $lang['downloading'] = '다운로드 중 ...'; $lang['downloaded'] = '%s 플러그인이 성공적으로 설치되었습니다'; $lang['downloads'] = '다음 플러그인이 성공적으로 설치되었습니다:'; -$lang['download_none'] = '플러그인이 없거나 다운로드 또는 설치 중에 알 수 없는 문제가 발생했습니다.'; +$lang['download_none'] = '플러그인이 없거나 다운로드 또는 설치 중에 알 수 없는 문제가 발생하였습니다.'; $lang['plugin'] = '플러그인:'; $lang['components'] = '구성 요소'; $lang['noinfo'] = '이 플러그인은 어떤 정보도 없습니다. 잘못된 플러그인일 수 있습니다.'; -$lang['name'] = '이름:'; -$lang['date'] = '날짜:'; -$lang['type'] = '종류:'; -$lang['desc'] = '설명:'; -$lang['author'] = '저자:'; -$lang['www'] = '웹:'; +$lang['name'] = '이름: '; +$lang['date'] = '날짜: '; +$lang['type'] = '종류: '; +$lang['desc'] = '설명: '; +$lang['author'] = '저자: '; +$lang['www'] = '웹: '; $lang['error'] = '알 수 없는 문제가 발생했습니다.'; $lang['error_download'] = '플러그인 파일을 다운로드 할 수 없습니다: %s'; $lang['error_badurl'] = '잘못된 URL 같습니다 - URL에서 파일 이름을 알 수 없습니다'; diff --git a/lib/plugins/popularity/lang/ko/lang.php b/lib/plugins/popularity/lang/ko/lang.php index f52e0007a..088ef1dc9 100644 --- a/lib/plugins/popularity/lang/ko/lang.php +++ b/lib/plugins/popularity/lang/ko/lang.php @@ -9,8 +9,9 @@ * @author Seung-Chul Yoo * @author erial2@gmail.com * @author Myeongjin + * @author Garam */ -$lang['name'] = '인기도 조사 (불러오는 데 시간이 걸릴 수 있습니다)'; +$lang['name'] = '인기도 조사(불러오는 데 시간이 걸릴 수 있습니다)'; $lang['submit'] = '자료 보내기'; $lang['autosubmit'] = '자료를 자동으로 한 달에 한 번씩 보내기'; $lang['submissionFailed'] = '다음과 같은 이유로 자료 보내기에 실패했습니다:'; diff --git a/lib/plugins/usermanager/lang/ko/lang.php b/lib/plugins/usermanager/lang/ko/lang.php index a01cbbdba..7c629f74f 100644 --- a/lib/plugins/usermanager/lang/ko/lang.php +++ b/lib/plugins/usermanager/lang/ko/lang.php @@ -10,6 +10,7 @@ * @author erial2@gmail.com * @author Myeongjin * @author Gerrit Uitslag + * @author Garam */ $lang['menu'] = '사용자 관리자'; $lang['noauth'] = '(사용자 인증이 불가능합니다)'; @@ -32,8 +33,8 @@ $lang['search'] = '검색'; $lang['search_prompt'] = '검색 수행'; $lang['clear'] = '검색 필터 재설정'; $lang['filter'] = '필터'; -$lang['export_all'] = '모든 사용자 목록 내보내기 (CSV)'; -$lang['export_filtered'] = '필터된 사용자 목록 내보내기 (CSV)'; +$lang['export_all'] = '모든 사용자 목록 내보내기(CSV)'; +$lang['export_filtered'] = '필터된 사용자 목록 내보내기(CSV)'; $lang['import'] = '새 사용자 목록 가져오기'; $lang['line'] = '줄 번호'; $lang['error'] = '오류 메시지'; @@ -52,12 +53,12 @@ $lang['edit_usermissing'] = '선택된 사용자를 찾을 수 없습니다 $lang['user_notify'] = '사용자에게 알림'; $lang['note_notify'] = '사용자에게 새로운 비밀번호를 준 경우에만 알림 이메일이 보내집니다.'; $lang['note_group'] = '새로운 사용자는 어떤 그룹도 설정하지 않은 경우에 기본 그룹(%s)에 추가됩니다.'; -$lang['note_pass'] = '사용자 통지가 지정되어 있을 때 필드에 아무 값도 입력하지 않으면 비밀번호가 자동으로 만들어집니다.'; +$lang['note_pass'] = '사용자 알림이 지정되어 있을 때 필드에 아무 값도 입력하지 않으면 비밀번호가 자동으로 만들어집니다.'; $lang['add_ok'] = '사용자를 성공적으로 추가했습니다'; $lang['add_fail'] = '사용자 추가를 실패했습니다'; $lang['notify_ok'] = '알림 이메일을 성공적으로 보냈습니다'; $lang['notify_fail'] = '알림 이메일을 보낼 수 없습니다'; -$lang['import_userlistcsv'] = '사용자 목록 파일 (CSV):'; +$lang['import_userlistcsv'] = '사용자 목록 파일(CSV):'; $lang['import_header'] = '가장 최근 가져오기 - 실패'; $lang['import_success_count'] = '사용자 가져오기: 사용자 %d명을 찾았고, %d명을 성공적으로 가져왔습니다.'; $lang['import_failure_count'] = '사용자 가져오기: %d명을 가져오지 못했습니다. 실패는 아래에 나타나 있습니다.'; @@ -68,5 +69,5 @@ $lang['import_error_badmail'] = '잘못된 이메일 주소'; $lang['import_error_upload'] = '가져오기를 실패했습니다. csv 파일을 올릴 수 없거나 비어 있습니다.'; $lang['import_error_readfail'] = '가져오기를 실패했습니다. 올린 파일을 읽을 수 없습니다.'; $lang['import_error_create'] = '사용자를 만들 수 없습니다.'; -$lang['import_notify_fail'] = '알림 메시지를 가져온 %s (이메일: %s ) 사용자에게 보낼 수 없습니다.'; +$lang['import_notify_fail'] = '알림 메시지를 가져온 %s(이메일: %s) 사용자에게 보낼 수 없습니다.'; $lang['import_downloadfailures'] = '교정을 위한 CSV로 다운로드 실패'; -- cgit v1.2.3 From 43e700149db19863b559e0eebc44132c611ef08d Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 26 Nov 2013 12:19:18 +0100 Subject: fix numeric expression read in plugin default conf FS#2888 --- lib/plugins/config/settings/config.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/plugins/config/settings/config.class.php b/lib/plugins/config/settings/config.class.php index a5a11cda1..ab76ddc9e 100644 --- a/lib/plugins/config/settings/config.class.php +++ b/lib/plugins/config/settings/config.class.php @@ -330,8 +330,7 @@ if (!class_exists('configuration')) { foreach ($this->get_plugin_list() as $plugin) { $plugin_dir = plugin_directory($plugin); if (@file_exists(DOKU_PLUGIN.$plugin_dir.$file)){ - $conf = array(); - @include(DOKU_PLUGIN.$plugin_dir.$file); + $conf = $this->_read_config(DOKU_PLUGIN.$plugin_dir.$file); foreach ($conf as $key => $value){ $default['plugin'.CM_KEYMARKER.$plugin.CM_KEYMARKER.$key] = $value; } -- cgit v1.2.3 From 8c58242fcc4654752ab53c46ec31d1bc4a622140 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Tue, 26 Nov 2013 12:47:40 +0100 Subject: FS#2888 fix for templates --- lib/plugins/config/settings/config.class.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/plugins/config/settings/config.class.php b/lib/plugins/config/settings/config.class.php index ab76ddc9e..05f8470f7 100644 --- a/lib/plugins/config/settings/config.class.php +++ b/lib/plugins/config/settings/config.class.php @@ -339,8 +339,7 @@ if (!class_exists('configuration')) { // the same for the active template if (@file_exists(tpl_incdir().$file)){ - $conf = array(); - @include(tpl_incdir().$file); + $conf = $this->_read_config(tpl_incdir().$file); foreach ($conf as $key => $value){ $default['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.$key] = $value; } -- cgit v1.2.3 From 1e2c59485b8396275abde11d047a4a42a4e4e335 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Tue, 26 Nov 2013 19:39:05 +0000 Subject: improved comments for code associated with PR#407 & PR#408 --- lib/exe/css.php | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/exe/css.php b/lib/exe/css.php index c2540cc03..c96dedd37 100644 --- a/lib/exe/css.php +++ b/lib/exe/css.php @@ -312,6 +312,11 @@ function css_styleini($tpl) { ); } +/** + * Amend paths used in replacement relative urls, refer FS#2879 + * + * @author Chris Smith + */ function css_fixreplacementurls($replacements, $location) { foreach($replacements as $key => $value) { $replacements[$key] = preg_replace('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#','\\1'.$location,$value); @@ -400,16 +405,29 @@ function css_loadfile($file,$location=''){ return $css_file->load($location); } +/** + * Helper class to abstract loading of css/less files + * + * @author Chris Smith + */ class DokuCssFile { - protected $filepath; - protected $location; + protected $filepath; // file system path to the CSS/Less file + protected $location; // base url location of the CSS/Less file private $relative_path = null; public function __construct($file) { $this->filepath = $file; } + /** + * Load the contents of the css/less file and adjust any relative paths/urls (relative to this file) to be + * relative to the dokuwiki root: the web root (DOKU_BASE) for most files; the file system root (DOKU_INC) + * for less files. + * + * @param string $location base url for this file + * @return string the CSS/Less contents of the file + */ public function load($location='') { if (!@file_exists($this->filepath)) return ''; @@ -424,10 +442,17 @@ class DokuCssFile { return $css; } + /** + * Get the relative file system path of this file, relative to dokuwiki's root folder, DOKU_INC + * + * @return string relative file system path + */ private function getRelativePath(){ if (is_null($this->relative_path)) { $basedir = array(DOKU_INC); + + // during testing, files may be found relative to a second base dir, TMP_DIR if (defined('DOKU_UNITTEST')) { $basedir[] = realpath(TMP_DIR); } @@ -439,16 +464,26 @@ class DokuCssFile { return $this->relative_path; } + /** + * preg_replace callback to adjust relative urls from relative to this file to relative + * to the appropriate dokuwiki root location as described in the code + * + * @param array see http://php.net/preg_replace_callback + * @return string see http://php.net/preg_replace_callback + */ public function replacements($match) { + // not a relative url? - no adjustment required if (preg_match('#^(/|data:|https?://)#',$match[3])) { return $match[0]; } + // a less file import? - requires a file system location else if (substr($match[3],-5) == '.less') { if ($match[3]{0} != '/') { $match[3] = $this->getRelativePath() . '/' . $match[3]; } } + // everything else requires a url adjustment else { $match[3] = $this->location . $match[3]; } -- cgit v1.2.3 From 77450f4001bc641f7a724ae5e5c2f71b44c022d1 Mon Sep 17 00:00:00 2001 From: lisps Date: Wed, 27 Nov 2013 09:38:06 +0100 Subject: media image can be resized by height (without width) --- lib/exe/fetch.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/exe/fetch.php b/lib/exe/fetch.php index 5967494bf..f33b3f2f8 100644 --- a/lib/exe/fetch.php +++ b/lib/exe/fetch.php @@ -78,8 +78,8 @@ if (defined('SIMPLE_TEST')) { unset($evt); //handle image resizing/cropping - if((substr($MIME, 0, 5) == 'image') && $WIDTH) { - if($HEIGHT) { + if((substr($MIME, 0, 5) == 'image') && ($WIDTH || $HEIGHT)) { + if($HEIGHT && $WDITH) { $data['file'] = $FILE = media_crop_image($data['file'], $EXT, $WIDTH, $HEIGHT); } else { $data['file'] = $FILE = media_resize_image($data['file'], $EXT, $WIDTH, $HEIGHT); -- cgit v1.2.3 From 32087ed0672a7921af76f92eb2e8d3b6e3a166de Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 28 Nov 2013 00:01:35 +0000 Subject: Bugfix: correct variable name to --- lib/plugins/usermanager/admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index c4d71cb22..f2ee95b38 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -830,7 +830,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { if (!$this->_auth->canDo('addUser')) return false; // check file uploaded ok. - if (empty($_FILES['import']['size']) || !empty($FILES['import']['error']) && is_uploaded_file($FILES['import']['tmp_name'])) { + if (empty($_FILES['import']['size']) || !empty($_FILES['import']['error']) && is_uploaded_file($_FILES['import']['tmp_name'])) { msg($this->lang['import_error_upload'],-1); return false; } -- cgit v1.2.3 From e73725bac6a3c60835092d4e2253730b7d683263 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 28 Nov 2013 00:03:48 +0000 Subject: IMPROVEMENT: remove generated password from import failure data --- lib/plugins/usermanager/admin.php | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index f2ee95b38..95524c56a 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -867,6 +867,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { $import_success_count++; } else { $import_fail_count++; + array_splice($raw, 1, 1); // remove the spliced in password $this->_import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv); } } -- cgit v1.2.3 From 5ba64050580b6936c8b364e3a288e7c875263c88 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 28 Nov 2013 00:04:20 +0000 Subject: MINOR: comment spelling corrections --- lib/plugins/usermanager/admin.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index 95524c56a..2c566723a 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -822,7 +822,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * csv file should have 4 columns, user_id, full name, email, groups (comma separated) * - * @return bool whether succesful + * @return bool whether successful */ protected function _import() { // check we are allowed to add users @@ -941,7 +941,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { * * @param array $user data of user * @param string &$error reference catched error message - * @return bool whether succesful + * @return bool whether successful */ protected function _addImportUser($user, & $error){ if (!$this->_auth->triggerUserMod('create', $user)) { -- cgit v1.2.3 From b2c01466e61a7800306d8705eada83563ca90a55 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 28 Nov 2013 00:08:52 +0000 Subject: Improvements to facilitate unit testing - don't die at end of _export() - internal classs wrapper method for is_uploaded_file() to allow overriding for use under cli & without having to upload a file --- lib/plugins/usermanager/admin.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index 2c566723a..782443ee1 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -814,6 +814,8 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { fputcsv($fd, $line); } fclose($fd); + if (defined('DOKU_UNITTEST')){ return; } + die; } @@ -830,7 +832,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { if (!$this->_auth->canDo('addUser')) return false; // check file uploaded ok. - if (empty($_FILES['import']['size']) || !empty($_FILES['import']['error']) && is_uploaded_file($_FILES['import']['tmp_name'])) { + if (empty($_FILES['import']['size']) || !empty($_FILES['import']['error']) && $this->_isUploadedFile($_FILES['import']['tmp_name'])) { msg($this->lang['import_error_upload'],-1); return false; } @@ -974,4 +976,11 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { die; } + /** + * wrapper for is_uploaded_file to facilitate overriding by test suite + */ + protected function _isUploadedFile($file) { + return is_uploaded_file($file); + } + } -- cgit v1.2.3 From ed6bf75f5a78a346e3c3192b2bab79450e206598 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 28 Nov 2013 00:12:38 +0000 Subject: Add unit tests for usermanager import & export functions --- lib/plugins/usermanager/_test/csv_export.test.php | 59 ++++++++ lib/plugins/usermanager/_test/csv_import.test.php | 155 ++++++++++++++++++++++ lib/plugins/usermanager/_test/mocks.class.php | 43 ++++++ 3 files changed, 257 insertions(+) create mode 100644 lib/plugins/usermanager/_test/csv_export.test.php create mode 100644 lib/plugins/usermanager/_test/csv_import.test.php create mode 100644 lib/plugins/usermanager/_test/mocks.class.php (limited to 'lib') diff --git a/lib/plugins/usermanager/_test/csv_export.test.php b/lib/plugins/usermanager/_test/csv_export.test.php new file mode 100644 index 000000000..d0942a861 --- /dev/null +++ b/lib/plugins/usermanager/_test/csv_export.test.php @@ -0,0 +1,59 @@ +usermanager = new admin_mock_usermanager(); + parent::setUp(); + } + + /** + * based on standard test user/conf setup + * + * users per _test/conf/users.auth.php + * expected to be: testuser:179ad45c6ce2cb97cf1029e212046e81:Arthur Dent:arthur@example.com + */ + function test_export() { + $expected = 'User,"Real Name",Email,Groups +testuser,"Arthur Dent",arthur@example.com, +'; + $this->assertEquals($expected, $this->usermanager->tryExport()); + } + + /** + * when configured to use a different locale, the column headings in the first line of the + * exported csv data should reflect the langauge strings of that locale + */ + function test_export_withlocale(){ + global $conf; + $old_conf = $conf; + $conf['lang'] = 'de'; + + $this->usermanager->localised = false; + $this->usermanager->setupLocale(); + + $conf = $old_conf; + + $expected = 'Benutzername,"Voller Name",E-Mail,Gruppen +testuser,"Arthur Dent",arthur@example.com, +'; + $this->assertEquals($expected, $this->usermanager->tryExport()); + } + + function test_export_withfilter(){ + $this->markTestIncomplete( + 'This test has not been implemented yet.' + ); + } + +} diff --git a/lib/plugins/usermanager/_test/csv_import.test.php b/lib/plugins/usermanager/_test/csv_import.test.php new file mode 100644 index 000000000..5deb201ba --- /dev/null +++ b/lib/plugins/usermanager/_test/csv_import.test.php @@ -0,0 +1,155 @@ +importfile = tempnam(TMP_DIR, 'csv'); + + $this->old_files = $_FILES; + $_FILES = array( + 'import' => array( + 'name' => 'import.csv', + 'tmp_name' => $this->importfile, + 'type' => 'text/plain', + 'size' => 1, + 'error' => 0, + ), + ); + + $this->usermanager = new admin_mock_usermanager(); + parent::setUp(); + } + + function tearDown() { + $_FILES = $this->old_files; + parent::tearDown(); + } + + function doImportTest($importCsv, $expectedResult, $expectedNewUsers, $expectedFailures) { + global $auth; + $before_users = $auth->retrieveUsers(); + + io_savefile($this->importfile, $importCsv); + $result = $this->usermanager->tryImport(); + + $after_users = $auth->retrieveUsers(); + $import_count = count($after_users) - count($before_users); + $new_users = array_diff_key($after_users, $before_users); + $diff_users = array_diff_assoc($after_users, $before_users); + + $expectedCount = count($expectedNewUsers); + + $this->assertEquals($expectedResult, $result); // import result as expected + $this->assertEquals($expectedCount, $import_count); // number of new users matches expected number imported + $this->assertEquals($expectedNewUsers, $this->stripPasswords($new_users)); // new user data matches imported user data + $this->assertEquals($expectedCount, $this->countPasswords($new_users)); // new users have a password + $this->assertEquals($expectedCount, $this->usermanager->mock_email_notifications_sent); // new users notified of their passwords + $this->assertEquals($new_users, $diff_users); // no other users were harmed in the testing of this import + $this->assertEquals($expectedFailures, $this->usermanager->getImportFailures()); // failures as expected + } + + function test_import() { + $csv = 'User,"Real Name",Email,Groups +importuser,"Ford Prefect",ford@example.com,user +'; + $expected = array( + 'importuser' => array( + 'name' => 'Ford Prefect', + 'mail' => 'ford@example.com', + 'grps' => array('user'), + ), + ); + + $this->doImportTest($csv, true, $expected, array()); + } + + function test_importExisting() { + $csv = 'User,"Real Name",Email,Groups +importuser,"Ford Prefect",ford@example.com,user +'; + $failures = array( + '2' => array( + 'error' => $this->usermanager->lang['import_error_create'], + 'user' => array( + 'importuser', + 'Ford Prefect', + 'ford@example.com', + 'user', + ), + 'orig' => 'importuser,"Ford Prefect",ford@example.com,user'.NL, + ), + ); + + $this->doImportTest($csv, true, array(), $failures); + } + + function test_importUtf8() { + $csv = 'User,"Real Name",Email,Groups +importutf8,"Førd Prefect",ford@example.com,user +'; + $expected = array( + 'importutf8' => array( + 'name' => 'Førd Prefect', + 'mail' => 'ford@example.com', + 'grps' => array('user'), + ), + ); + + $this->doImportTest($csv, true, $expected, array()); + } + + /** + * utf8: u+00F8 (ø) <=> 0xF8 :iso-8859-1 + */ + function test_importIso8859() { + $csv = 'User,"Real Name",Email,Groups +importiso8859,"F'.chr(0xF8).'rd Prefect",ford@example.com,user +'; + $expected = array( + 'importiso8859' => array( + 'name' => 'Førd Prefect', + 'mail' => 'ford@example.com', + 'grps' => array('user'), + ), + ); + + $this->doImportTest($csv, true, $expected, array()); + } + + private function stripPasswords($array){ + foreach ($array as $user => $data) { + unset($array[$user]['pass']); + } + return $array; + } + + private function countPasswords($array){ + $count = 0; + foreach ($array as $user => $data) { + if (!empty($data['pass'])) { + $count++; + } + } + return $count; + } + +} + diff --git a/lib/plugins/usermanager/_test/mocks.class.php b/lib/plugins/usermanager/_test/mocks.class.php new file mode 100644 index 000000000..edf5438b2 --- /dev/null +++ b/lib/plugins/usermanager/_test/mocks.class.php @@ -0,0 +1,43 @@ +_import_failures; + } + + public function tryExport() { + ob_start(); + $this->_export(); + return ob_get_clean(); + } + + public function tryImport() { + return $this->_import(); + } + + // no need to send email notifications (mostly) + protected function _notifyUser($user, $password, $status_alert=true) { + if ($this->mock_email_notifications) { + $this->mock_email_notifications_sent++; + return true; + } else { + return parent::_notifyUser($user, $password, $status_alert); + } + } + + protected function _isUploadedFile($file) { + return file_exists($file); + } +} + -- cgit v1.2.3 From 211955bef84071b025e83bdeeefe496a5002fdd8 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Thu, 28 Nov 2013 00:49:31 +0000 Subject: test import against auth plugin which doesn't allow adding users --- lib/plugins/usermanager/_test/csv_import.test.php | 18 +++++++++++++++++- lib/plugins/usermanager/_test/mocks.class.php | 7 +++++++ 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/usermanager/_test/csv_import.test.php b/lib/plugins/usermanager/_test/csv_import.test.php index 5deb201ba..1f0ee7436 100644 --- a/lib/plugins/usermanager/_test/csv_import.test.php +++ b/lib/plugins/usermanager/_test/csv_import.test.php @@ -47,7 +47,7 @@ class plugin_usermanager_csv_import_test extends DokuWikiTest { global $auth; $before_users = $auth->retrieveUsers(); - io_savefile($this->importfile, $importCsv); + io_savefile($this->importfile, $importCsv); $result = $this->usermanager->tryImport(); $after_users = $auth->retrieveUsers(); @@ -66,6 +66,22 @@ class plugin_usermanager_csv_import_test extends DokuWikiTest { $this->assertEquals($expectedFailures, $this->usermanager->getImportFailures()); // failures as expected } + function test_cantImport(){ + global $auth; + $oldauth = $auth; + + $auth = new auth_mock_authplain(); + $auth->setCanDo('addUser', false); + + $csv = 'User,"Real Name",Email,Groups +importuser,"Ford Prefect",ford@example.com,user +'; + + $this->doImportTest($csv, false, array(), array()); + + $auth = $oldauth; + } + function test_import() { $csv = 'User,"Real Name",Email,Groups importuser,"Ford Prefect",ford@example.com,user diff --git a/lib/plugins/usermanager/_test/mocks.class.php b/lib/plugins/usermanager/_test/mocks.class.php index edf5438b2..f3cc72c27 100644 --- a/lib/plugins/usermanager/_test/mocks.class.php +++ b/lib/plugins/usermanager/_test/mocks.class.php @@ -41,3 +41,10 @@ class admin_mock_usermanager extends admin_plugin_usermanager { } } +class auth_mock_authplain extends auth_plugin_authplain { + + public function setCanDo($op, $canDo) { + $this->cando[$op] = $canDo; + } + +} -- cgit v1.2.3 From 0d1370783bb8cfbdc2e1e347edb743fd0de590a2 Mon Sep 17 00:00:00 2001 From: chris taklis Date: Sat, 30 Nov 2013 19:05:55 +0100 Subject: translation update --- lib/plugins/authad/lang/el/settings.php | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 lib/plugins/authad/lang/el/settings.php (limited to 'lib') diff --git a/lib/plugins/authad/lang/el/settings.php b/lib/plugins/authad/lang/el/settings.php new file mode 100644 index 000000000..9bf23ea1c --- /dev/null +++ b/lib/plugins/authad/lang/el/settings.php @@ -0,0 +1,8 @@ + + */ +$lang['admin_password'] = 'Ο κωδικός του παραπάνω χρήστη.'; -- cgit v1.2.3 From d2a843c310418267d3baedd63547d75917da2efe Mon Sep 17 00:00:00 2001 From: Juliano Marconi Lanigra Date: Sat, 30 Nov 2013 23:10:58 +0100 Subject: translation update --- lib/plugins/authad/lang/pt-br/settings.php | 2 ++ lib/plugins/usermanager/lang/pt-br/lang.php | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'lib') diff --git a/lib/plugins/authad/lang/pt-br/settings.php b/lib/plugins/authad/lang/pt-br/settings.php index 76fb419a6..cdc748055 100644 --- a/lib/plugins/authad/lang/pt-br/settings.php +++ b/lib/plugins/authad/lang/pt-br/settings.php @@ -5,6 +5,7 @@ * * @author Victor Westmann * @author Frederico Guimarães + * @author Juliano Marconi Lanigra */ $lang['account_suffix'] = 'Sufixo de sua conta. Eg. @meu.domínio.org'; $lang['base_dn'] = 'Sua base DN. Eg. DC=meu,DC=domínio,DC=org'; @@ -12,6 +13,7 @@ $lang['domain_controllers'] = 'Uma lista de controles de domínios separada p $lang['admin_username'] = 'Um usuário do Active Directory com privilégios para acessar os dados de todos os outros usuários. Opcional, mas necessário para realizar certas ações, tais como enviar mensagens de assinatura.'; $lang['admin_password'] = 'A senha do usuário acima.'; $lang['sso'] = 'Usar Single-Sign-On através do Kerberos ou NTLM?'; +$lang['sso_charset'] = 'A codificação de caracteres que seu servidor web passará o nome de usuário Kerberos ou NTLM. Vazio para UTF-8 ou latin-1. Requere a extensão iconv.'; $lang['real_primarygroup'] = 'O grupo primário real deve ser resolvido ao invés de assumirmos como "Usuários do Domínio" (mais lento)'; $lang['use_ssl'] = 'Usar conexão SSL? Se usar, não habilitar TLS abaixo.'; $lang['use_tls'] = 'Usar conexão TLS? se usar, não habilitar SSL acima.'; diff --git a/lib/plugins/usermanager/lang/pt-br/lang.php b/lib/plugins/usermanager/lang/pt-br/lang.php index 9bb37742a..356d139eb 100644 --- a/lib/plugins/usermanager/lang/pt-br/lang.php +++ b/lib/plugins/usermanager/lang/pt-br/lang.php @@ -20,6 +20,7 @@ * @author Victor Westmann * @author Leone Lisboa Magevski * @author Dário Estevão + * @author Juliano Marconi Lanigra */ $lang['menu'] = 'Gerenciamento de Usuários'; $lang['noauth'] = '(o gerenciamento de usuários não está disponível)'; @@ -43,6 +44,7 @@ $lang['search_prompt'] = 'Executar a pesquisa'; $lang['clear'] = 'Limpar o filtro de pesquisa'; $lang['filter'] = 'Filtro'; $lang['export_all'] = 'Exportar Todos Usuários (CSV)'; +$lang['export_filtered'] = 'Exportar lista de Usuários Filtrados (CSV)'; $lang['import'] = 'Importar Novos Usuários'; $lang['line'] = 'Linha Nº.'; $lang['error'] = 'Mensagem de Erro'; @@ -66,6 +68,8 @@ $lang['add_ok'] = 'O usuário foi adicionado com sucesso'; $lang['add_fail'] = 'O usuário não foi adicionado'; $lang['notify_ok'] = 'O e-mail de notificação foi enviado'; $lang['notify_fail'] = 'Não foi possível enviar o e-mail de notificação'; +$lang['import_userlistcsv'] = 'Arquivo de lista de usuários (CSV):'; +$lang['import_header'] = 'Importações Mais Recentes - Falhas'; $lang['import_success_count'] = 'Importação de Usuário: %d usuário (s) encontrado (s), %d importado (s) com sucesso.'; $lang['import_failure_count'] = 'Importação de Usuário: %d falhou. As falhas estão listadas abaixo.'; $lang['import_error_fields'] = 'Campos insuficientes, encontrado (s) %d, necessário 4.'; @@ -75,3 +79,5 @@ $lang['import_error_badmail'] = 'Endereço de email errado'; $lang['import_error_upload'] = 'Falha na Importação: O arquivo csv não pode ser carregado ou está vazio.'; $lang['import_error_readfail'] = 'Falha na Importação: Habilitar para ler o arquivo a ser carregado.'; $lang['import_error_create'] = 'Habilitar para criar o usuário.'; +$lang['import_notify_fail'] = 'Mensagem de notificação não pode ser enviada para o usuário importado, %s com email %s.'; +$lang['import_downloadfailures'] = 'Falhas no Download como CSV para correção'; -- cgit v1.2.3 From c9454ee3a82b29418a7ee59f0bb35006ea6a7fb1 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Sun, 1 Dec 2013 16:23:02 +0000 Subject: Per FS#2884, implement a local version of str_getcsv() to maintain compatibility with php 5.2.x (str_getcsv() is only available in php 5.3+ and is used by user manager import feature. --- lib/plugins/usermanager/_test/csv_import.test.php | 14 ++++++++++++ lib/plugins/usermanager/_test/mocks.class.php | 8 +++++++ lib/plugins/usermanager/admin.php | 28 ++++++++++++++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/usermanager/_test/csv_import.test.php b/lib/plugins/usermanager/_test/csv_import.test.php index 1f0ee7436..5133c1256 100644 --- a/lib/plugins/usermanager/_test/csv_import.test.php +++ b/lib/plugins/usermanager/_test/csv_import.test.php @@ -150,6 +150,20 @@ importiso8859,"F'.chr(0xF8).'rd Prefect",ford@example.com,user $this->doImportTest($csv, true, $expected, array()); } + /** + * Verify usermanager::str_getcsv() behaves identically to php 5.3's str_getcsv() + * within the context/parameters required by _import() + * + * @requires PHP 5.3 + * @deprecated remove when dokuwiki requires 5.3+ + * also associated usermanager & mock usermanager access methods + */ + private function test_getcsvcompatibility() { + $line = 'importuser,"Ford Prefect",ford@example.com,user'.NL; + + $this->assertEquals(str_getcsv($line), $this->usermanager->access_str_getcsv($line)); + } + private function stripPasswords($array){ foreach ($array as $user => $data) { unset($array[$user]['pass']); diff --git a/lib/plugins/usermanager/_test/mocks.class.php b/lib/plugins/usermanager/_test/mocks.class.php index f3cc72c27..91c74768c 100644 --- a/lib/plugins/usermanager/_test/mocks.class.php +++ b/lib/plugins/usermanager/_test/mocks.class.php @@ -26,6 +26,14 @@ class admin_mock_usermanager extends admin_plugin_usermanager { return $this->_import(); } + /** + * @deprecated remove when dokuwiki requires php 5.3+ + * also associated unit test & usermanager methods + */ + public function access_str_getcsv($line){ + return $this->str_getcsv($line); + } + // no need to send email notifications (mostly) protected function _notifyUser($user, $password, $status_alert=true) { if ($this->mock_email_notifications) { diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index 782443ee1..156037f09 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -847,7 +847,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { if (!utf8_check($csv)) { $csv = utf8_encode($csv); } - $raw = str_getcsv($csv); + $raw = $this->_getcsv($csv); $error = ''; // clean out any errors from the previous line // data checks... if (1 == ++$line) { @@ -983,4 +983,30 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { return is_uploaded_file($file); } + /** + * wrapper for str_getcsv() to simplify maintaining compatibility with php 5.2 + * + * @deprecated remove when dokuwiki php requirement increases to 5.3+ + * also associated unit test & mock access method + */ + protected function _getcsv($csv) { + return function_exists('str_getcsv') ? str_getcsv($csv) : $this->str_getcsv($csv); + } + + /** + * replacement str_getcsv() function for php < 5.3 + * loosely based on www.php.net/str_getcsv#88311 + * + * @deprecated remove when dokuwiki php requirement increases to 5.3+ + */ + protected function str_getcsv($str) { + $fp = fopen("php://temp/maxmemory:1048576", 'r+'); // 1MiB + fputs($fp, $str); + rewind($fp); + + $data = fgetcsv($fp); + + fclose($fp); + return $data; + } } -- cgit v1.2.3 From 3946d21690c98d095fff4a0ad5be4c47c0230ed7 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Sun, 1 Dec 2013 16:44:37 +0000 Subject: comment (hide) incomplete export with filter test --- lib/plugins/usermanager/_test/csv_export.test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/plugins/usermanager/_test/csv_export.test.php b/lib/plugins/usermanager/_test/csv_export.test.php index d0942a861..667fc71dc 100644 --- a/lib/plugins/usermanager/_test/csv_export.test.php +++ b/lib/plugins/usermanager/_test/csv_export.test.php @@ -49,11 +49,11 @@ testuser,"Arthur Dent",arthur@example.com, '; $this->assertEquals($expected, $this->usermanager->tryExport()); } - +/* function test_export_withfilter(){ $this->markTestIncomplete( 'This test has not been implemented yet.' ); } - +*/ } -- cgit v1.2.3 From 1da08fca34cb20a1b12d83e70a1d915f66cf6438 Mon Sep 17 00:00:00 2001 From: Christopher Smith Date: Sun, 1 Dec 2013 16:45:53 +0000 Subject: remove incorrect 'private' restriction from tset method --- lib/plugins/usermanager/_test/csv_import.test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/usermanager/_test/csv_import.test.php b/lib/plugins/usermanager/_test/csv_import.test.php index 5133c1256..3968356bc 100644 --- a/lib/plugins/usermanager/_test/csv_import.test.php +++ b/lib/plugins/usermanager/_test/csv_import.test.php @@ -158,7 +158,7 @@ importiso8859,"F'.chr(0xF8).'rd Prefect",ford@example.com,user * @deprecated remove when dokuwiki requires 5.3+ * also associated usermanager & mock usermanager access methods */ - private function test_getcsvcompatibility() { + function test_getcsvcompatibility() { $line = 'importuser,"Ford Prefect",ford@example.com,user'.NL; $this->assertEquals(str_getcsv($line), $this->usermanager->access_str_getcsv($line)); -- cgit v1.2.3 From 6b1ab5ac63d5b5cb49c944d4ef20650977759a66 Mon Sep 17 00:00:00 2001 From: Antonio Bueno Date: Mon, 2 Dec 2013 01:21:32 +0100 Subject: translation update --- lib/plugins/authad/lang/es/settings.php | 2 ++ lib/plugins/authldap/lang/es/settings.php | 13 +++++++++++++ lib/plugins/authmysql/lang/es/settings.php | 12 ++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 lib/plugins/authldap/lang/es/settings.php create mode 100644 lib/plugins/authmysql/lang/es/settings.php (limited to 'lib') diff --git a/lib/plugins/authad/lang/es/settings.php b/lib/plugins/authad/lang/es/settings.php index 9d0aa80ac..98b78056b 100644 --- a/lib/plugins/authad/lang/es/settings.php +++ b/lib/plugins/authad/lang/es/settings.php @@ -4,6 +4,7 @@ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * * @author monica + * @author Antonio Bueno */ $lang['account_suffix'] = 'Su cuenta, sufijo. Ejem. @ my.domain.org '; $lang['base_dn'] = 'Su base DN. Ejem. DC=my,DC=dominio,DC=org'; @@ -11,3 +12,4 @@ $lang['domain_controllers'] = 'Una lista separada por coma de los controlador $lang['admin_username'] = 'Un usuario con privilegios de Active Directory con acceso a los datos de cualquier otro usuario. Opcional, pero es necesario para determinadas acciones como el envío de suscripciones de correos electrónicos.'; $lang['admin_password'] = 'La contraseña del usuario anterior.'; $lang['sso'] = 'En caso de inicio de sesión usará ¿Kerberos o NTLM?'; +$lang['sso_charset'] = 'La codificación con que tu servidor web pasará el nombre de usuario Kerberos o NTLM. Si es UTF-8 o latin-1 dejar en blanco. Requiere la extensión iconv.'; diff --git a/lib/plugins/authldap/lang/es/settings.php b/lib/plugins/authldap/lang/es/settings.php new file mode 100644 index 000000000..f8c3ad014 --- /dev/null +++ b/lib/plugins/authldap/lang/es/settings.php @@ -0,0 +1,13 @@ + + */ +$lang['starttls'] = 'Usar conexiones TLS?'; +$lang['debug'] = 'Mostrar información adicional para depuración de errores'; +$lang['deref_o_0'] = 'LDAP_DEREF_NEVER'; +$lang['deref_o_1'] = 'LDAP_DEREF_SEARCHING'; +$lang['deref_o_2'] = 'LDAP_DEREF_FINDING'; +$lang['deref_o_3'] = 'LDAP_DEREF_ALWAYS'; diff --git a/lib/plugins/authmysql/lang/es/settings.php b/lib/plugins/authmysql/lang/es/settings.php new file mode 100644 index 000000000..64d422102 --- /dev/null +++ b/lib/plugins/authmysql/lang/es/settings.php @@ -0,0 +1,12 @@ + + */ +$lang['server'] = 'Tu servidor MySQL'; +$lang['user'] = 'Nombre de usuario MySQL'; +$lang['database'] = 'Base de datos a usar'; +$lang['charset'] = 'Codificación usada en la base de datos'; +$lang['debug'] = 'Mostrar información adicional para depuración de errores'; -- cgit v1.2.3 From 2c01be2ff65c7adeb4e34cd2a507c910e84b79b7 Mon Sep 17 00:00:00 2001 From: zamroni Date: Tue, 3 Dec 2013 06:45:45 +0100 Subject: translation update --- lib/plugins/acl/lang/id/lang.php | 4 ++-- lib/plugins/plugin/lang/id/lang.php | 5 +++-- lib/plugins/usermanager/lang/id/lang.php | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/plugins/acl/lang/id/lang.php b/lib/plugins/acl/lang/id/lang.php index 650637635..6f619c5ec 100644 --- a/lib/plugins/acl/lang/id/lang.php +++ b/lib/plugins/acl/lang/id/lang.php @@ -1,8 +1,8 @@ * @author Yustinus Waruwu */ diff --git a/lib/plugins/plugin/lang/id/lang.php b/lib/plugins/plugin/lang/id/lang.php index f3a1fe4e6..2653b075e 100644 --- a/lib/plugins/plugin/lang/id/lang.php +++ b/lib/plugins/plugin/lang/id/lang.php @@ -1,7 +1,8 @@ * @author Yustinus Waruwu */ diff --git a/lib/plugins/usermanager/lang/id/lang.php b/lib/plugins/usermanager/lang/id/lang.php index 457ad4963..425b2ff59 100644 --- a/lib/plugins/usermanager/lang/id/lang.php +++ b/lib/plugins/usermanager/lang/id/lang.php @@ -1,7 +1,8 @@ * @author Yustinus Waruwu */ -- cgit v1.2.3 From 7c586cd898dec6fc85ce7817f134aa1b35fcb499 Mon Sep 17 00:00:00 2001 From: anjianshi Date: Thu, 5 Dec 2013 08:11:19 +0100 Subject: translation update --- lib/plugins/plugin/lang/zh/lang.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/plugins/plugin/lang/zh/lang.php b/lib/plugins/plugin/lang/zh/lang.php index f69410503..b39c6b063 100644 --- a/lib/plugins/plugin/lang/zh/lang.php +++ b/lib/plugins/plugin/lang/zh/lang.php @@ -15,6 +15,7 @@ * @author caii, patent agent in China * @author lainme993@gmail.com * @author Shuo-Ting Jian + * @author anjianshi */ $lang['menu'] = '插件管理器'; $lang['download'] = '下载并安装新的插件'; @@ -26,7 +27,7 @@ $lang['btn_settings'] = '设置'; $lang['btn_download'] = '下载'; $lang['btn_enable'] = '保存'; $lang['url'] = 'URL'; -$lang['installed'] = '已安装:'; +$lang['installed'] = '安装时间:'; $lang['lastupdate'] = '最后更新于:'; $lang['source'] = '来源:'; $lang['unknown'] = '未知'; -- cgit v1.2.3 From 6593db4300a3db6d88c9b09df725ecc8589e99b6 Mon Sep 17 00:00:00 2001 From: Myeongjin Date: Sat, 7 Dec 2013 02:01:38 +0100 Subject: translation update --- lib/plugins/acl/lang/ko/lang.php | 2 +- lib/plugins/authad/lang/ko/settings.php | 2 +- lib/plugins/plugin/lang/ko/lang.php | 14 +++++++------- lib/plugins/popularity/lang/ko/lang.php | 2 +- lib/plugins/usermanager/lang/ko/lang.php | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/plugins/acl/lang/ko/lang.php b/lib/plugins/acl/lang/ko/lang.php index 37cec307c..34b93a9f4 100644 --- a/lib/plugins/acl/lang/ko/lang.php +++ b/lib/plugins/acl/lang/ko/lang.php @@ -39,6 +39,6 @@ $lang['acl_perm1'] = '읽기'; $lang['acl_perm2'] = '편집'; $lang['acl_perm4'] = '만들기'; $lang['acl_perm8'] = '올리기'; -$lang['acl_perm16'] = '지우기'; +$lang['acl_perm16'] = '삭제'; $lang['acl_new'] = '새 항목 추가'; $lang['acl_mod'] = '항목 수정'; diff --git a/lib/plugins/authad/lang/ko/settings.php b/lib/plugins/authad/lang/ko/settings.php index 6c00950bf..b104371fe 100644 --- a/lib/plugins/authad/lang/ko/settings.php +++ b/lib/plugins/authad/lang/ko/settings.php @@ -13,7 +13,7 @@ $lang['admin_username'] = '다른 모든 사용자의 데이터에 접근 $lang['admin_password'] = '위 사용자의 비밀번호.'; $lang['sso'] = 'Kerberos나 NTLM을 통해 Single-Sign-On을 사용해야 합니까?'; $lang['sso_charset'] = '당신의 웹서버의 문자집합은 Kerberos나 NTLM 사용자 이름으로 전달됩니다. UTF-8이나 라린-1이 비어 있습니다. icov 확장 기능이 필요합니다.'; -$lang['real_primarygroup'] = '실제 기본 그룹은 "도메인 사용자"를 가정하는 대신 해결될 것입니다(느림)'; +$lang['real_primarygroup'] = '실제 기본 그룹은 "도메인 사용자"를 가정하는 대신 해결될 것입니다. (느림)'; $lang['use_ssl'] = 'SSL 연결을 사용합니까? 사용한다면 아래 TLS을 활성화하지 마세요.'; $lang['use_tls'] = 'TLS 연결을 사용합니까? 사용한다면 위 SSL을 활성화하지 마세요.'; $lang['debug'] = '오류에 대한 추가적인 디버그 정보를 보이겠습니까?'; diff --git a/lib/plugins/plugin/lang/ko/lang.php b/lib/plugins/plugin/lang/ko/lang.php index 8d2006672..4cd1ae3c7 100644 --- a/lib/plugins/plugin/lang/ko/lang.php +++ b/lib/plugins/plugin/lang/ko/lang.php @@ -34,16 +34,16 @@ $lang['deleted'] = '%s 플러그인이 삭제되었습니다.'; $lang['downloading'] = '다운로드 중 ...'; $lang['downloaded'] = '%s 플러그인이 성공적으로 설치되었습니다'; $lang['downloads'] = '다음 플러그인이 성공적으로 설치되었습니다:'; -$lang['download_none'] = '플러그인이 없거나 다운로드 또는 설치 중에 알 수 없는 문제가 발생하였습니다.'; +$lang['download_none'] = '플러그인이 없거나 다운로드 또는 설치 중에 알 수 없는 문제가 발생했습니다.'; $lang['plugin'] = '플러그인:'; $lang['components'] = '구성 요소'; $lang['noinfo'] = '이 플러그인은 어떤 정보도 없습니다. 잘못된 플러그인일 수 있습니다.'; -$lang['name'] = '이름: '; -$lang['date'] = '날짜: '; -$lang['type'] = '종류: '; -$lang['desc'] = '설명: '; -$lang['author'] = '저자: '; -$lang['www'] = '웹: '; +$lang['name'] = '이름:'; +$lang['date'] = '날짜:'; +$lang['type'] = '종류:'; +$lang['desc'] = '설명:'; +$lang['author'] = '저자:'; +$lang['www'] = '웹:'; $lang['error'] = '알 수 없는 문제가 발생했습니다.'; $lang['error_download'] = '플러그인 파일을 다운로드 할 수 없습니다: %s'; $lang['error_badurl'] = '잘못된 URL 같습니다 - URL에서 파일 이름을 알 수 없습니다'; diff --git a/lib/plugins/popularity/lang/ko/lang.php b/lib/plugins/popularity/lang/ko/lang.php index 088ef1dc9..f8cf4525d 100644 --- a/lib/plugins/popularity/lang/ko/lang.php +++ b/lib/plugins/popularity/lang/ko/lang.php @@ -11,7 +11,7 @@ * @author Myeongjin * @author Garam */ -$lang['name'] = '인기도 조사(불러오는 데 시간이 걸릴 수 있습니다)'; +$lang['name'] = '인기도 조사 (불러오는 데 시간이 걸릴 수 있습니다)'; $lang['submit'] = '자료 보내기'; $lang['autosubmit'] = '자료를 자동으로 한 달에 한 번씩 보내기'; $lang['submissionFailed'] = '다음과 같은 이유로 자료 보내기에 실패했습니다:'; diff --git a/lib/plugins/usermanager/lang/ko/lang.php b/lib/plugins/usermanager/lang/ko/lang.php index 7c629f74f..ac129c95e 100644 --- a/lib/plugins/usermanager/lang/ko/lang.php +++ b/lib/plugins/usermanager/lang/ko/lang.php @@ -33,8 +33,8 @@ $lang['search'] = '검색'; $lang['search_prompt'] = '검색 수행'; $lang['clear'] = '검색 필터 재설정'; $lang['filter'] = '필터'; -$lang['export_all'] = '모든 사용자 목록 내보내기(CSV)'; -$lang['export_filtered'] = '필터된 사용자 목록 내보내기(CSV)'; +$lang['export_all'] = '모든 사용자 목록 내보내기 (CSV)'; +$lang['export_filtered'] = '필터된 사용자 목록 내보내기 (CSV)'; $lang['import'] = '새 사용자 목록 가져오기'; $lang['line'] = '줄 번호'; $lang['error'] = '오류 메시지'; @@ -58,7 +58,7 @@ $lang['add_ok'] = '사용자를 성공적으로 추가했습니 $lang['add_fail'] = '사용자 추가를 실패했습니다'; $lang['notify_ok'] = '알림 이메일을 성공적으로 보냈습니다'; $lang['notify_fail'] = '알림 이메일을 보낼 수 없습니다'; -$lang['import_userlistcsv'] = '사용자 목록 파일(CSV):'; +$lang['import_userlistcsv'] = '사용자 목록 파일 (CSV):'; $lang['import_header'] = '가장 최근 가져오기 - 실패'; $lang['import_success_count'] = '사용자 가져오기: 사용자 %d명을 찾았고, %d명을 성공적으로 가져왔습니다.'; $lang['import_failure_count'] = '사용자 가져오기: %d명을 가져오지 못했습니다. 실패는 아래에 나타나 있습니다.'; @@ -69,5 +69,5 @@ $lang['import_error_badmail'] = '잘못된 이메일 주소'; $lang['import_error_upload'] = '가져오기를 실패했습니다. csv 파일을 올릴 수 없거나 비어 있습니다.'; $lang['import_error_readfail'] = '가져오기를 실패했습니다. 올린 파일을 읽을 수 없습니다.'; $lang['import_error_create'] = '사용자를 만들 수 없습니다.'; -$lang['import_notify_fail'] = '알림 메시지를 가져온 %s(이메일: %s) 사용자에게 보낼 수 없습니다.'; +$lang['import_notify_fail'] = '알림 메시지를 가져온 %s (이메일: %s) 사용자에게 보낼 수 없습니다.'; $lang['import_downloadfailures'] = '교정을 위한 CSV로 다운로드 실패'; -- cgit v1.2.3 From ccfec5606dae81e6524f6cfcdaca09d4cde7f111 Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Sat, 7 Dec 2013 23:10:05 +0000 Subject: crlf 2 lf whitespace fixes --- lib/plugins/authad/adLDAP/adLDAP.php | 1900 ++++++++++---------- .../authad/adLDAP/classes/adLDAPComputers.php | 304 ++-- .../authad/adLDAP/classes/adLDAPContacts.php | 588 +++--- .../authad/adLDAP/classes/adLDAPExchange.php | 778 ++++---- .../authad/adLDAP/classes/adLDAPFolders.php | 356 ++-- lib/plugins/authad/adLDAP/classes/adLDAPGroups.php | 1262 ++++++------- lib/plugins/authad/adLDAP/classes/adLDAPUsers.php | 1364 +++++++------- lib/plugins/authad/adLDAP/classes/adLDAPUtils.php | 526 +++--- .../authad/adLDAP/collections/adLDAPCollection.php | 274 +-- .../collections/adLDAPComputerCollection.php | 92 +- .../adLDAP/collections/adLDAPContactCollection.php | 92 +- .../adLDAP/collections/adLDAPGroupCollection.php | 92 +- .../adLDAP/collections/adLDAPUserCollection.php | 92 +- lib/scripts/jquery/jquery-migrate.js | 1022 +++++------ lib/scripts/jquery/jquery-migrate.min.js | 2 +- 15 files changed, 4372 insertions(+), 4372 deletions(-) (limited to 'lib') diff --git a/lib/plugins/authad/adLDAP/adLDAP.php b/lib/plugins/authad/adLDAP/adLDAP.php index a8f33b47e..c1f92abe2 100644 --- a/lib/plugins/authad/adLDAP/adLDAP.php +++ b/lib/plugins/authad/adLDAP/adLDAP.php @@ -1,951 +1,951 @@ -ldapConnection) { - return $this->ldapConnection; - } - return false; - } - - /** - * Get the bind status - * - * @return bool - */ - public function getLdapBind() { - return $this->ldapBind; - } - - /** - * Get the current base DN - * - * @return string - */ - public function getBaseDn() { - return $this->baseDn; - } - - /** - * The group class - * - * @var adLDAPGroups - */ - protected $groupClass; - - /** - * Get the group class interface - * - * @return adLDAPGroups - */ - public function group() { - if (!$this->groupClass) { - $this->groupClass = new adLDAPGroups($this); - } - return $this->groupClass; - } - - /** - * The user class - * - * @var adLDAPUsers - */ - protected $userClass; - - /** - * Get the userclass interface - * - * @return adLDAPUsers - */ - public function user() { - if (!$this->userClass) { - $this->userClass = new adLDAPUsers($this); - } - return $this->userClass; - } - - /** - * The folders class - * - * @var adLDAPFolders - */ - protected $folderClass; - - /** - * Get the folder class interface - * - * @return adLDAPFolders - */ - public function folder() { - if (!$this->folderClass) { - $this->folderClass = new adLDAPFolders($this); - } - return $this->folderClass; - } - - /** - * The utils class - * - * @var adLDAPUtils - */ - protected $utilClass; - - /** - * Get the utils class interface - * - * @return adLDAPUtils - */ - public function utilities() { - if (!$this->utilClass) { - $this->utilClass = new adLDAPUtils($this); - } - return $this->utilClass; - } - - /** - * The contacts class - * - * @var adLDAPContacts - */ - protected $contactClass; - - /** - * Get the contacts class interface - * - * @return adLDAPContacts - */ - public function contact() { - if (!$this->contactClass) { - $this->contactClass = new adLDAPContacts($this); - } - return $this->contactClass; - } - - /** - * The exchange class - * - * @var adLDAPExchange - */ - protected $exchangeClass; - - /** - * Get the exchange class interface - * - * @return adLDAPExchange - */ - public function exchange() { - if (!$this->exchangeClass) { - $this->exchangeClass = new adLDAPExchange($this); - } - return $this->exchangeClass; - } - - /** - * The computers class - * - * @var adLDAPComputers - */ - protected $computersClass; - - /** - * Get the computers class interface - * - * @return adLDAPComputers - */ - public function computer() { - if (!$this->computerClass) { - $this->computerClass = new adLDAPComputers($this); - } - return $this->computerClass; - } - - /** - * Getters and Setters - */ - - /** - * Set the account suffix - * - * @param string $accountSuffix - * @return void - */ - public function setAccountSuffix($accountSuffix) - { - $this->accountSuffix = $accountSuffix; - } - - /** - * Get the account suffix - * - * @return string - */ - public function getAccountSuffix() - { - return $this->accountSuffix; - } - - /** - * Set the domain controllers array - * - * @param array $domainControllers - * @return void - */ - public function setDomainControllers(array $domainControllers) - { - $this->domainControllers = $domainControllers; - } - - /** - * Get the list of domain controllers - * - * @return void - */ - public function getDomainControllers() - { - return $this->domainControllers; - } - - /** - * Sets the port number your domain controller communicates over - * - * @param int $adPort - */ - public function setPort($adPort) - { - $this->adPort = $adPort; - } - - /** - * Gets the port number your domain controller communicates over - * - * @return int - */ - public function getPort() - { - return $this->adPort; - } - - /** - * Set the username of an account with higher priviledges - * - * @param string $adminUsername - * @return void - */ - public function setAdminUsername($adminUsername) - { - $this->adminUsername = $adminUsername; - } - - /** - * Get the username of the account with higher priviledges - * - * This will throw an exception for security reasons - */ - public function getAdminUsername() - { - throw new adLDAPException('For security reasons you cannot access the domain administrator account details'); - } - - /** - * Set the password of an account with higher priviledges - * - * @param string $adminPassword - * @return void - */ - public function setAdminPassword($adminPassword) - { - $this->adminPassword = $adminPassword; - } - - /** - * Get the password of the account with higher priviledges - * - * This will throw an exception for security reasons - */ - public function getAdminPassword() - { - throw new adLDAPException('For security reasons you cannot access the domain administrator account details'); - } - - /** - * Set whether to detect the true primary group - * - * @param bool $realPrimaryGroup - * @return void - */ - public function setRealPrimaryGroup($realPrimaryGroup) - { - $this->realPrimaryGroup = $realPrimaryGroup; - } - - /** - * Get the real primary group setting - * - * @return bool - */ - public function getRealPrimaryGroup() - { - return $this->realPrimaryGroup; - } - - /** - * Set whether to use SSL - * - * @param bool $useSSL - * @return void - */ - public function setUseSSL($useSSL) - { - $this->useSSL = $useSSL; - // Set the default port correctly - if($this->useSSL) { - $this->setPort(self::ADLDAP_LDAPS_PORT); - } - else { - $this->setPort(self::ADLDAP_LDAP_PORT); - } - } - - /** - * Get the SSL setting - * - * @return bool - */ - public function getUseSSL() - { - return $this->useSSL; - } - - /** - * Set whether to use TLS - * - * @param bool $useTLS - * @return void - */ - public function setUseTLS($useTLS) - { - $this->useTLS = $useTLS; - } - - /** - * Get the TLS setting - * - * @return bool - */ - public function getUseTLS() - { - return $this->useTLS; - } - - /** - * Set whether to use SSO - * Requires ldap_sasl_bind support. Be sure --with-ldap-sasl is used when configuring PHP otherwise this function will be undefined. - * - * @param bool $useSSO - * @return void - */ - public function setUseSSO($useSSO) - { - if ($useSSO === true && !$this->ldapSaslSupported()) { - throw new adLDAPException('No LDAP SASL support for PHP. See: http://www.php.net/ldap_sasl_bind'); - } - $this->useSSO = $useSSO; - } - - /** - * Get the SSO setting - * - * @return bool - */ - public function getUseSSO() - { - return $this->useSSO; - } - - /** - * Set whether to lookup recursive groups - * - * @param bool $recursiveGroups - * @return void - */ - public function setRecursiveGroups($recursiveGroups) - { - $this->recursiveGroups = $recursiveGroups; - } - - /** - * Get the recursive groups setting - * - * @return bool - */ - public function getRecursiveGroups() - { - return $this->recursiveGroups; - } - - /** - * Default Constructor - * - * Tries to bind to the AD domain over LDAP or LDAPs - * - * @param array $options Array of options to pass to the constructor - * @throws Exception - if unable to bind to Domain Controller - * @return bool - */ - function __construct($options = array()) { - // You can specifically overide any of the default configuration options setup above - if (count($options) > 0) { - if (array_key_exists("account_suffix",$options)){ $this->accountSuffix = $options["account_suffix"]; } - if (array_key_exists("base_dn",$options)){ $this->baseDn = $options["base_dn"]; } - if (array_key_exists("domain_controllers",$options)){ - if (!is_array($options["domain_controllers"])) { - throw new adLDAPException('[domain_controllers] option must be an array'); - } - $this->domainControllers = $options["domain_controllers"]; - } - if (array_key_exists("admin_username",$options)){ $this->adminUsername = $options["admin_username"]; } - if (array_key_exists("admin_password",$options)){ $this->adminPassword = $options["admin_password"]; } - if (array_key_exists("real_primarygroup",$options)){ $this->realPrimaryGroup = $options["real_primarygroup"]; } - if (array_key_exists("use_ssl",$options)){ $this->setUseSSL($options["use_ssl"]); } - if (array_key_exists("use_tls",$options)){ $this->useTLS = $options["use_tls"]; } - if (array_key_exists("recursive_groups",$options)){ $this->recursiveGroups = $options["recursive_groups"]; } - if (array_key_exists("ad_port",$options)){ $this->setPort($options["ad_port"]); } - if (array_key_exists("sso",$options)) { - $this->setUseSSO($options["sso"]); - if (!$this->ldapSaslSupported()) { - $this->setUseSSO(false); - } - } - } - - if ($this->ldapSupported() === false) { - throw new adLDAPException('No LDAP support for PHP. See: http://www.php.net/ldap'); - } - - return $this->connect(); - } - - /** - * Default Destructor - * - * Closes the LDAP connection - * - * @return void - */ - function __destruct() { - $this->close(); - } - - /** - * Connects and Binds to the Domain Controller - * - * @return bool - */ - public function connect() - { - // Connect to the AD/LDAP server as the username/password - $domainController = $this->randomController(); - if ($this->useSSL) { - $this->ldapConnection = ldap_connect("ldaps://" . $domainController, $this->adPort); - } else { - $this->ldapConnection = ldap_connect($domainController, $this->adPort); - } - - // Set some ldap options for talking to AD - ldap_set_option($this->ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3); - ldap_set_option($this->ldapConnection, LDAP_OPT_REFERRALS, 0); - - if ($this->useTLS) { - ldap_start_tls($this->ldapConnection); - } - - // Bind as a domain admin if they've set it up - if ($this->adminUsername !== NULL && $this->adminPassword !== NULL) { - $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix, $this->adminPassword); - if (!$this->ldapBind) { - if ($this->useSSL && !$this->useTLS) { - // If you have problems troubleshooting, remove the @ character from the ldapldapBind command above to get the actual error message - throw new adLDAPException('Bind to Active Directory failed. Either the LDAPs connection failed or the login credentials are incorrect. AD said: ' . $this->getLastError()); - } - else { - throw new adLDAPException('Bind to Active Directory failed. Check the login credentials and/or server details. AD said: ' . $this->getLastError()); - } - } - } - if ($this->useSSO && $_SERVER['REMOTE_USER'] && $this->adminUsername === null && $_SERVER['KRB5CCNAME']) { - putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']); - $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI"); - if (!$this->ldapBind){ - throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError()); - } - else { - return true; - } - } - - - if ($this->baseDn == NULL) { - $this->baseDn = $this->findBaseDn(); - } - - return true; - } - - /** - * Closes the LDAP connection - * - * @return void - */ - public function close() { - if ($this->ldapConnection) { - @ldap_close($this->ldapConnection); - } - } - - /** - * Validate a user's login credentials - * - * @param string $username A user's AD username - * @param string $password A user's AD password - * @param bool optional $preventRebind - * @return bool - */ - public function authenticate($username, $password, $preventRebind = false) { - // Prevent null binding - if ($username === NULL || $password === NULL) { return false; } - if (empty($username) || empty($password)) { return false; } - - // Allow binding over SSO for Kerberos - if ($this->useSSO && $_SERVER['REMOTE_USER'] && $_SERVER['REMOTE_USER'] == $username && $this->adminUsername === NULL && $_SERVER['KRB5CCNAME']) { - putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']); - $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI"); - if (!$this->ldapBind) { - throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError()); - } - else { - return true; - } - } - - // Bind as the user - $ret = true; - $this->ldapBind = @ldap_bind($this->ldapConnection, $username . $this->accountSuffix, $password); - if (!$this->ldapBind){ - $ret = false; - } - - // Cnce we've checked their details, kick back into admin mode if we have it - if ($this->adminUsername !== NULL && !$preventRebind) { - $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix , $this->adminPassword); - if (!$this->ldapBind){ - // This should never happen in theory - throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError()); - } - } - - return $ret; - } - - /** - * Find the Base DN of your domain controller - * - * @return string - */ - public function findBaseDn() - { - $namingContext = $this->getRootDse(array('defaultnamingcontext')); - return $namingContext[0]['defaultnamingcontext'][0]; - } - - /** - * Get the RootDSE properties from a domain controller - * - * @param array $attributes The attributes you wish to query e.g. defaultnamingcontext - * @return array - */ - public function getRootDse($attributes = array("*", "+")) { - if (!$this->ldapBind){ return (false); } - - $sr = @ldap_read($this->ldapConnection, NULL, 'objectClass=*', $attributes); - $entries = @ldap_get_entries($this->ldapConnection, $sr); - return $entries; - } - - /** - * Get last error from Active Directory - * - * This function gets the last message from Active Directory - * This may indeed be a 'Success' message but if you get an unknown error - * it might be worth calling this function to see what errors were raised - * - * return string - */ - public function getLastError() { - return @ldap_error($this->ldapConnection); - } - - /** - * Detect LDAP support in php - * - * @return bool - */ - protected function ldapSupported() - { - if (!function_exists('ldap_connect')) { - return false; - } - return true; - } - - /** - * Detect ldap_sasl_bind support in PHP - * - * @return bool - */ - protected function ldapSaslSupported() - { - if (!function_exists('ldap_sasl_bind')) { - return false; - } - return true; - } - - /** - * Schema - * - * @param array $attributes Attributes to be queried - * @return array - */ - public function adldap_schema($attributes){ - - // LDAP doesn't like NULL attributes, only set them if they have values - // If you wish to remove an attribute you should set it to a space - // TO DO: Adapt user_modify to use ldap_mod_delete to remove a NULL attribute - $mod=array(); - - // Check every attribute to see if it contains 8bit characters and then UTF8 encode them - array_walk($attributes, array($this, 'encode8bit')); - - if ($attributes["address_city"]){ $mod["l"][0]=$attributes["address_city"]; } - if ($attributes["address_code"]){ $mod["postalCode"][0]=$attributes["address_code"]; } - //if ($attributes["address_country"]){ $mod["countryCode"][0]=$attributes["address_country"]; } // use country codes? - if ($attributes["address_country"]){ $mod["c"][0]=$attributes["address_country"]; } - if ($attributes["address_pobox"]){ $mod["postOfficeBox"][0]=$attributes["address_pobox"]; } - if ($attributes["address_state"]){ $mod["st"][0]=$attributes["address_state"]; } - if ($attributes["address_street"]){ $mod["streetAddress"][0]=$attributes["address_street"]; } - if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; } - if ($attributes["change_password"]){ $mod["pwdLastSet"][0]=0; } - if ($attributes["department"]){ $mod["department"][0]=$attributes["department"]; } - if ($attributes["description"]){ $mod["description"][0]=$attributes["description"]; } - if ($attributes["display_name"]){ $mod["displayName"][0]=$attributes["display_name"]; } - if ($attributes["email"]){ $mod["mail"][0]=$attributes["email"]; } - if ($attributes["expires"]){ $mod["accountExpires"][0]=$attributes["expires"]; } //unix epoch format? - if ($attributes["firstname"]){ $mod["givenName"][0]=$attributes["firstname"]; } - if ($attributes["home_directory"]){ $mod["homeDirectory"][0]=$attributes["home_directory"]; } - if ($attributes["home_drive"]){ $mod["homeDrive"][0]=$attributes["home_drive"]; } - if ($attributes["initials"]){ $mod["initials"][0]=$attributes["initials"]; } - if ($attributes["logon_name"]){ $mod["userPrincipalName"][0]=$attributes["logon_name"]; } - if ($attributes["manager"]){ $mod["manager"][0]=$attributes["manager"]; } //UNTESTED ***Use DistinguishedName*** - if ($attributes["office"]){ $mod["physicalDeliveryOfficeName"][0]=$attributes["office"]; } - if ($attributes["password"]){ $mod["unicodePwd"][0]=$this->user()->encodePassword($attributes["password"]); } - if ($attributes["profile_path"]){ $mod["profilepath"][0]=$attributes["profile_path"]; } - if ($attributes["script_path"]){ $mod["scriptPath"][0]=$attributes["script_path"]; } - if ($attributes["surname"]){ $mod["sn"][0]=$attributes["surname"]; } - if ($attributes["title"]){ $mod["title"][0]=$attributes["title"]; } - if ($attributes["telephone"]){ $mod["telephoneNumber"][0]=$attributes["telephone"]; } - if ($attributes["mobile"]){ $mod["mobile"][0]=$attributes["mobile"]; } - if ($attributes["pager"]){ $mod["pager"][0]=$attributes["pager"]; } - if ($attributes["ipphone"]){ $mod["ipphone"][0]=$attributes["ipphone"]; } - if ($attributes["web_page"]){ $mod["wWWHomePage"][0]=$attributes["web_page"]; } - if ($attributes["fax"]){ $mod["facsimileTelephoneNumber"][0]=$attributes["fax"]; } - if ($attributes["enabled"]){ $mod["userAccountControl"][0]=$attributes["enabled"]; } - if ($attributes["homephone"]){ $mod["homephone"][0]=$attributes["homephone"]; } - - // Distribution List specific schema - if ($attributes["group_sendpermission"]){ $mod["dlMemSubmitPerms"][0]=$attributes["group_sendpermission"]; } - if ($attributes["group_rejectpermission"]){ $mod["dlMemRejectPerms"][0]=$attributes["group_rejectpermission"]; } - - // Exchange Schema - if ($attributes["exchange_homemdb"]){ $mod["homeMDB"][0]=$attributes["exchange_homemdb"]; } - if ($attributes["exchange_mailnickname"]){ $mod["mailNickname"][0]=$attributes["exchange_mailnickname"]; } - if ($attributes["exchange_proxyaddress"]){ $mod["proxyAddresses"][0]=$attributes["exchange_proxyaddress"]; } - if ($attributes["exchange_usedefaults"]){ $mod["mDBUseDefaults"][0]=$attributes["exchange_usedefaults"]; } - if ($attributes["exchange_policyexclude"]){ $mod["msExchPoliciesExcluded"][0]=$attributes["exchange_policyexclude"]; } - if ($attributes["exchange_policyinclude"]){ $mod["msExchPoliciesIncluded"][0]=$attributes["exchange_policyinclude"]; } - if ($attributes["exchange_addressbook"]){ $mod["showInAddressBook"][0]=$attributes["exchange_addressbook"]; } - if ($attributes["exchange_altrecipient"]){ $mod["altRecipient"][0]=$attributes["exchange_altrecipient"]; } - if ($attributes["exchange_deliverandredirect"]){ $mod["deliverAndRedirect"][0]=$attributes["exchange_deliverandredirect"]; } - - // This schema is designed for contacts - if ($attributes["exchange_hidefromlists"]){ $mod["msExchHideFromAddressLists"][0]=$attributes["exchange_hidefromlists"]; } - if ($attributes["contact_email"]){ $mod["targetAddress"][0]=$attributes["contact_email"]; } - - //echo ("
    "); print_r($mod);
    -        /*
    -        // modifying a name is a bit fiddly
    -        if ($attributes["firstname"] && $attributes["surname"]){
    -            $mod["cn"][0]=$attributes["firstname"]." ".$attributes["surname"];
    -            $mod["displayname"][0]=$attributes["firstname"]." ".$attributes["surname"];
    -            $mod["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
    -        }
    -        */
    -
    -        if (count($mod)==0){ return (false); }
    -        return ($mod);
    -    }
    -    
    -    /**
    -    * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
    -    */
    -    protected function encode8Bit(&$item, $key) {
    -        $encode = false;
    -        if (is_string($item)) {
    -            for ($i=0; $i> 7) {
    -                    $encode = true;
    -                }
    -            }
    -        }
    -        if ($encode === true && $key != 'password') {
    -            $item = utf8_encode($item);   
    -        }
    -    }
    -    
    -    /**
    -    * Select a random domain controller from your domain controller array
    -    * 
    -    * @return string
    -    */
    -    protected function randomController() 
    -    {
    -        mt_srand(doubleval(microtime()) * 100000000); // For older PHP versions
    -        /*if (sizeof($this->domainControllers) > 1) {
    -            $adController = $this->domainControllers[array_rand($this->domainControllers)]; 
    -            // Test if the controller is responding to pings
    -            $ping = $this->pingController($adController); 
    -            if ($ping === false) { 
    -                // Find the current key in the domain controllers array
    -                $key = array_search($adController, $this->domainControllers);
    -                // Remove it so that we don't end up in a recursive loop
    -                unset($this->domainControllers[$key]);
    -                // Select a new controller
    -                return $this->randomController(); 
    -            }
    -            else { 
    -                return ($adController); 
    -            }
    -        } */
    -        return $this->domainControllers[array_rand($this->domainControllers)];
    -    }  
    -    
    -    /** 
    -    * Test basic connectivity to controller 
    -    * 
    -    * @return bool
    -    */ 
    -    protected function pingController($host) {
    -        $port = $this->adPort; 
    -        fsockopen($host, $port, $errno, $errstr, 10); 
    -        if ($errno > 0) {
    -            return false;
    -        }
    -        return true;
    -    }
    -
    -}
    -
    -/**
    -* adLDAP Exception Handler
    -* 
    -* Exceptions of this type are thrown on bind failure or when SSL is required but not configured
    -* Example:
    -* try {
    -*   $adldap = new adLDAP();
    -* }
    -* catch (adLDAPException $e) {
    -*   echo $e;
    -*   exit();
    -* }
    -*/
    -class adLDAPException extends Exception {}
    -
    +ldapConnection) {
    +            return $this->ldapConnection;   
    +        }
    +        return false;
    +    }
    +    
    +    /**
    +    * Get the bind status
    +    * 
    +    * @return bool
    +    */
    +    public function getLdapBind() {
    +        return $this->ldapBind;
    +    }
    +    
    +    /**
    +    * Get the current base DN
    +    * 
    +    * @return string
    +    */
    +    public function getBaseDn() {
    +        return $this->baseDn;   
    +    }
    +    
    +    /**
    +    * The group class
    +    * 
    +    * @var adLDAPGroups
    +    */
    +    protected $groupClass;
    +    
    +    /**
    +    * Get the group class interface
    +    * 
    +    * @return adLDAPGroups
    +    */
    +    public function group() {
    +        if (!$this->groupClass) {
    +            $this->groupClass = new adLDAPGroups($this);
    +        }   
    +        return $this->groupClass;
    +    }
    +    
    +    /**
    +    * The user class
    +    * 
    +    * @var adLDAPUsers
    +    */
    +    protected $userClass;
    +    
    +    /**
    +    * Get the userclass interface
    +    * 
    +    * @return adLDAPUsers
    +    */
    +    public function user() {
    +        if (!$this->userClass) {
    +            $this->userClass = new adLDAPUsers($this);
    +        }   
    +        return $this->userClass;
    +    }
    +    
    +    /**
    +    * The folders class
    +    * 
    +    * @var adLDAPFolders
    +    */
    +    protected $folderClass;
    +    
    +    /**
    +    * Get the folder class interface
    +    * 
    +    * @return adLDAPFolders
    +    */
    +    public function folder() {
    +        if (!$this->folderClass) {
    +            $this->folderClass = new adLDAPFolders($this);
    +        }   
    +        return $this->folderClass;
    +    }
    +    
    +    /**
    +    * The utils class
    +    * 
    +    * @var adLDAPUtils
    +    */
    +    protected $utilClass;
    +    
    +    /**
    +    * Get the utils class interface
    +    * 
    +    * @return adLDAPUtils
    +    */
    +    public function utilities() {
    +        if (!$this->utilClass) {
    +            $this->utilClass = new adLDAPUtils($this);
    +        }   
    +        return $this->utilClass;
    +    }
    +    
    +    /**
    +    * The contacts class
    +    * 
    +    * @var adLDAPContacts
    +    */
    +    protected $contactClass;
    +    
    +    /**
    +    * Get the contacts class interface
    +    * 
    +    * @return adLDAPContacts
    +    */
    +    public function contact() {
    +        if (!$this->contactClass) {
    +            $this->contactClass = new adLDAPContacts($this);
    +        }   
    +        return $this->contactClass;
    +    }
    +    
    +    /**
    +    * The exchange class
    +    * 
    +    * @var adLDAPExchange
    +    */
    +    protected $exchangeClass;
    +    
    +    /**
    +    * Get the exchange class interface
    +    * 
    +    * @return adLDAPExchange
    +    */
    +    public function exchange() {
    +        if (!$this->exchangeClass) {
    +            $this->exchangeClass = new adLDAPExchange($this);
    +        }   
    +        return $this->exchangeClass;
    +    }
    +    
    +    /**
    +    * The computers class
    +    * 
    +    * @var adLDAPComputers
    +    */
    +    protected $computersClass;
    +    
    +    /**
    +    * Get the computers class interface
    +    * 
    +    * @return adLDAPComputers
    +    */
    +    public function computer() {
    +        if (!$this->computerClass) {
    +            $this->computerClass = new adLDAPComputers($this);
    +        }   
    +        return $this->computerClass;
    +    }
    +
    +    /**
    +    * Getters and Setters
    +    */
    +    
    +    /**
    +    * Set the account suffix
    +    * 
    +    * @param string $accountSuffix
    +    * @return void
    +    */
    +    public function setAccountSuffix($accountSuffix)
    +    {
    +          $this->accountSuffix = $accountSuffix;
    +    }
    +
    +    /**
    +    * Get the account suffix
    +    * 
    +    * @return string
    +    */
    +    public function getAccountSuffix()
    +    {
    +          return $this->accountSuffix;
    +    }
    +    
    +    /**
    +    * Set the domain controllers array
    +    * 
    +    * @param array $domainControllers
    +    * @return void
    +    */
    +    public function setDomainControllers(array $domainControllers)
    +    {
    +          $this->domainControllers = $domainControllers;
    +    }
    +
    +    /**
    +    * Get the list of domain controllers
    +    * 
    +    * @return void
    +    */
    +    public function getDomainControllers()
    +    {
    +          return $this->domainControllers;
    +    }
    +    
    +    /**
    +    * Sets the port number your domain controller communicates over
    +    * 
    +    * @param int $adPort
    +    */
    +    public function setPort($adPort) 
    +    { 
    +        $this->adPort = $adPort; 
    +    } 
    +    
    +    /**
    +    * Gets the port number your domain controller communicates over
    +    * 
    +    * @return int
    +    */
    +    public function getPort() 
    +    { 
    +        return $this->adPort; 
    +    } 
    +    
    +    /**
    +    * Set the username of an account with higher priviledges
    +    * 
    +    * @param string $adminUsername
    +    * @return void
    +    */
    +    public function setAdminUsername($adminUsername)
    +    {
    +          $this->adminUsername = $adminUsername;
    +    }
    +
    +    /**
    +    * Get the username of the account with higher priviledges
    +    * 
    +    * This will throw an exception for security reasons
    +    */
    +    public function getAdminUsername()
    +    {
    +          throw new adLDAPException('For security reasons you cannot access the domain administrator account details');
    +    }
    +    
    +    /**
    +    * Set the password of an account with higher priviledges
    +    * 
    +    * @param string $adminPassword
    +    * @return void
    +    */
    +    public function setAdminPassword($adminPassword)
    +    {
    +          $this->adminPassword = $adminPassword;
    +    }
    +
    +    /**
    +    * Get the password of the account with higher priviledges
    +    * 
    +    * This will throw an exception for security reasons
    +    */
    +    public function getAdminPassword()
    +    {
    +          throw new adLDAPException('For security reasons you cannot access the domain administrator account details');
    +    }
    +    
    +    /**
    +    * Set whether to detect the true primary group
    +    * 
    +    * @param bool $realPrimaryGroup
    +    * @return void
    +    */
    +    public function setRealPrimaryGroup($realPrimaryGroup)
    +    {
    +          $this->realPrimaryGroup = $realPrimaryGroup;
    +    }
    +
    +    /**
    +    * Get the real primary group setting
    +    * 
    +    * @return bool
    +    */
    +    public function getRealPrimaryGroup()
    +    {
    +          return $this->realPrimaryGroup;
    +    }
    +    
    +    /**
    +    * Set whether to use SSL
    +    * 
    +    * @param bool $useSSL
    +    * @return void
    +    */
    +    public function setUseSSL($useSSL)
    +    {
    +          $this->useSSL = $useSSL;
    +          // Set the default port correctly 
    +          if($this->useSSL) { 
    +            $this->setPort(self::ADLDAP_LDAPS_PORT); 
    +          }
    +          else { 
    +            $this->setPort(self::ADLDAP_LDAP_PORT); 
    +          } 
    +    }
    +
    +    /**
    +    * Get the SSL setting
    +    * 
    +    * @return bool
    +    */
    +    public function getUseSSL()
    +    {
    +          return $this->useSSL;
    +    }
    +    
    +    /**
    +    * Set whether to use TLS
    +    * 
    +    * @param bool $useTLS
    +    * @return void
    +    */
    +    public function setUseTLS($useTLS)
    +    {
    +          $this->useTLS = $useTLS;
    +    }
    +
    +    /**
    +    * Get the TLS setting
    +    * 
    +    * @return bool
    +    */
    +    public function getUseTLS()
    +    {
    +          return $this->useTLS;
    +    }
    +    
    +    /**
    +    * Set whether to use SSO
    +    * Requires ldap_sasl_bind support. Be sure --with-ldap-sasl is used when configuring PHP otherwise this function will be undefined. 
    +    * 
    +    * @param bool $useSSO
    +    * @return void
    +    */
    +    public function setUseSSO($useSSO)
    +    {
    +          if ($useSSO === true && !$this->ldapSaslSupported()) {
    +              throw new adLDAPException('No LDAP SASL support for PHP.  See: http://www.php.net/ldap_sasl_bind');
    +          }
    +          $this->useSSO = $useSSO;
    +    }
    +
    +    /**
    +    * Get the SSO setting
    +    * 
    +    * @return bool
    +    */
    +    public function getUseSSO()
    +    {
    +          return $this->useSSO;
    +    }
    +    
    +    /**
    +    * Set whether to lookup recursive groups
    +    * 
    +    * @param bool $recursiveGroups
    +    * @return void
    +    */
    +    public function setRecursiveGroups($recursiveGroups)
    +    {
    +          $this->recursiveGroups = $recursiveGroups;
    +    }
    +
    +    /**
    +    * Get the recursive groups setting
    +    * 
    +    * @return bool
    +    */
    +    public function getRecursiveGroups()
    +    {
    +          return $this->recursiveGroups;
    +    }
    +
    +    /**
    +    * Default Constructor
    +    * 
    +    * Tries to bind to the AD domain over LDAP or LDAPs
    +    * 
    +    * @param array $options Array of options to pass to the constructor
    +    * @throws Exception - if unable to bind to Domain Controller
    +    * @return bool
    +    */
    +    function __construct($options = array()) {
    +        // You can specifically overide any of the default configuration options setup above
    +        if (count($options) > 0) {
    +            if (array_key_exists("account_suffix",$options)){ $this->accountSuffix = $options["account_suffix"]; }
    +            if (array_key_exists("base_dn",$options)){ $this->baseDn = $options["base_dn"]; }
    +            if (array_key_exists("domain_controllers",$options)){ 
    +                if (!is_array($options["domain_controllers"])) { 
    +                    throw new adLDAPException('[domain_controllers] option must be an array');
    +                }
    +                $this->domainControllers = $options["domain_controllers"]; 
    +            }
    +            if (array_key_exists("admin_username",$options)){ $this->adminUsername = $options["admin_username"]; }
    +            if (array_key_exists("admin_password",$options)){ $this->adminPassword = $options["admin_password"]; }
    +            if (array_key_exists("real_primarygroup",$options)){ $this->realPrimaryGroup = $options["real_primarygroup"]; }
    +            if (array_key_exists("use_ssl",$options)){ $this->setUseSSL($options["use_ssl"]); }
    +            if (array_key_exists("use_tls",$options)){ $this->useTLS = $options["use_tls"]; }
    +            if (array_key_exists("recursive_groups",$options)){ $this->recursiveGroups = $options["recursive_groups"]; }
    +            if (array_key_exists("ad_port",$options)){ $this->setPort($options["ad_port"]); } 
    +            if (array_key_exists("sso",$options)) { 
    +                $this->setUseSSO($options["sso"]);
    +                if (!$this->ldapSaslSupported()) {
    +                    $this->setUseSSO(false);
    +                }
    +            } 
    +        }
    +        
    +        if ($this->ldapSupported() === false) {
    +            throw new adLDAPException('No LDAP support for PHP.  See: http://www.php.net/ldap');
    +        }
    +
    +        return $this->connect();
    +    }
    +
    +    /**
    +    * Default Destructor
    +    * 
    +    * Closes the LDAP connection
    +    * 
    +    * @return void
    +    */
    +    function __destruct() { 
    +        $this->close(); 
    +    }
    +
    +    /**
    +    * Connects and Binds to the Domain Controller
    +    * 
    +    * @return bool
    +    */
    +    public function connect() 
    +    {
    +        // Connect to the AD/LDAP server as the username/password
    +        $domainController = $this->randomController();
    +        if ($this->useSSL) {
    +            $this->ldapConnection = ldap_connect("ldaps://" . $domainController, $this->adPort);
    +        } else {
    +            $this->ldapConnection = ldap_connect($domainController, $this->adPort);
    +        }
    +               
    +        // Set some ldap options for talking to AD
    +        ldap_set_option($this->ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
    +        ldap_set_option($this->ldapConnection, LDAP_OPT_REFERRALS, 0);
    +        
    +        if ($this->useTLS) {
    +            ldap_start_tls($this->ldapConnection);
    +        }
    +               
    +        // Bind as a domain admin if they've set it up
    +        if ($this->adminUsername !== NULL && $this->adminPassword !== NULL) {
    +            $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix, $this->adminPassword);
    +            if (!$this->ldapBind) {
    +                if ($this->useSSL && !$this->useTLS) {
    +                    // If you have problems troubleshooting, remove the @ character from the ldapldapBind command above to get the actual error message
    +                    throw new adLDAPException('Bind to Active Directory failed. Either the LDAPs connection failed or the login credentials are incorrect. AD said: ' . $this->getLastError());
    +                }
    +                else {
    +                    throw new adLDAPException('Bind to Active Directory failed. Check the login credentials and/or server details. AD said: ' . $this->getLastError());
    +                }
    +            }
    +        }
    +        if ($this->useSSO && $_SERVER['REMOTE_USER'] && $this->adminUsername === null && $_SERVER['KRB5CCNAME']) {
    +            putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);  
    +            $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI"); 
    +            if (!$this->ldapBind){ 
    +                throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError()); 
    +            }
    +            else {
    +                return true;
    +            }
    +        }
    +                
    +        
    +        if ($this->baseDn == NULL) {
    +            $this->baseDn = $this->findBaseDn();   
    +        }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Closes the LDAP connection
    +    * 
    +    * @return void
    +    */
    +    public function close() {
    +        if ($this->ldapConnection) {
    +            @ldap_close($this->ldapConnection);
    +        }
    +    }
    +    
    +    /**
    +    * Validate a user's login credentials
    +    * 
    +    * @param string $username A user's AD username
    +    * @param string $password A user's AD password
    +    * @param bool optional $preventRebind
    +    * @return bool
    +    */
    +    public function authenticate($username, $password, $preventRebind = false) {
    +        // Prevent null binding
    +        if ($username === NULL || $password === NULL) { return false; } 
    +        if (empty($username) || empty($password)) { return false; }
    +        
    +        // Allow binding over SSO for Kerberos
    +        if ($this->useSSO && $_SERVER['REMOTE_USER'] && $_SERVER['REMOTE_USER'] == $username && $this->adminUsername === NULL && $_SERVER['KRB5CCNAME']) { 
    +            putenv("KRB5CCNAME=" . $_SERVER['KRB5CCNAME']);
    +            $this->ldapBind = @ldap_sasl_bind($this->ldapConnection, NULL, NULL, "GSSAPI");
    +            if (!$this->ldapBind) {
    +                throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
    +            }
    +            else {
    +                return true;
    +            }
    +        }
    +        
    +        // Bind as the user        
    +        $ret = true;
    +        $this->ldapBind = @ldap_bind($this->ldapConnection, $username . $this->accountSuffix, $password);
    +        if (!$this->ldapBind){ 
    +            $ret = false; 
    +        }
    +        
    +        // Cnce we've checked their details, kick back into admin mode if we have it
    +        if ($this->adminUsername !== NULL && !$preventRebind) {
    +            $this->ldapBind = @ldap_bind($this->ldapConnection, $this->adminUsername . $this->accountSuffix , $this->adminPassword);
    +            if (!$this->ldapBind){
    +                // This should never happen in theory
    +                throw new adLDAPException('Rebind to Active Directory failed. AD said: ' . $this->getLastError());
    +            } 
    +        } 
    +        
    +        return $ret;
    +    }
    +    
    +    /**
    +    * Find the Base DN of your domain controller
    +    * 
    +    * @return string
    +    */
    +    public function findBaseDn() 
    +    {
    +        $namingContext = $this->getRootDse(array('defaultnamingcontext'));   
    +        return $namingContext[0]['defaultnamingcontext'][0];
    +    }
    +    
    +    /**
    +    * Get the RootDSE properties from a domain controller
    +    * 
    +    * @param array $attributes The attributes you wish to query e.g. defaultnamingcontext
    +    * @return array
    +    */
    +    public function getRootDse($attributes = array("*", "+")) {
    +        if (!$this->ldapBind){ return (false); }
    +        
    +        $sr = @ldap_read($this->ldapConnection, NULL, 'objectClass=*', $attributes);
    +        $entries = @ldap_get_entries($this->ldapConnection, $sr);
    +        return $entries;
    +    }
    +
    +    /**
    +    * Get last error from Active Directory
    +    * 
    +    * This function gets the last message from Active Directory
    +    * This may indeed be a 'Success' message but if you get an unknown error
    +    * it might be worth calling this function to see what errors were raised
    +    * 
    +    * return string
    +    */
    +    public function getLastError() {
    +        return @ldap_error($this->ldapConnection);
    +    }
    +    
    +    /**
    +    * Detect LDAP support in php
    +    * 
    +    * @return bool
    +    */    
    +    protected function ldapSupported()
    +    {
    +        if (!function_exists('ldap_connect')) {
    +            return false;   
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Detect ldap_sasl_bind support in PHP
    +    * 
    +    * @return bool
    +    */
    +    protected function ldapSaslSupported()
    +    {
    +        if (!function_exists('ldap_sasl_bind')) {
    +            return false;
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Schema
    +    * 
    +    * @param array $attributes Attributes to be queried
    +    * @return array
    +    */    
    +    public function adldap_schema($attributes){
    +    
    +        // LDAP doesn't like NULL attributes, only set them if they have values
    +        // If you wish to remove an attribute you should set it to a space
    +        // TO DO: Adapt user_modify to use ldap_mod_delete to remove a NULL attribute
    +        $mod=array();
    +        
    +        // Check every attribute to see if it contains 8bit characters and then UTF8 encode them
    +        array_walk($attributes, array($this, 'encode8bit'));
    +
    +        if ($attributes["address_city"]){ $mod["l"][0]=$attributes["address_city"]; }
    +        if ($attributes["address_code"]){ $mod["postalCode"][0]=$attributes["address_code"]; }
    +        //if ($attributes["address_country"]){ $mod["countryCode"][0]=$attributes["address_country"]; } // use country codes?
    +        if ($attributes["address_country"]){ $mod["c"][0]=$attributes["address_country"]; }
    +        if ($attributes["address_pobox"]){ $mod["postOfficeBox"][0]=$attributes["address_pobox"]; }
    +        if ($attributes["address_state"]){ $mod["st"][0]=$attributes["address_state"]; }
    +        if ($attributes["address_street"]){ $mod["streetAddress"][0]=$attributes["address_street"]; }
    +        if ($attributes["company"]){ $mod["company"][0]=$attributes["company"]; }
    +        if ($attributes["change_password"]){ $mod["pwdLastSet"][0]=0; }
    +        if ($attributes["department"]){ $mod["department"][0]=$attributes["department"]; }
    +        if ($attributes["description"]){ $mod["description"][0]=$attributes["description"]; }
    +        if ($attributes["display_name"]){ $mod["displayName"][0]=$attributes["display_name"]; }
    +        if ($attributes["email"]){ $mod["mail"][0]=$attributes["email"]; }
    +        if ($attributes["expires"]){ $mod["accountExpires"][0]=$attributes["expires"]; } //unix epoch format?
    +        if ($attributes["firstname"]){ $mod["givenName"][0]=$attributes["firstname"]; }
    +        if ($attributes["home_directory"]){ $mod["homeDirectory"][0]=$attributes["home_directory"]; }
    +        if ($attributes["home_drive"]){ $mod["homeDrive"][0]=$attributes["home_drive"]; }
    +        if ($attributes["initials"]){ $mod["initials"][0]=$attributes["initials"]; }
    +        if ($attributes["logon_name"]){ $mod["userPrincipalName"][0]=$attributes["logon_name"]; }
    +        if ($attributes["manager"]){ $mod["manager"][0]=$attributes["manager"]; }  //UNTESTED ***Use DistinguishedName***
    +        if ($attributes["office"]){ $mod["physicalDeliveryOfficeName"][0]=$attributes["office"]; }
    +        if ($attributes["password"]){ $mod["unicodePwd"][0]=$this->user()->encodePassword($attributes["password"]); }
    +        if ($attributes["profile_path"]){ $mod["profilepath"][0]=$attributes["profile_path"]; }
    +        if ($attributes["script_path"]){ $mod["scriptPath"][0]=$attributes["script_path"]; }
    +        if ($attributes["surname"]){ $mod["sn"][0]=$attributes["surname"]; }
    +        if ($attributes["title"]){ $mod["title"][0]=$attributes["title"]; }
    +        if ($attributes["telephone"]){ $mod["telephoneNumber"][0]=$attributes["telephone"]; }
    +        if ($attributes["mobile"]){ $mod["mobile"][0]=$attributes["mobile"]; }
    +        if ($attributes["pager"]){ $mod["pager"][0]=$attributes["pager"]; }
    +        if ($attributes["ipphone"]){ $mod["ipphone"][0]=$attributes["ipphone"]; }
    +        if ($attributes["web_page"]){ $mod["wWWHomePage"][0]=$attributes["web_page"]; }
    +        if ($attributes["fax"]){ $mod["facsimileTelephoneNumber"][0]=$attributes["fax"]; }
    +        if ($attributes["enabled"]){ $mod["userAccountControl"][0]=$attributes["enabled"]; }
    +        if ($attributes["homephone"]){ $mod["homephone"][0]=$attributes["homephone"]; }
    +        
    +        // Distribution List specific schema
    +        if ($attributes["group_sendpermission"]){ $mod["dlMemSubmitPerms"][0]=$attributes["group_sendpermission"]; }
    +        if ($attributes["group_rejectpermission"]){ $mod["dlMemRejectPerms"][0]=$attributes["group_rejectpermission"]; }
    +        
    +        // Exchange Schema
    +        if ($attributes["exchange_homemdb"]){ $mod["homeMDB"][0]=$attributes["exchange_homemdb"]; }
    +        if ($attributes["exchange_mailnickname"]){ $mod["mailNickname"][0]=$attributes["exchange_mailnickname"]; }
    +        if ($attributes["exchange_proxyaddress"]){ $mod["proxyAddresses"][0]=$attributes["exchange_proxyaddress"]; }
    +        if ($attributes["exchange_usedefaults"]){ $mod["mDBUseDefaults"][0]=$attributes["exchange_usedefaults"]; }
    +        if ($attributes["exchange_policyexclude"]){ $mod["msExchPoliciesExcluded"][0]=$attributes["exchange_policyexclude"]; }
    +        if ($attributes["exchange_policyinclude"]){ $mod["msExchPoliciesIncluded"][0]=$attributes["exchange_policyinclude"]; }       
    +        if ($attributes["exchange_addressbook"]){ $mod["showInAddressBook"][0]=$attributes["exchange_addressbook"]; }    
    +        if ($attributes["exchange_altrecipient"]){ $mod["altRecipient"][0]=$attributes["exchange_altrecipient"]; } 
    +        if ($attributes["exchange_deliverandredirect"]){ $mod["deliverAndRedirect"][0]=$attributes["exchange_deliverandredirect"]; }    
    +        
    +        // This schema is designed for contacts
    +        if ($attributes["exchange_hidefromlists"]){ $mod["msExchHideFromAddressLists"][0]=$attributes["exchange_hidefromlists"]; }
    +        if ($attributes["contact_email"]){ $mod["targetAddress"][0]=$attributes["contact_email"]; }
    +        
    +        //echo ("
    "); print_r($mod);
    +        /*
    +        // modifying a name is a bit fiddly
    +        if ($attributes["firstname"] && $attributes["surname"]){
    +            $mod["cn"][0]=$attributes["firstname"]." ".$attributes["surname"];
    +            $mod["displayname"][0]=$attributes["firstname"]." ".$attributes["surname"];
    +            $mod["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
    +        }
    +        */
    +
    +        if (count($mod)==0){ return (false); }
    +        return ($mod);
    +    }
    +    
    +    /**
    +    * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
    +    */
    +    protected function encode8Bit(&$item, $key) {
    +        $encode = false;
    +        if (is_string($item)) {
    +            for ($i=0; $i> 7) {
    +                    $encode = true;
    +                }
    +            }
    +        }
    +        if ($encode === true && $key != 'password') {
    +            $item = utf8_encode($item);   
    +        }
    +    }
    +    
    +    /**
    +    * Select a random domain controller from your domain controller array
    +    * 
    +    * @return string
    +    */
    +    protected function randomController() 
    +    {
    +        mt_srand(doubleval(microtime()) * 100000000); // For older PHP versions
    +        /*if (sizeof($this->domainControllers) > 1) {
    +            $adController = $this->domainControllers[array_rand($this->domainControllers)]; 
    +            // Test if the controller is responding to pings
    +            $ping = $this->pingController($adController); 
    +            if ($ping === false) { 
    +                // Find the current key in the domain controllers array
    +                $key = array_search($adController, $this->domainControllers);
    +                // Remove it so that we don't end up in a recursive loop
    +                unset($this->domainControllers[$key]);
    +                // Select a new controller
    +                return $this->randomController(); 
    +            }
    +            else { 
    +                return ($adController); 
    +            }
    +        } */
    +        return $this->domainControllers[array_rand($this->domainControllers)];
    +    }  
    +    
    +    /** 
    +    * Test basic connectivity to controller 
    +    * 
    +    * @return bool
    +    */ 
    +    protected function pingController($host) {
    +        $port = $this->adPort; 
    +        fsockopen($host, $port, $errno, $errstr, 10); 
    +        if ($errno > 0) {
    +            return false;
    +        }
    +        return true;
    +    }
    +
    +}
    +
    +/**
    +* adLDAP Exception Handler
    +* 
    +* Exceptions of this type are thrown on bind failure or when SSL is required but not configured
    +* Example:
    +* try {
    +*   $adldap = new adLDAP();
    +* }
    +* catch (adLDAPException $e) {
    +*   echo $e;
    +*   exit();
    +* }
    +*/
    +class adLDAPException extends Exception {}
    +
     ?>
    \ No newline at end of file
    diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPComputers.php b/lib/plugins/authad/adLDAP/classes/adLDAPComputers.php
    index 71b24a04f..aabd88fa5 100644
    --- a/lib/plugins/authad/adLDAP/classes/adLDAPComputers.php
    +++ b/lib/plugins/authad/adLDAP/classes/adLDAPComputers.php
    @@ -1,153 +1,153 @@
    -adldap = $adldap;
    -    }
    -    
    -    /**
    -    * Get information about a specific computer. Returned in a raw array format from AD
    -    * 
    -    * @param string $computerName The name of the computer
    -    * @param array $fields Attributes to return
    -    * @return array
    -    */
    -    public function info($computerName, $fields = NULL)
    -    {
    -        if ($computerName === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -
    -        $filter = "(&(objectClass=computer)(cn=" . $computerName . "))";
    -        if ($fields === NULL) { 
    -            $fields = array("memberof","cn","displayname","dnshostname","distinguishedname","objectcategory","operatingsystem","operatingsystemservicepack","operatingsystemversion"); 
    -        }
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -        
    -        return $entries;
    -    }
    -    
    -    /**
    -    * Find information about the computers. Returned in a raw array format from AD
    -    * 
    -    * @param string $computerName The name of the computer
    -    * @param array $fields Array of parameters to query
    -    * @return mixed
    -    */
    -    public function infoCollection($computerName, $fields = NULL)
    -    {
    -        if ($computerName === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        $info = $this->info($computerName, $fields);
    -        
    -        if ($info !== false) {
    -            $collection = new adLDAPComputerCollection($info, $this->adldap);
    -            return $collection;
    -        }
    -        return false;
    -    }
    -    
    -    /**
    -    * Check if a computer is in a group
    -    * 
    -    * @param string $computerName The name of the computer
    -    * @param string $group The group to check
    -    * @param bool $recursive Whether to check recursively
    -    * @return array
    -    */
    -    public function inGroup($computerName, $group, $recursive = NULL)
    -    {
    -        if ($computerName === NULL) { return false; }
    -        if ($group === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // use the default option if they haven't set it
    -
    -        //get a list of the groups
    -        $groups = $this->groups($computerName, array("memberof"), $recursive);
    -
    -        //return true if the specified group is in the group list
    -        if (in_array($group, $groups)){ 
    -            return true; 
    -        }
    -
    -        return false;
    -    }
    -    
    -    /**
    -    * Get the groups a computer is in
    -    * 
    -    * @param string $computerName The name of the computer
    -    * @param bool $recursive Whether to check recursively
    -    * @return array
    -    */
    -    public function groups($computerName, $recursive = NULL)
    -    {
    -        if ($computerName === NULL) { return false; }
    -        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -
    -        //search the directory for their information
    -        $info = @$this->info($computerName, array("memberof", "primarygroupid"));
    -        $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our guy (unique usernames)
    -
    -        if ($recursive === true) {
    -            foreach ($groups as $id => $groupName){
    -              $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
    -              $groups = array_merge($groups, $extraGroups);
    -            }
    -        }
    -
    -        return $groups;
    -    }
    -    
    -}
    +adldap = $adldap;
    +    }
    +    
    +    /**
    +    * Get information about a specific computer. Returned in a raw array format from AD
    +    * 
    +    * @param string $computerName The name of the computer
    +    * @param array $fields Attributes to return
    +    * @return array
    +    */
    +    public function info($computerName, $fields = NULL)
    +    {
    +        if ($computerName === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +
    +        $filter = "(&(objectClass=computer)(cn=" . $computerName . "))";
    +        if ($fields === NULL) { 
    +            $fields = array("memberof","cn","displayname","dnshostname","distinguishedname","objectcategory","operatingsystem","operatingsystemservicepack","operatingsystemversion"); 
    +        }
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +        
    +        return $entries;
    +    }
    +    
    +    /**
    +    * Find information about the computers. Returned in a raw array format from AD
    +    * 
    +    * @param string $computerName The name of the computer
    +    * @param array $fields Array of parameters to query
    +    * @return mixed
    +    */
    +    public function infoCollection($computerName, $fields = NULL)
    +    {
    +        if ($computerName === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        $info = $this->info($computerName, $fields);
    +        
    +        if ($info !== false) {
    +            $collection = new adLDAPComputerCollection($info, $this->adldap);
    +            return $collection;
    +        }
    +        return false;
    +    }
    +    
    +    /**
    +    * Check if a computer is in a group
    +    * 
    +    * @param string $computerName The name of the computer
    +    * @param string $group The group to check
    +    * @param bool $recursive Whether to check recursively
    +    * @return array
    +    */
    +    public function inGroup($computerName, $group, $recursive = NULL)
    +    {
    +        if ($computerName === NULL) { return false; }
    +        if ($group === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // use the default option if they haven't set it
    +
    +        //get a list of the groups
    +        $groups = $this->groups($computerName, array("memberof"), $recursive);
    +
    +        //return true if the specified group is in the group list
    +        if (in_array($group, $groups)){ 
    +            return true; 
    +        }
    +
    +        return false;
    +    }
    +    
    +    /**
    +    * Get the groups a computer is in
    +    * 
    +    * @param string $computerName The name of the computer
    +    * @param bool $recursive Whether to check recursively
    +    * @return array
    +    */
    +    public function groups($computerName, $recursive = NULL)
    +    {
    +        if ($computerName === NULL) { return false; }
    +        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +
    +        //search the directory for their information
    +        $info = @$this->info($computerName, array("memberof", "primarygroupid"));
    +        $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our guy (unique usernames)
    +
    +        if ($recursive === true) {
    +            foreach ($groups as $id => $groupName){
    +              $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
    +              $groups = array_merge($groups, $extraGroups);
    +            }
    +        }
    +
    +        return $groups;
    +    }
    +    
    +}
     ?>
    \ No newline at end of file
    diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPContacts.php b/lib/plugins/authad/adLDAP/classes/adLDAPContacts.php
    index addd3e5f0..42a0d756b 100644
    --- a/lib/plugins/authad/adLDAP/classes/adLDAPContacts.php
    +++ b/lib/plugins/authad/adLDAP/classes/adLDAPContacts.php
    @@ -1,294 +1,294 @@
    -adldap = $adldap;
    -    }
    -    
    -    //*****************************************************************************************************************
    -    // CONTACT FUNCTIONS
    -    // * Still work to do in this area, and new functions to write
    -    
    -    /**
    -    * Create a contact
    -    * 
    -    * @param array $attributes The attributes to set to the contact
    -    * @return bool
    -    */
    -    public function create($attributes)
    -    {
    -        // Check for compulsory fields
    -        if (!array_key_exists("display_name", $attributes)) { return "Missing compulsory field [display_name]"; }
    -        if (!array_key_exists("email", $attributes)) { return "Missing compulsory field [email]"; }
    -        if (!array_key_exists("container", $attributes)) { return "Missing compulsory field [container]"; }
    -        if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
    -
    -        // Translate the schema
    -        $add = $this->adldap->adldap_schema($attributes);
    -        
    -        // Additional stuff only used for adding contacts
    -        $add["cn"][0] = $attributes["display_name"];
    -        $add["objectclass"][0] = "top";
    -        $add["objectclass"][1] = "person";
    -        $add["objectclass"][2] = "organizationalPerson";
    -        $add["objectclass"][3] = "contact"; 
    -        if (!isset($attributes['exchange_hidefromlists'])) {
    -            $add["msExchHideFromAddressLists"][0] = "TRUE";
    -        }
    -
    -        // Determine the container
    -        $attributes["container"] = array_reverse($attributes["container"]);
    -        $container= "OU=" . implode(",OU=", $attributes["container"]);
    -
    -        // Add the entry
    -        $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $this->adldap->utilities()->escapeCharacters($add["cn"][0]) . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
    -        if ($result != true) { 
    -            return false; 
    -        }
    -        
    -        return true;
    -    }  
    -    
    -    /**
    -    * Determine the list of groups a contact is a member of
    -    * 
    -    * @param string $distinguisedname The full DN of a contact
    -    * @param bool $recursive Recursively check groups
    -    * @return array
    -    */
    -    public function groups($distinguishedName, $recursive = NULL)
    -    {
    -        if ($distinguishedName === NULL) { return false; }
    -        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -        
    -        // Search the directory for their information
    -        $info = @$this->info($distinguishedName, array("memberof", "primarygroupid"));
    -        $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our contact
    -
    -        if ($recursive === true){
    -            foreach ($groups as $id => $groupName){
    -                $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
    -                $groups = array_merge($groups, $extraGroups);
    -            }
    -        }
    -        
    -        return $groups;
    -    }
    -    
    -    /**
    -    * Get contact information. Returned in a raw array format from AD
    -    * 
    -    * @param string $distinguisedname The full DN of a contact
    -    * @param array $fields Attributes to be returned
    -    * @return array
    -    */
    -    public function info($distinguishedName, $fields = NULL)
    -    {
    -        if ($distinguishedName === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -
    -        $filter = "distinguishedName=" . $distinguishedName;
    -        if ($fields === NULL) { 
    -            $fields = array("distinguishedname", "mail", "memberof", "department", "displayname", "telephonenumber", "primarygroupid", "objectsid"); 
    -        }
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -        
    -        if ($entries[0]['count'] >= 1) {
    -            // AD does not return the primary group in the ldap query, we may need to fudge it
    -            if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["primarygroupid"][0])){
    -                //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
    -                $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
    -            } else {
    -                $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
    -            }
    -        }
    -        
    -        $entries[0]["memberof"]["count"]++;
    -        return $entries;
    -    }
    -    
    -    /**
    -    * Find information about the contacts. Returned in a raw array format from AD
    -    * 
    -    * @param string $distinguishedName The full DN of a contact 
    -    * @param array $fields Array of parameters to query
    -    * @return mixed
    -    */
    -    public function infoCollection($distinguishedName, $fields = NULL)
    -    {
    -        if ($distinguishedName === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        $info = $this->info($distinguishedName, $fields);
    -        
    -        if ($info !== false) {
    -            $collection = new adLDAPContactCollection($info, $this->adldap);
    -            return $collection;
    -        }
    -        return false;
    -    }
    -    
    -    /**
    -    * Determine if a contact is a member of a group
    -    * 
    -    * @param string $distinguisedName The full DN of a contact
    -    * @param string $group The group name to query
    -    * @param bool $recursive Recursively check groups
    -    * @return bool
    -    */
    -    public function inGroup($distinguisedName, $group, $recursive = NULL)
    -    {
    -        if ($distinguisedName === NULL) { return false; }
    -        if ($group === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
    -        
    -        // Get a list of the groups
    -        $groups = $this->groups($distinguisedName, array("memberof"), $recursive);
    -        
    -        // Return true if the specified group is in the group list
    -        if (in_array($group, $groups)){ 
    -            return true; 
    -        }
    -
    -        return false;
    -    }          
    -    
    -    /**
    -    * Modify a contact
    -    * 
    -    * @param string $distinguishedName The contact to query
    -    * @param array $attributes The attributes to modify.  Note if you set the enabled attribute you must not specify any other attributes
    -    * @return bool
    -    */
    -    public function modify($distinguishedName, $attributes) {
    -        if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedname]"; }
    -        
    -        // Translate the update to the LDAP schema                
    -        $mod = $this->adldap->adldap_schema($attributes);
    -        
    -        // Check to see if this is an enabled status update
    -        if (!$mod) { 
    -            return false; 
    -        }
    -        
    -        // Do the update
    -        $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        
    -        return true;
    -    }
    -    
    -    /**
    -    * Delete a contact
    -    * 
    -    * @param string $distinguishedName The contact dn to delete (please be careful here!)
    -    * @return array
    -    */
    -    public function delete($distinguishedName) 
    -    {
    -        $result = $this->folder()->delete($distinguishedName);
    -        if ($result != true) { 
    -            return false; 
    -        }       
    -        return true;
    -    }
    -    
    -    /**
    -    * Return a list of all contacts
    -    * 
    -    * @param bool $includeDescription Include a description of a contact
    -    * @param string $search The search parameters
    -    * @param bool $sorted Whether to sort the results
    -    * @return array
    -    */
    -    public function all($includeDescription = false, $search = "*", $sorted = true) {
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        // Perform the search and grab all their details
    -        $filter = "(&(objectClass=contact)(cn=" . $search . "))";
    -        $fields = array("displayname","distinguishedname");           
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -        $usersArray = array();
    -        for ($i=0; $i<$entries["count"]; $i++){
    -            if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
    -                $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["displayname"][0];
    -            } elseif ($includeDescription){
    -                $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["distinguishedname"][0];
    -            } else {
    -                array_push($usersArray, $entries[$i]["distinguishedname"][0]);
    -            }
    -        }
    -        if ($sorted) { 
    -            asort($usersArray); 
    -        }
    -        return $usersArray;
    -    }
    -    
    -    /**
    -    * Mail enable a contact
    -    * Allows email to be sent to them through Exchange
    -    * 
    -    * @param string $distinguishedname The contact to mail enable
    -    * @param string $emailaddress The email address to allow emails to be sent through
    -    * @param string $mailnickname The mailnickname for the contact in Exchange.  If NULL this will be set to the display name
    -    * @return bool
    -    */
    -    public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL){
    -        return $this->adldap->exchange()->contactMailEnable($distinguishedName, $emailAddress, $mailNickname);
    -    }
    -    
    -    
    -}
    -?>
    +adldap = $adldap;
    +    }
    +    
    +    //*****************************************************************************************************************
    +    // CONTACT FUNCTIONS
    +    // * Still work to do in this area, and new functions to write
    +    
    +    /**
    +    * Create a contact
    +    * 
    +    * @param array $attributes The attributes to set to the contact
    +    * @return bool
    +    */
    +    public function create($attributes)
    +    {
    +        // Check for compulsory fields
    +        if (!array_key_exists("display_name", $attributes)) { return "Missing compulsory field [display_name]"; }
    +        if (!array_key_exists("email", $attributes)) { return "Missing compulsory field [email]"; }
    +        if (!array_key_exists("container", $attributes)) { return "Missing compulsory field [container]"; }
    +        if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
    +
    +        // Translate the schema
    +        $add = $this->adldap->adldap_schema($attributes);
    +        
    +        // Additional stuff only used for adding contacts
    +        $add["cn"][0] = $attributes["display_name"];
    +        $add["objectclass"][0] = "top";
    +        $add["objectclass"][1] = "person";
    +        $add["objectclass"][2] = "organizationalPerson";
    +        $add["objectclass"][3] = "contact"; 
    +        if (!isset($attributes['exchange_hidefromlists'])) {
    +            $add["msExchHideFromAddressLists"][0] = "TRUE";
    +        }
    +
    +        // Determine the container
    +        $attributes["container"] = array_reverse($attributes["container"]);
    +        $container= "OU=" . implode(",OU=", $attributes["container"]);
    +
    +        // Add the entry
    +        $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $this->adldap->utilities()->escapeCharacters($add["cn"][0]) . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
    +        if ($result != true) { 
    +            return false; 
    +        }
    +        
    +        return true;
    +    }  
    +    
    +    /**
    +    * Determine the list of groups a contact is a member of
    +    * 
    +    * @param string $distinguisedname The full DN of a contact
    +    * @param bool $recursive Recursively check groups
    +    * @return array
    +    */
    +    public function groups($distinguishedName, $recursive = NULL)
    +    {
    +        if ($distinguishedName === NULL) { return false; }
    +        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +        
    +        // Search the directory for their information
    +        $info = @$this->info($distinguishedName, array("memberof", "primarygroupid"));
    +        $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our contact
    +
    +        if ($recursive === true){
    +            foreach ($groups as $id => $groupName){
    +                $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
    +                $groups = array_merge($groups, $extraGroups);
    +            }
    +        }
    +        
    +        return $groups;
    +    }
    +    
    +    /**
    +    * Get contact information. Returned in a raw array format from AD
    +    * 
    +    * @param string $distinguisedname The full DN of a contact
    +    * @param array $fields Attributes to be returned
    +    * @return array
    +    */
    +    public function info($distinguishedName, $fields = NULL)
    +    {
    +        if ($distinguishedName === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +
    +        $filter = "distinguishedName=" . $distinguishedName;
    +        if ($fields === NULL) { 
    +            $fields = array("distinguishedname", "mail", "memberof", "department", "displayname", "telephonenumber", "primarygroupid", "objectsid"); 
    +        }
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +        
    +        if ($entries[0]['count'] >= 1) {
    +            // AD does not return the primary group in the ldap query, we may need to fudge it
    +            if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["primarygroupid"][0])){
    +                //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
    +                $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
    +            } else {
    +                $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
    +            }
    +        }
    +        
    +        $entries[0]["memberof"]["count"]++;
    +        return $entries;
    +    }
    +    
    +    /**
    +    * Find information about the contacts. Returned in a raw array format from AD
    +    * 
    +    * @param string $distinguishedName The full DN of a contact 
    +    * @param array $fields Array of parameters to query
    +    * @return mixed
    +    */
    +    public function infoCollection($distinguishedName, $fields = NULL)
    +    {
    +        if ($distinguishedName === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        $info = $this->info($distinguishedName, $fields);
    +        
    +        if ($info !== false) {
    +            $collection = new adLDAPContactCollection($info, $this->adldap);
    +            return $collection;
    +        }
    +        return false;
    +    }
    +    
    +    /**
    +    * Determine if a contact is a member of a group
    +    * 
    +    * @param string $distinguisedName The full DN of a contact
    +    * @param string $group The group name to query
    +    * @param bool $recursive Recursively check groups
    +    * @return bool
    +    */
    +    public function inGroup($distinguisedName, $group, $recursive = NULL)
    +    {
    +        if ($distinguisedName === NULL) { return false; }
    +        if ($group === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
    +        
    +        // Get a list of the groups
    +        $groups = $this->groups($distinguisedName, array("memberof"), $recursive);
    +        
    +        // Return true if the specified group is in the group list
    +        if (in_array($group, $groups)){ 
    +            return true; 
    +        }
    +
    +        return false;
    +    }          
    +    
    +    /**
    +    * Modify a contact
    +    * 
    +    * @param string $distinguishedName The contact to query
    +    * @param array $attributes The attributes to modify.  Note if you set the enabled attribute you must not specify any other attributes
    +    * @return bool
    +    */
    +    public function modify($distinguishedName, $attributes) {
    +        if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedname]"; }
    +        
    +        // Translate the update to the LDAP schema                
    +        $mod = $this->adldap->adldap_schema($attributes);
    +        
    +        // Check to see if this is an enabled status update
    +        if (!$mod) { 
    +            return false; 
    +        }
    +        
    +        // Do the update
    +        $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Delete a contact
    +    * 
    +    * @param string $distinguishedName The contact dn to delete (please be careful here!)
    +    * @return array
    +    */
    +    public function delete($distinguishedName) 
    +    {
    +        $result = $this->folder()->delete($distinguishedName);
    +        if ($result != true) { 
    +            return false; 
    +        }       
    +        return true;
    +    }
    +    
    +    /**
    +    * Return a list of all contacts
    +    * 
    +    * @param bool $includeDescription Include a description of a contact
    +    * @param string $search The search parameters
    +    * @param bool $sorted Whether to sort the results
    +    * @return array
    +    */
    +    public function all($includeDescription = false, $search = "*", $sorted = true) {
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        // Perform the search and grab all their details
    +        $filter = "(&(objectClass=contact)(cn=" . $search . "))";
    +        $fields = array("displayname","distinguishedname");           
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +        $usersArray = array();
    +        for ($i=0; $i<$entries["count"]; $i++){
    +            if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
    +                $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["displayname"][0];
    +            } elseif ($includeDescription){
    +                $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["distinguishedname"][0];
    +            } else {
    +                array_push($usersArray, $entries[$i]["distinguishedname"][0]);
    +            }
    +        }
    +        if ($sorted) { 
    +            asort($usersArray); 
    +        }
    +        return $usersArray;
    +    }
    +    
    +    /**
    +    * Mail enable a contact
    +    * Allows email to be sent to them through Exchange
    +    * 
    +    * @param string $distinguishedname The contact to mail enable
    +    * @param string $emailaddress The email address to allow emails to be sent through
    +    * @param string $mailnickname The mailnickname for the contact in Exchange.  If NULL this will be set to the display name
    +    * @return bool
    +    */
    +    public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL){
    +        return $this->adldap->exchange()->contactMailEnable($distinguishedName, $emailAddress, $mailNickname);
    +    }
    +    
    +    
    +}
    +?>
    diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPExchange.php b/lib/plugins/authad/adLDAP/classes/adLDAPExchange.php
    index dd0c6de05..d70aac779 100644
    --- a/lib/plugins/authad/adLDAP/classes/adLDAPExchange.php
    +++ b/lib/plugins/authad/adLDAP/classes/adLDAPExchange.php
    @@ -1,390 +1,390 @@
    -adldap = $adldap;
    -    }
    -    
    -    /**
    -    * Create an Exchange account
    -    * 
    -    * @param string $username The username of the user to add the Exchange account to
    -    * @param array $storageGroup The mailbox, Exchange Storage Group, for the user account, this must be a full CN
    -    *                            If the storage group has a different base_dn to the adLDAP configuration, set it using $base_dn
    -    * @param string $emailAddress The primary email address to add to this user
    -    * @param string $mailNickname The mail nick name.  If mail nickname is blank, the username will be used
    -    * @param bool $mdbUseDefaults Indicates whether the store should use the default quota, rather than the per-mailbox quota.
    -    * @param string $baseDn Specify an alternative base_dn for the Exchange storage group
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function createMailbox($username, $storageGroup, $emailAddress, $mailNickname=NULL, $useDefaults=TRUE, $baseDn=NULL, $isGUID=false)
    -    {
    -        if ($username === NULL){ return "Missing compulsory field [username]"; }     
    -        if ($storageGroup === NULL) { return "Missing compulsory array [storagegroup]"; }
    -        if (!is_array($storageGroup)) { return "[storagegroup] must be an array"; }
    -        if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; }
    -        
    -        if ($baseDn === NULL) {
    -            $baseDn = $this->adldap->getBaseDn();   
    -        }
    -        
    -        $container = "CN=" . implode(",CN=", $storageGroup);
    -        
    -        if ($mailNickname === NULL) { 
    -            $mailNickname = $username; 
    -        }
    -        $mdbUseDefaults = $this->adldap->utilities()->boolToString($useDefaults);
    -        
    -        $attributes = array(
    -            'exchange_homemdb'=>$container.",".$baseDn,
    -            'exchange_proxyaddress'=>'SMTP:' . $emailAddress,
    -            'exchange_mailnickname'=>$mailNickname,
    -            'exchange_usedefaults'=>$mdbUseDefaults
    -        );
    -        $result = $this->adldap->user()->modify($username, $attributes, $isGUID);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Add an X400 address to Exchange
    -    * See http://tools.ietf.org/html/rfc1685 for more information.
    -    * An X400 Address looks similar to this X400:c=US;a= ;p=Domain;o=Organization;s=Doe;g=John;
    -    * 
    -    * @param string $username The username of the user to add the X400 to to
    -    * @param string $country Country
    -    * @param string $admd Administration Management Domain
    -    * @param string $pdmd Private Management Domain (often your AD domain)
    -    * @param string $org Organization
    -    * @param string $surname Surname
    -    * @param string $givenName Given name
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function addX400($username, $country, $admd, $pdmd, $org, $surname, $givenName, $isGUID=false) 
    -    {
    -        if ($username === NULL){ return "Missing compulsory field [username]"; }     
    -        
    -        $proxyValue = 'X400:';
    -            
    -        // Find the dn of the user
    -        $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
    -        if ($user[0]["dn"] === NULL) { return false; }
    -        $userDn = $user[0]["dn"];
    -        
    -        // We do not have to demote an email address from the default so we can just add the new proxy address
    -        $attributes['exchange_proxyaddress'] = $proxyValue . 'c=' . $country . ';a=' . $admd . ';p=' . $pdmd . ';o=' . $org . ';s=' . $surname . ';g=' . $givenName . ';';
    -       
    -        // Translate the update to the LDAP schema                
    -        $add = $this->adldap->adldap_schema($attributes);
    -        
    -        if (!$add) { return false; }
    -        
    -        // Do the update
    -        // Take out the @ to see any errors, usually this error might occur because the address already
    -        // exists in the list of proxyAddresses
    -        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn, $add);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        
    -        return true;
    -    }
    -    
    -    /**
    -    * Add an address to Exchange
    -    * 
    -    * @param string $username The username of the user to add the Exchange account to
    -    * @param string $emailAddress The email address to add to this user
    -    * @param bool $default Make this email address the default address, this is a bit more intensive as we have to demote any existing default addresses
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function addAddress($username, $emailAddress, $default = FALSE, $isGUID = false) 
    -    {
    -        if ($username === NULL) { return "Missing compulsory field [username]"; }     
    -        if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
    -        
    -        $proxyValue = 'smtp:';
    -        if ($default === true) {
    -            $proxyValue = 'SMTP:';
    -        }
    -              
    -        // Find the dn of the user
    -        $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
    -        if ($user[0]["dn"] === NULL){ return false; }
    -        $userDn = $user[0]["dn"];
    -        
    -        // We need to scan existing proxy addresses and demote the default one
    -        if (is_array($user[0]["proxyaddresses"]) && $default === true) {
    -            $modAddresses = array();
    -            for ($i=0;$iadldap->getLdapConnection(), $userDn, $modAddresses);
    -            if ($result == false) { 
    -                return false; 
    -            }
    -            
    -            return true;
    -        }
    -        else {
    -            // We do not have to demote an email address from the default so we can just add the new proxy address
    -            $attributes['exchange_proxyaddress'] = $proxyValue . $emailAddress;
    -            
    -            // Translate the update to the LDAP schema                
    -            $add = $this->adldap->adldap_schema($attributes);
    -            
    -            if (!$add) { 
    -                return false; 
    -            }
    -            
    -            // Do the update
    -            // Take out the @ to see any errors, usually this error might occur because the address already
    -            // exists in the list of proxyAddresses
    -            $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn,$add);
    -            if ($result == false) { 
    -                return false; 
    -            }
    -            
    -            return true;
    -        }
    -    }
    -    
    -    /**
    -    * Remove an address to Exchange
    -    * If you remove a default address the account will no longer have a default, 
    -    * we recommend changing the default address first
    -    * 
    -    * @param string $username The username of the user to add the Exchange account to
    -    * @param string $emailAddress The email address to add to this user
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function deleteAddress($username, $emailAddress, $isGUID=false) 
    -    {
    -        if ($username === NULL) { return "Missing compulsory field [username]"; }     
    -        if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
    -        
    -        // Find the dn of the user
    -        $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
    -        if ($user[0]["dn"] === NULL) { return false; }
    -        $userDn = $user[0]["dn"];
    -        
    -        if (is_array($user[0]["proxyaddresses"])) {
    -            $mod = array();
    -            for ($i=0;$iadldap->getLdapConnection(), $userDn,$mod);
    -            if ($result == false) { 
    -                return false; 
    -            }
    -            
    -            return true;
    -        }
    -        else {
    -            return false;
    -        }
    -    }
    -    /**
    -    * Change the default address
    -    * 
    -    * @param string $username The username of the user to add the Exchange account to
    -    * @param string $emailAddress The email address to make default
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function primaryAddress($username, $emailAddress, $isGUID = false) 
    -    {
    -        if ($username === NULL) { return "Missing compulsory field [username]"; }     
    -        if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
    -        
    -        // Find the dn of the user
    -        $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
    -        if ($user[0]["dn"] === NULL){ return false; }
    -        $userDn = $user[0]["dn"];
    -        
    -        if (is_array($user[0]["proxyaddresses"])) {
    -            $modAddresses = array();
    -            for ($i=0;$iadldap->getLdapConnection(), $userDn, $modAddresses);
    -            if ($result == false) { 
    -                return false; 
    -            }
    -            
    -            return true;
    -        }
    -        
    -    }
    -    
    -    /**
    -    * Mail enable a contact
    -    * Allows email to be sent to them through Exchange
    -    * 
    -    * @param string $distinguishedName The contact to mail enable
    -    * @param string $emailAddress The email address to allow emails to be sent through
    -    * @param string $mailNickname The mailnickname for the contact in Exchange.  If NULL this will be set to the display name
    -    * @return bool
    -    */
    -    public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL)
    -    {
    -        if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedName]"; }   
    -        if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; }  
    -        
    -        if ($mailNickname !== NULL) {
    -            // Find the dn of the user
    -            $user = $this->adldap->contact()->info($distinguishedName, array("cn","displayname"));
    -            if ($user[0]["displayname"] === NULL) { return false; }
    -            $mailNickname = $user[0]['displayname'][0];
    -        }
    -        
    -        $attributes = array("email"=>$emailAddress,"contact_email"=>"SMTP:" . $emailAddress,"exchange_proxyaddress"=>"SMTP:" . $emailAddress,"exchange_mailnickname" => $mailNickname);
    -         
    -        // Translate the update to the LDAP schema                
    -        $mod = $this->adldap->adldap_schema($attributes);
    -        
    -        // Check to see if this is an enabled status update
    -        if (!$mod) { return false; }
    -        
    -        // Do the update
    -        $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
    -        if ($result == false) { return false; }
    -        
    -        return true;
    -    }
    -    
    -    /**
    -    * Returns a list of Exchange Servers in the ConfigurationNamingContext of the domain
    -    * 
    -    * @param array $attributes An array of the AD attributes you wish to return
    -    * @return array
    -    */
    -    public function servers($attributes = array('cn','distinguishedname','serialnumber')) 
    -    {
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -        
    -        $configurationNamingContext = $this->adldap->getRootDse(array('configurationnamingcontext'));
    -        $sr = @ldap_search($this->adldap->getLdapConnection(), $configurationNamingContext[0]['configurationnamingcontext'][0],'(&(objectCategory=msExchExchangeServer))', $attributes);
    -        $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -        return $entries;
    -    }
    -    
    -    /**
    -    * Returns a list of Storage Groups in Exchange for a given mail server
    -    * 
    -    * @param string $exchangeServer The full DN of an Exchange server.  You can use exchange_servers() to find the DN for your server
    -    * @param array $attributes An array of the AD attributes you wish to return
    -    * @param bool $recursive If enabled this will automatically query the databases within a storage group
    -    * @return array
    -    */
    -    public function storageGroups($exchangeServer, $attributes = array('cn','distinguishedname'), $recursive = NULL) 
    -    {
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -        if ($exchangeServer === NULL) { return "Missing compulsory field [exchangeServer]"; }
    -        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); }
    -
    -        $filter = '(&(objectCategory=msExchStorageGroup))';
    -        $sr = @ldap_search($this->adldap->getLdapConnection(), $exchangeServer, $filter, $attributes);
    -        $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -        if ($recursive === true) {
    -            for ($i=0; $i<$entries['count']; $i++) {
    -                $entries[$i]['msexchprivatemdb'] = $this->storageDatabases($entries[$i]['distinguishedname'][0]);       
    -            }
    -        }
    -        
    -        return $entries;
    -    }
    -    
    -    /**
    -    * Returns a list of Databases within any given storage group in Exchange for a given mail server
    -    * 
    -    * @param string $storageGroup The full DN of an Storage Group.  You can use exchange_storage_groups() to find the DN 
    -    * @param array $attributes An array of the AD attributes you wish to return
    -    * @return array
    -    */
    -    public function storageDatabases($storageGroup, $attributes = array('cn','distinguishedname','displayname')) {
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -        if ($storageGroup === NULL) { return "Missing compulsory field [storageGroup]"; }
    -        
    -        $filter = '(&(objectCategory=msExchPrivateMDB))';
    -        $sr = @ldap_search($this->adldap->getLdapConnection(), $storageGroup, $filter, $attributes);
    -        $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -        return $entries;
    -    }
    -}
    +adldap = $adldap;
    +    }
    +    
    +    /**
    +    * Create an Exchange account
    +    * 
    +    * @param string $username The username of the user to add the Exchange account to
    +    * @param array $storageGroup The mailbox, Exchange Storage Group, for the user account, this must be a full CN
    +    *                            If the storage group has a different base_dn to the adLDAP configuration, set it using $base_dn
    +    * @param string $emailAddress The primary email address to add to this user
    +    * @param string $mailNickname The mail nick name.  If mail nickname is blank, the username will be used
    +    * @param bool $mdbUseDefaults Indicates whether the store should use the default quota, rather than the per-mailbox quota.
    +    * @param string $baseDn Specify an alternative base_dn for the Exchange storage group
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function createMailbox($username, $storageGroup, $emailAddress, $mailNickname=NULL, $useDefaults=TRUE, $baseDn=NULL, $isGUID=false)
    +    {
    +        if ($username === NULL){ return "Missing compulsory field [username]"; }     
    +        if ($storageGroup === NULL) { return "Missing compulsory array [storagegroup]"; }
    +        if (!is_array($storageGroup)) { return "[storagegroup] must be an array"; }
    +        if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; }
    +        
    +        if ($baseDn === NULL) {
    +            $baseDn = $this->adldap->getBaseDn();   
    +        }
    +        
    +        $container = "CN=" . implode(",CN=", $storageGroup);
    +        
    +        if ($mailNickname === NULL) { 
    +            $mailNickname = $username; 
    +        }
    +        $mdbUseDefaults = $this->adldap->utilities()->boolToString($useDefaults);
    +        
    +        $attributes = array(
    +            'exchange_homemdb'=>$container.",".$baseDn,
    +            'exchange_proxyaddress'=>'SMTP:' . $emailAddress,
    +            'exchange_mailnickname'=>$mailNickname,
    +            'exchange_usedefaults'=>$mdbUseDefaults
    +        );
    +        $result = $this->adldap->user()->modify($username, $attributes, $isGUID);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Add an X400 address to Exchange
    +    * See http://tools.ietf.org/html/rfc1685 for more information.
    +    * An X400 Address looks similar to this X400:c=US;a= ;p=Domain;o=Organization;s=Doe;g=John;
    +    * 
    +    * @param string $username The username of the user to add the X400 to to
    +    * @param string $country Country
    +    * @param string $admd Administration Management Domain
    +    * @param string $pdmd Private Management Domain (often your AD domain)
    +    * @param string $org Organization
    +    * @param string $surname Surname
    +    * @param string $givenName Given name
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function addX400($username, $country, $admd, $pdmd, $org, $surname, $givenName, $isGUID=false) 
    +    {
    +        if ($username === NULL){ return "Missing compulsory field [username]"; }     
    +        
    +        $proxyValue = 'X400:';
    +            
    +        // Find the dn of the user
    +        $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
    +        if ($user[0]["dn"] === NULL) { return false; }
    +        $userDn = $user[0]["dn"];
    +        
    +        // We do not have to demote an email address from the default so we can just add the new proxy address
    +        $attributes['exchange_proxyaddress'] = $proxyValue . 'c=' . $country . ';a=' . $admd . ';p=' . $pdmd . ';o=' . $org . ';s=' . $surname . ';g=' . $givenName . ';';
    +       
    +        // Translate the update to the LDAP schema                
    +        $add = $this->adldap->adldap_schema($attributes);
    +        
    +        if (!$add) { return false; }
    +        
    +        // Do the update
    +        // Take out the @ to see any errors, usually this error might occur because the address already
    +        // exists in the list of proxyAddresses
    +        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn, $add);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Add an address to Exchange
    +    * 
    +    * @param string $username The username of the user to add the Exchange account to
    +    * @param string $emailAddress The email address to add to this user
    +    * @param bool $default Make this email address the default address, this is a bit more intensive as we have to demote any existing default addresses
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function addAddress($username, $emailAddress, $default = FALSE, $isGUID = false) 
    +    {
    +        if ($username === NULL) { return "Missing compulsory field [username]"; }     
    +        if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
    +        
    +        $proxyValue = 'smtp:';
    +        if ($default === true) {
    +            $proxyValue = 'SMTP:';
    +        }
    +              
    +        // Find the dn of the user
    +        $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
    +        if ($user[0]["dn"] === NULL){ return false; }
    +        $userDn = $user[0]["dn"];
    +        
    +        // We need to scan existing proxy addresses and demote the default one
    +        if (is_array($user[0]["proxyaddresses"]) && $default === true) {
    +            $modAddresses = array();
    +            for ($i=0;$iadldap->getLdapConnection(), $userDn, $modAddresses);
    +            if ($result == false) { 
    +                return false; 
    +            }
    +            
    +            return true;
    +        }
    +        else {
    +            // We do not have to demote an email address from the default so we can just add the new proxy address
    +            $attributes['exchange_proxyaddress'] = $proxyValue . $emailAddress;
    +            
    +            // Translate the update to the LDAP schema                
    +            $add = $this->adldap->adldap_schema($attributes);
    +            
    +            if (!$add) { 
    +                return false; 
    +            }
    +            
    +            // Do the update
    +            // Take out the @ to see any errors, usually this error might occur because the address already
    +            // exists in the list of proxyAddresses
    +            $result = @ldap_mod_add($this->adldap->getLdapConnection(), $userDn,$add);
    +            if ($result == false) { 
    +                return false; 
    +            }
    +            
    +            return true;
    +        }
    +    }
    +    
    +    /**
    +    * Remove an address to Exchange
    +    * If you remove a default address the account will no longer have a default, 
    +    * we recommend changing the default address first
    +    * 
    +    * @param string $username The username of the user to add the Exchange account to
    +    * @param string $emailAddress The email address to add to this user
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function deleteAddress($username, $emailAddress, $isGUID=false) 
    +    {
    +        if ($username === NULL) { return "Missing compulsory field [username]"; }     
    +        if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
    +        
    +        // Find the dn of the user
    +        $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
    +        if ($user[0]["dn"] === NULL) { return false; }
    +        $userDn = $user[0]["dn"];
    +        
    +        if (is_array($user[0]["proxyaddresses"])) {
    +            $mod = array();
    +            for ($i=0;$iadldap->getLdapConnection(), $userDn,$mod);
    +            if ($result == false) { 
    +                return false; 
    +            }
    +            
    +            return true;
    +        }
    +        else {
    +            return false;
    +        }
    +    }
    +    /**
    +    * Change the default address
    +    * 
    +    * @param string $username The username of the user to add the Exchange account to
    +    * @param string $emailAddress The email address to make default
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function primaryAddress($username, $emailAddress, $isGUID = false) 
    +    {
    +        if ($username === NULL) { return "Missing compulsory field [username]"; }     
    +        if ($emailAddress === NULL) { return "Missing compulsory fields [emailAddress]"; }
    +        
    +        // Find the dn of the user
    +        $user = $this->adldap->user()->info($username, array("cn","proxyaddresses"), $isGUID);
    +        if ($user[0]["dn"] === NULL){ return false; }
    +        $userDn = $user[0]["dn"];
    +        
    +        if (is_array($user[0]["proxyaddresses"])) {
    +            $modAddresses = array();
    +            for ($i=0;$iadldap->getLdapConnection(), $userDn, $modAddresses);
    +            if ($result == false) { 
    +                return false; 
    +            }
    +            
    +            return true;
    +        }
    +        
    +    }
    +    
    +    /**
    +    * Mail enable a contact
    +    * Allows email to be sent to them through Exchange
    +    * 
    +    * @param string $distinguishedName The contact to mail enable
    +    * @param string $emailAddress The email address to allow emails to be sent through
    +    * @param string $mailNickname The mailnickname for the contact in Exchange.  If NULL this will be set to the display name
    +    * @return bool
    +    */
    +    public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL)
    +    {
    +        if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedName]"; }   
    +        if ($emailAddress === NULL) { return "Missing compulsory field [emailAddress]"; }  
    +        
    +        if ($mailNickname !== NULL) {
    +            // Find the dn of the user
    +            $user = $this->adldap->contact()->info($distinguishedName, array("cn","displayname"));
    +            if ($user[0]["displayname"] === NULL) { return false; }
    +            $mailNickname = $user[0]['displayname'][0];
    +        }
    +        
    +        $attributes = array("email"=>$emailAddress,"contact_email"=>"SMTP:" . $emailAddress,"exchange_proxyaddress"=>"SMTP:" . $emailAddress,"exchange_mailnickname" => $mailNickname);
    +         
    +        // Translate the update to the LDAP schema                
    +        $mod = $this->adldap->adldap_schema($attributes);
    +        
    +        // Check to see if this is an enabled status update
    +        if (!$mod) { return false; }
    +        
    +        // Do the update
    +        $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
    +        if ($result == false) { return false; }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Returns a list of Exchange Servers in the ConfigurationNamingContext of the domain
    +    * 
    +    * @param array $attributes An array of the AD attributes you wish to return
    +    * @return array
    +    */
    +    public function servers($attributes = array('cn','distinguishedname','serialnumber')) 
    +    {
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +        
    +        $configurationNamingContext = $this->adldap->getRootDse(array('configurationnamingcontext'));
    +        $sr = @ldap_search($this->adldap->getLdapConnection(), $configurationNamingContext[0]['configurationnamingcontext'][0],'(&(objectCategory=msExchExchangeServer))', $attributes);
    +        $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +        return $entries;
    +    }
    +    
    +    /**
    +    * Returns a list of Storage Groups in Exchange for a given mail server
    +    * 
    +    * @param string $exchangeServer The full DN of an Exchange server.  You can use exchange_servers() to find the DN for your server
    +    * @param array $attributes An array of the AD attributes you wish to return
    +    * @param bool $recursive If enabled this will automatically query the databases within a storage group
    +    * @return array
    +    */
    +    public function storageGroups($exchangeServer, $attributes = array('cn','distinguishedname'), $recursive = NULL) 
    +    {
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +        if ($exchangeServer === NULL) { return "Missing compulsory field [exchangeServer]"; }
    +        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); }
    +
    +        $filter = '(&(objectCategory=msExchStorageGroup))';
    +        $sr = @ldap_search($this->adldap->getLdapConnection(), $exchangeServer, $filter, $attributes);
    +        $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +        if ($recursive === true) {
    +            for ($i=0; $i<$entries['count']; $i++) {
    +                $entries[$i]['msexchprivatemdb'] = $this->storageDatabases($entries[$i]['distinguishedname'][0]);       
    +            }
    +        }
    +        
    +        return $entries;
    +    }
    +    
    +    /**
    +    * Returns a list of Databases within any given storage group in Exchange for a given mail server
    +    * 
    +    * @param string $storageGroup The full DN of an Storage Group.  You can use exchange_storage_groups() to find the DN 
    +    * @param array $attributes An array of the AD attributes you wish to return
    +    * @return array
    +    */
    +    public function storageDatabases($storageGroup, $attributes = array('cn','distinguishedname','displayname')) {
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +        if ($storageGroup === NULL) { return "Missing compulsory field [storageGroup]"; }
    +        
    +        $filter = '(&(objectCategory=msExchPrivateMDB))';
    +        $sr = @ldap_search($this->adldap->getLdapConnection(), $storageGroup, $filter, $attributes);
    +        $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +        return $entries;
    +    }
    +}
     ?>
    \ No newline at end of file
    diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPFolders.php b/lib/plugins/authad/adLDAP/classes/adLDAPFolders.php
    index 55120152d..67b1474db 100644
    --- a/lib/plugins/authad/adLDAP/classes/adLDAPFolders.php
    +++ b/lib/plugins/authad/adLDAP/classes/adLDAPFolders.php
    @@ -1,179 +1,179 @@
    -adldap = $adldap;
    -    }
    -    
    -    /**
    -    * Delete a distinguished name from Active Directory
    -    * You should never need to call this yourself, just use the wrapper functions user_delete and contact_delete
    -    *
    -    * @param string $dn The distinguished name to delete
    -    * @return bool
    -    */
    -    public function delete($dn){ 
    -        $result = ldap_delete($this->adldap->getLdapConnection(), $dn);
    -        if ($result != true) { 
    -            return false; 
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Returns a folder listing for a specific OU
    -    * See http://adldap.sourceforge.net/wiki/doku.php?id=api_folder_functions
    -    * 
    -    * @param array $folderName An array to the OU you wish to list. 
    -    *                           If set to NULL will list the root, strongly recommended to set 
    -    *                           $recursive to false in that instance!
    -    * @param string $dnType The type of record to list.  This can be ADLDAP_FOLDER or ADLDAP_CONTAINER.
    -    * @param bool $recursive Recursively search sub folders
    -    * @param bool $type Specify a type of object to search for
    -    * @return array
    -    */
    -    public function listing($folderName = NULL, $dnType = adLDAP::ADLDAP_FOLDER, $recursive = NULL, $type = NULL) 
    -    {
    -        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -
    -        $filter = '(&';
    -        if ($type !== NULL) {
    -            switch ($type) {
    -                case 'contact':
    -                    $filter .= '(objectClass=contact)';
    -                    break;
    -                case 'computer':
    -                    $filter .= '(objectClass=computer)';
    -                    break;
    -                case 'group':
    -                    $filter .= '(objectClass=group)';
    -                    break;
    -                case 'folder':
    -                    $filter .= '(objectClass=organizationalUnit)';
    -                    break;
    -                case 'container':
    -                    $filter .= '(objectClass=container)';
    -                    break;
    -                case 'domain':
    -                    $filter .= '(objectClass=builtinDomain)';
    -                    break;
    -                default:
    -                    $filter .= '(objectClass=user)';
    -                    break;   
    -            }
    -        }
    -        else {
    -            $filter .= '(objectClass=*)';   
    -        }
    -        // If the folder name is null then we will search the root level of AD
    -        // This requires us to not have an OU= part, just the base_dn
    -        $searchOu = $this->adldap->getBaseDn();
    -        if (is_array($folderName)) {
    -            $ou = $dnType . "=" . implode("," . $dnType . "=", $folderName);
    -            $filter .= '(!(distinguishedname=' . $ou . ',' . $this->adldap->getBaseDn() . ')))';
    -            $searchOu = $ou . ',' . $this->adldap->getBaseDn();
    -        }
    -        else {
    -            $filter .= '(!(distinguishedname=' . $this->adldap->getBaseDn() . ')))';
    -        }
    -
    -        if ($recursive === true) {
    -            $sr = ldap_search($this->adldap->getLdapConnection(), $searchOu, $filter, array('objectclass', 'distinguishedname', 'samaccountname'));
    -            $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -            if (is_array($entries)) {
    -                return $entries;
    -            }
    -        }
    -        else {
    -            $sr = ldap_list($this->adldap->getLdapConnection(), $searchOu, $filter, array('objectclass', 'distinguishedname', 'samaccountname'));
    -            $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -            if (is_array($entries)) {
    -                return $entries;
    -            }
    -        }
    -        
    -        return false;
    -    }
    -
    -    /**
    -    * Create an organizational unit
    -    * 
    -    * @param array $attributes Default attributes of the ou
    -    * @return bool
    -    */
    -    public function create($attributes)
    -    {
    -        if (!is_array($attributes)){ return "Attributes must be an array"; }
    -        if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
    -        if (!array_key_exists("ou_name",$attributes)) { return "Missing compulsory field [ou_name]"; }
    -        if (!array_key_exists("container",$attributes)) { return "Missing compulsory field [container]"; }
    -        
    -        $attributes["container"] = array_reverse($attributes["container"]);
    -
    -        $add=array();
    -        $add["objectClass"] = "organizationalUnit";
    -        $add["OU"] = $attributes['ou_name'];
    -        $containers = "";
    -        if (count($attributes['container']) > 0) {
    -            $containers = "OU=" . implode(",OU=", $attributes["container"]) . ",";
    -        }
    -
    -        $containers = "OU=" . implode(",OU=", $attributes["container"]);
    -        $result = ldap_add($this->adldap->getLdapConnection(), "OU=" . $add["OU"] . ", " . $containers . $this->adldap->getBaseDn(), $add);
    -        if ($result != true) { 
    -            return false; 
    -        }
    -        
    -        return true;
    -    }
    -    
    -}
    -
    +adldap = $adldap;
    +    }
    +    
    +    /**
    +    * Delete a distinguished name from Active Directory
    +    * You should never need to call this yourself, just use the wrapper functions user_delete and contact_delete
    +    *
    +    * @param string $dn The distinguished name to delete
    +    * @return bool
    +    */
    +    public function delete($dn){ 
    +        $result = ldap_delete($this->adldap->getLdapConnection(), $dn);
    +        if ($result != true) { 
    +            return false; 
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Returns a folder listing for a specific OU
    +    * See http://adldap.sourceforge.net/wiki/doku.php?id=api_folder_functions
    +    * 
    +    * @param array $folderName An array to the OU you wish to list. 
    +    *                           If set to NULL will list the root, strongly recommended to set 
    +    *                           $recursive to false in that instance!
    +    * @param string $dnType The type of record to list.  This can be ADLDAP_FOLDER or ADLDAP_CONTAINER.
    +    * @param bool $recursive Recursively search sub folders
    +    * @param bool $type Specify a type of object to search for
    +    * @return array
    +    */
    +    public function listing($folderName = NULL, $dnType = adLDAP::ADLDAP_FOLDER, $recursive = NULL, $type = NULL) 
    +    {
    +        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +
    +        $filter = '(&';
    +        if ($type !== NULL) {
    +            switch ($type) {
    +                case 'contact':
    +                    $filter .= '(objectClass=contact)';
    +                    break;
    +                case 'computer':
    +                    $filter .= '(objectClass=computer)';
    +                    break;
    +                case 'group':
    +                    $filter .= '(objectClass=group)';
    +                    break;
    +                case 'folder':
    +                    $filter .= '(objectClass=organizationalUnit)';
    +                    break;
    +                case 'container':
    +                    $filter .= '(objectClass=container)';
    +                    break;
    +                case 'domain':
    +                    $filter .= '(objectClass=builtinDomain)';
    +                    break;
    +                default:
    +                    $filter .= '(objectClass=user)';
    +                    break;   
    +            }
    +        }
    +        else {
    +            $filter .= '(objectClass=*)';   
    +        }
    +        // If the folder name is null then we will search the root level of AD
    +        // This requires us to not have an OU= part, just the base_dn
    +        $searchOu = $this->adldap->getBaseDn();
    +        if (is_array($folderName)) {
    +            $ou = $dnType . "=" . implode("," . $dnType . "=", $folderName);
    +            $filter .= '(!(distinguishedname=' . $ou . ',' . $this->adldap->getBaseDn() . ')))';
    +            $searchOu = $ou . ',' . $this->adldap->getBaseDn();
    +        }
    +        else {
    +            $filter .= '(!(distinguishedname=' . $this->adldap->getBaseDn() . ')))';
    +        }
    +
    +        if ($recursive === true) {
    +            $sr = ldap_search($this->adldap->getLdapConnection(), $searchOu, $filter, array('objectclass', 'distinguishedname', 'samaccountname'));
    +            $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +            if (is_array($entries)) {
    +                return $entries;
    +            }
    +        }
    +        else {
    +            $sr = ldap_list($this->adldap->getLdapConnection(), $searchOu, $filter, array('objectclass', 'distinguishedname', 'samaccountname'));
    +            $entries = @ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +            if (is_array($entries)) {
    +                return $entries;
    +            }
    +        }
    +        
    +        return false;
    +    }
    +
    +    /**
    +    * Create an organizational unit
    +    * 
    +    * @param array $attributes Default attributes of the ou
    +    * @return bool
    +    */
    +    public function create($attributes)
    +    {
    +        if (!is_array($attributes)){ return "Attributes must be an array"; }
    +        if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
    +        if (!array_key_exists("ou_name",$attributes)) { return "Missing compulsory field [ou_name]"; }
    +        if (!array_key_exists("container",$attributes)) { return "Missing compulsory field [container]"; }
    +        
    +        $attributes["container"] = array_reverse($attributes["container"]);
    +
    +        $add=array();
    +        $add["objectClass"] = "organizationalUnit";
    +        $add["OU"] = $attributes['ou_name'];
    +        $containers = "";
    +        if (count($attributes['container']) > 0) {
    +            $containers = "OU=" . implode(",OU=", $attributes["container"]) . ",";
    +        }
    +
    +        $containers = "OU=" . implode(",OU=", $attributes["container"]);
    +        $result = ldap_add($this->adldap->getLdapConnection(), "OU=" . $add["OU"] . ", " . $containers . $this->adldap->getBaseDn(), $add);
    +        if ($result != true) { 
    +            return false; 
    +        }
    +        
    +        return true;
    +    }
    +    
    +}
    +
     ?>
    \ No newline at end of file
    diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php b/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php
    index 05e4cc93b..94bc04853 100644
    --- a/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php
    +++ b/lib/plugins/authad/adLDAP/classes/adLDAPGroups.php
    @@ -1,631 +1,631 @@
    -adldap = $adldap;
    -    }
    -    
    -    /**
    -    * Add a group to a group
    -    * 
    -    * @param string $parent The parent group name
    -    * @param string $child The child group name
    -    * @return bool
    -    */
    -    public function addGroup($parent,$child){
    -
    -        // Find the parent group's dn
    -        $parentGroup = $this->ginfo($parent, array("cn"));
    -        if ($parentGroup[0]["dn"] === NULL){
    -            return false; 
    -        }
    -        $parentDn = $parentGroup[0]["dn"];
    -        
    -        // Find the child group's dn
    -        $childGroup = $this->info($child, array("cn"));
    -        if ($childGroup[0]["dn"] === NULL){ 
    -            return false; 
    -        }
    -        $childDn = $childGroup[0]["dn"];
    -                
    -        $add = array();
    -        $add["member"] = $childDn;
    -        
    -        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $parentDn, $add);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Add a user to a group
    -    * 
    -    * @param string $group The group to add the user to
    -    * @param string $user The user to add to the group
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function addUser($group, $user, $isGUID = false)
    -    {
    -        // Adding a user is a bit fiddly, we need to get the full DN of the user
    -        // and add it using the full DN of the group
    -        
    -        // Find the user's dn
    -        $userDn = $this->adldap->user()->dn($user, $isGUID);
    -        if ($userDn === false) { 
    -            return false; 
    -        }
    -        
    -        // Find the group's dn
    -        $groupInfo = $this->info($group, array("cn"));
    -        if ($groupInfo[0]["dn"] === NULL) { 
    -            return false; 
    -        }
    -        $groupDn = $groupInfo[0]["dn"];
    -        
    -        $add = array();
    -        $add["member"] = $userDn;
    -        
    -        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Add a contact to a group
    -    * 
    -    * @param string $group The group to add the contact to
    -    * @param string $contactDn The DN of the contact to add
    -    * @return bool
    -    */
    -    public function addContact($group, $contactDn)
    -    {
    -        // To add a contact we take the contact's DN
    -        // and add it using the full DN of the group
    -        
    -        // Find the group's dn
    -        $groupInfo = $this->info($group, array("cn"));
    -        if ($groupInfo[0]["dn"] === NULL) { 
    -            return false; 
    -        }
    -        $groupDn = $groupInfo[0]["dn"];
    -        
    -        $add = array();
    -        $add["member"] = $contactDn;
    -        
    -        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        return true;
    -    }
    -
    -    /**
    -    * Create a group
    -    * 
    -    * @param array $attributes Default attributes of the group
    -    * @return bool
    -    */
    -    public function create($attributes)
    -    {
    -        if (!is_array($attributes)){ return "Attributes must be an array"; }
    -        if (!array_key_exists("group_name", $attributes)){ return "Missing compulsory field [group_name]"; }
    -        if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
    -        if (!array_key_exists("description", $attributes)){ return "Missing compulsory field [description]"; }
    -        if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
    -        $attributes["container"] = array_reverse($attributes["container"]);
    -
    -        //$member_array = array();
    -        //$member_array[0] = "cn=user1,cn=Users,dc=yourdomain,dc=com";
    -        //$member_array[1] = "cn=administrator,cn=Users,dc=yourdomain,dc=com";
    -        
    -        $add = array();
    -        $add["cn"] = $attributes["group_name"];
    -        $add["samaccountname"] = $attributes["group_name"];
    -        $add["objectClass"] = "Group";
    -        $add["description"] = $attributes["description"];
    -        //$add["member"] = $member_array; UNTESTED
    -
    -        $container = "OU=" . implode(",OU=", $attributes["container"]);
    -        $result = ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
    -        if ($result != true) { 
    -            return false; 
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Delete a group account 
    -    * 
    -    * @param string $group The group to delete (please be careful here!) 
    -    * 
    -    * @return array 
    -    */
    -    public function delete($group) {
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -        if ($group === null){ return "Missing compulsory field [group]"; }
    -        
    -        $groupInfo = $this->info($group, array("*"));
    -        $dn = $groupInfo[0]['distinguishedname'][0]; 
    -        $result = $this->adldap->folder()->delete($dn); 
    -        if ($result !== true) { 
    -            return false; 
    -        } return true;   
    -    }
    -
    -    /**
    -    * Remove a group from a group
    -    * 
    -    * @param string $parent The parent group name
    -    * @param string $child The child group name
    -    * @return bool
    -    */
    -    public function removeGroup($parent , $child)
    -    {
    -    
    -        // Find the parent dn
    -        $parentGroup = $this->info($parent, array("cn"));
    -        if ($parentGroup[0]["dn"] === NULL) { 
    -            return false; 
    -        }
    -        $parentDn = $parentGroup[0]["dn"];
    -        
    -        // Find the child dn
    -        $childGroup = $this->info($child, array("cn"));
    -        if ($childGroup[0]["dn"] === NULL) { 
    -            return false; 
    -        }
    -        $childDn = $childGroup[0]["dn"];
    -        
    -        $del = array();
    -        $del["member"] = $childDn;
    -        
    -        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $parentDn, $del);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Remove a user from a group
    -    * 
    -    * @param string $group The group to remove a user from
    -    * @param string $user The AD user to remove from the group
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function removeUser($group, $user, $isGUID = false)
    -    {
    -    
    -        // Find the parent dn
    -        $groupInfo = $this->info($group, array("cn"));
    -        if ($groupInfo[0]["dn"] === NULL){ 
    -            return false; 
    -        }
    -        $groupDn = $groupInfo[0]["dn"];
    -        
    -        // Find the users dn
    -        $userDn = $this->adldap->user()->dn($user, $isGUID);
    -        if ($userDn === false) {
    -            return false; 
    -        }
    -
    -        $del = array();
    -        $del["member"] = $userDn;
    -        
    -        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
    -        if ($result == false) {
    -            return false; 
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Remove a contact from a group
    -    * 
    -    * @param string $group The group to remove a user from
    -    * @param string $contactDn The DN of a contact to remove from the group
    -    * @return bool
    -    */
    -    public function removeContact($group, $contactDn)
    -    {
    -    
    -        // Find the parent dn
    -        $groupInfo = $this->info($group, array("cn"));
    -        if ($groupInfo[0]["dn"] === NULL) { 
    -            return false; 
    -        }
    -        $groupDn = $groupInfo[0]["dn"];
    -    
    -        $del = array();
    -        $del["member"] = $contactDn;
    -        
    -        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Return a list of groups in a group
    -    * 
    -    * @param string $group The group to query
    -    * @param bool $recursive Recursively get groups
    -    * @return array
    -    */
    -    public function inGroup($group, $recursive = NULL)
    -    {
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -        if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it 
    -        
    -        // Search the directory for the members of a group
    -        $info = $this->info($group, array("member","cn"));
    -        $groups = $info[0]["member"];
    -        if (!is_array($groups)) {
    -            return false;   
    -        }
    - 
    -        $groupArray = array();
    -
    -        for ($i=0; $i<$groups["count"]; $i++){ 
    -             $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";
    -             $fields = array("samaccountname", "distinguishedname", "objectClass");
    -             $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -             $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -             // not a person, look for a group  
    -             if ($entries['count'] == 0 && $recursive == true) {  
    -                $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";  
    -                $fields = array("distinguishedname");  
    -                $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);  
    -                $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);  
    -                if (!isset($entries[0]['distinguishedname'][0])) {
    -                    continue;  
    -                }
    -                $subGroups = $this->inGroup($entries[0]['distinguishedname'][0], $recursive);  
    -                if (is_array($subGroups)) {
    -                    $groupArray = array_merge($groupArray, $subGroups); 
    -                    $groupArray = array_unique($groupArray);  
    -                }
    -                continue;  
    -             } 
    -
    -             $groupArray[] = $entries[0]['distinguishedname'][0];
    -        }
    -        return $groupArray;
    -    }
    -    
    -    /**
    -    * Return a list of members in a group
    -    * 
    -    * @param string $group The group to query
    -    * @param bool $recursive Recursively get group members
    -    * @return array
    -    */
    -    public function members($group, $recursive = NULL)
    -    {
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -        if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it 
    -        // Search the directory for the members of a group
    -        $info = $this->info($group, array("member","cn"));
    -        $users = $info[0]["member"];
    -        if (!is_array($users)) {
    -            return false;   
    -        }
    - 
    -        $userArray = array();
    -
    -        for ($i=0; $i<$users["count"]; $i++){ 
    -             $filter = "(&(objectCategory=person)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";
    -             $fields = array("samaccountname", "distinguishedname", "objectClass");
    -             $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -             $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -             // not a person, look for a group  
    -             if ($entries['count'] == 0 && $recursive == true) {  
    -                $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";  
    -                $fields = array("samaccountname");  
    -                $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);  
    -                $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);  
    -                if (!isset($entries[0]['samaccountname'][0])) {
    -                    continue;  
    -                }
    -                $subUsers = $this->members($entries[0]['samaccountname'][0], $recursive);  
    -                if (is_array($subUsers)) {
    -                    $userArray = array_merge($userArray, $subUsers); 
    -                    $userArray = array_unique($userArray);  
    -                }
    -                continue;  
    -             } 
    -             else if ($entries['count'] == 0) {   
    -                continue; 
    -             } 
    -
    -             if ((!isset($entries[0]['samaccountname'][0]) || $entries[0]['samaccountname'][0] === NULL) && $entries[0]['distinguishedname'][0] !== NULL) {
    -                 $userArray[] = $entries[0]['distinguishedname'][0];
    -             }
    -             else if ($entries[0]['samaccountname'][0] !== NULL) {
    -                $userArray[] = $entries[0]['samaccountname'][0];
    -             }
    -        }
    -        return $userArray;
    -    }
    -    
    -    /**
    -    * Group Information.  Returns an array of raw information about a group.
    -    * The group name is case sensitive
    -    * 
    -    * @param string $groupName The group name to retrieve info about
    -    * @param array $fields Fields to retrieve
    -    * @return array
    -    */
    -    public function info($groupName, $fields = NULL)
    -    {
    -        if ($groupName === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        if (stristr($groupName, '+')) {
    -            $groupName = stripslashes($groupName);   
    -        }
    -        
    -        $filter = "(&(objectCategory=group)(name=" . $this->adldap->utilities()->ldapSlashes($groupName) . "))";
    -        if ($fields === NULL) { 
    -            $fields = array("member","memberof","cn","description","distinguishedname","objectcategory","samaccountname"); 
    -        }
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -        return $entries;
    -    }
    -    
    -    /**
    -    * Group Information.  Returns an collection
    -    * The group name is case sensitive
    -    * 
    -    * @param string $groupName The group name to retrieve info about
    -    * @param array $fields Fields to retrieve
    -    * @return adLDAPGroupCollection
    -    */
    -    public function infoCollection($groupName, $fields = NULL)
    -    {
    -        if ($groupName === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        $info = $this->info($groupName, $fields);
    -        if ($info !== false) {
    -            $collection = new adLDAPGroupCollection($info, $this->adldap);
    -            return $collection;
    -        }
    -        return false;
    -    }
    -    
    -    /**
    -    * Return a complete list of "groups in groups"
    -    * 
    -    * @param string $group The group to get the list from
    -    * @return array
    -    */
    -    public function recursiveGroups($group)
    -    {
    -        if ($group === NULL) { return false; }
    -
    -        $stack = array(); 
    -        $processed = array(); 
    -        $retGroups = array(); 
    -     
    -        array_push($stack, $group); // Initial Group to Start with 
    -        while (count($stack) > 0) {
    -            $parent = array_pop($stack);
    -            array_push($processed, $parent);
    -            
    -            $info = $this->info($parent, array("memberof"));
    -            
    -            if (isset($info[0]["memberof"]) && is_array($info[0]["memberof"])) {
    -                $groups = $info[0]["memberof"]; 
    -                if ($groups) {
    -                    $groupNames = $this->adldap->utilities()->niceNames($groups);  
    -                    $retGroups = array_merge($retGroups, $groupNames); //final groups to return
    -                    foreach ($groupNames as $id => $groupName) { 
    -                        if (!in_array($groupName, $processed)) {
    -                            array_push($stack, $groupName);
    -                        }
    -                    }
    -                }
    -            }
    -        }
    -        
    -        return $retGroups;
    -    }
    -    
    -    /**
    -    * Returns a complete list of the groups in AD based on a SAM Account Type  
    -    * 
    -    * @param string $sAMAaccountType The account type to return
    -    * @param bool $includeDescription Whether to return a description
    -    * @param string $search Search parameters
    -    * @param bool $sorted Whether to sort the results
    -    * @return array
    -    */
    -    public function search($sAMAaccountType = adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription = false, $search = "*", $sorted = true) {
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        $filter = '(&(objectCategory=group)';
    -        if ($sAMAaccountType !== null) {
    -            $filter .= '(samaccounttype='. $sAMAaccountType .')';
    -        }
    -        $filter .= '(cn=' . $search . '))';
    -        // Perform the search and grab all their details
    -        $fields = array("samaccountname", "description");
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -        $groupsArray = array();        
    -        for ($i=0; $i<$entries["count"]; $i++){
    -            if ($includeDescription && strlen($entries[$i]["description"][0]) > 0 ) {
    -                $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["description"][0];
    -            }
    -            else if ($includeDescription){
    -                $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
    -            }
    -            else {
    -                array_push($groupsArray, $entries[$i]["samaccountname"][0]);
    -            }
    -        }
    -        if ($sorted) { 
    -            asort($groupsArray); 
    -        }
    -        return $groupsArray;
    -    }
    -    
    -    /**
    -    * Returns a complete list of all groups in AD
    -    * 
    -    * @param bool $includeDescription Whether to return a description
    -    * @param string $search Search parameters
    -    * @param bool $sorted Whether to sort the results
    -    * @return array
    -    */
    -    public function all($includeDescription = false, $search = "*", $sorted = true){
    -        $groupsArray = $this->search(null, $includeDescription, $search, $sorted);
    -        return $groupsArray;
    -    }
    -    
    -    /**
    -    * Returns a complete list of security groups in AD
    -    * 
    -    * @param bool $includeDescription Whether to return a description
    -    * @param string $search Search parameters
    -    * @param bool $sorted Whether to sort the results
    -    * @return array
    -    */
    -    public function allSecurity($includeDescription = false, $search = "*", $sorted = true){
    -        $groupsArray = $this->search(adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription, $search, $sorted);
    -        return $groupsArray;
    -    }
    -    
    -    /**
    -    * Returns a complete list of distribution lists in AD
    -    * 
    -    * @param bool $includeDescription Whether to return a description
    -    * @param string $search Search parameters
    -    * @param bool $sorted Whether to sort the results
    -    * @return array
    -    */
    -    public function allDistribution($includeDescription = false, $search = "*", $sorted = true){
    -        $groupsArray = $this->search(adLDAP::ADLDAP_DISTRIBUTION_GROUP, $includeDescription, $search, $sorted);
    -        return $groupsArray;
    -    }
    -    
    -    /**
    -    * Coping with AD not returning the primary group
    -    * http://support.microsoft.com/?kbid=321360 
    -    * 
    -    * This is a re-write based on code submitted by Bruce which prevents the 
    -    * need to search each security group to find the true primary group
    -    * 
    -    * @param string $gid Group ID
    -    * @param string $usersid User's Object SID
    -    * @return mixed
    -    */
    -    public function getPrimaryGroup($gid, $usersid)
    -    {
    -        if ($gid === NULL || $usersid === NULL) { return false; }
    -        $sr = false;
    -
    -        $gsid = substr_replace($usersid, pack('V',$gid), strlen($usersid)-4,4);
    -        $filter = '(objectsid=' . $this->adldap->utilities()->getTextSID($gsid).')';
    -        $fields = array("samaccountname","distinguishedname");
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -        if (isset($entries[0]['distinguishedname'][0])) {
    -            return $entries[0]['distinguishedname'][0];
    -        }
    -        return false;
    -     }
    -     
    -     /**
    -    * Coping with AD not returning the primary group
    -    * http://support.microsoft.com/?kbid=321360 
    -    * 
    -    * For some reason it's not possible to search on primarygrouptoken=XXX
    -    * If someone can show otherwise, I'd like to know about it :)
    -    * this way is resource intensive and generally a pain in the @#%^
    -    * 
    -    * @deprecated deprecated since version 3.1, see get get_primary_group
    -    * @param string $gid Group ID
    -    * @return string
    -    */
    -    public function cn($gid){    
    -        if ($gid === NULL) { return false; }
    -        $sr = false;
    -        $r = '';
    -        
    -        $filter = "(&(objectCategory=group)(samaccounttype=" . adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP . "))";
    -        $fields = array("primarygrouptoken", "samaccountname", "distinguishedname");
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -        
    -        for ($i=0; $i<$entries["count"]; $i++){
    -            if ($entries[$i]["primarygrouptoken"][0] == $gid) {
    -                $r = $entries[$i]["distinguishedname"][0];
    -                $i = $entries["count"];
    -            }
    -        }
    -
    -        return $r;
    -    }
    -}
    -?>
    +adldap = $adldap;
    +    }
    +    
    +    /**
    +    * Add a group to a group
    +    * 
    +    * @param string $parent The parent group name
    +    * @param string $child The child group name
    +    * @return bool
    +    */
    +    public function addGroup($parent,$child){
    +
    +        // Find the parent group's dn
    +        $parentGroup = $this->ginfo($parent, array("cn"));
    +        if ($parentGroup[0]["dn"] === NULL){
    +            return false; 
    +        }
    +        $parentDn = $parentGroup[0]["dn"];
    +        
    +        // Find the child group's dn
    +        $childGroup = $this->info($child, array("cn"));
    +        if ($childGroup[0]["dn"] === NULL){ 
    +            return false; 
    +        }
    +        $childDn = $childGroup[0]["dn"];
    +                
    +        $add = array();
    +        $add["member"] = $childDn;
    +        
    +        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $parentDn, $add);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Add a user to a group
    +    * 
    +    * @param string $group The group to add the user to
    +    * @param string $user The user to add to the group
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function addUser($group, $user, $isGUID = false)
    +    {
    +        // Adding a user is a bit fiddly, we need to get the full DN of the user
    +        // and add it using the full DN of the group
    +        
    +        // Find the user's dn
    +        $userDn = $this->adldap->user()->dn($user, $isGUID);
    +        if ($userDn === false) { 
    +            return false; 
    +        }
    +        
    +        // Find the group's dn
    +        $groupInfo = $this->info($group, array("cn"));
    +        if ($groupInfo[0]["dn"] === NULL) { 
    +            return false; 
    +        }
    +        $groupDn = $groupInfo[0]["dn"];
    +        
    +        $add = array();
    +        $add["member"] = $userDn;
    +        
    +        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Add a contact to a group
    +    * 
    +    * @param string $group The group to add the contact to
    +    * @param string $contactDn The DN of the contact to add
    +    * @return bool
    +    */
    +    public function addContact($group, $contactDn)
    +    {
    +        // To add a contact we take the contact's DN
    +        // and add it using the full DN of the group
    +        
    +        // Find the group's dn
    +        $groupInfo = $this->info($group, array("cn"));
    +        if ($groupInfo[0]["dn"] === NULL) { 
    +            return false; 
    +        }
    +        $groupDn = $groupInfo[0]["dn"];
    +        
    +        $add = array();
    +        $add["member"] = $contactDn;
    +        
    +        $result = @ldap_mod_add($this->adldap->getLdapConnection(), $groupDn, $add);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        return true;
    +    }
    +
    +    /**
    +    * Create a group
    +    * 
    +    * @param array $attributes Default attributes of the group
    +    * @return bool
    +    */
    +    public function create($attributes)
    +    {
    +        if (!is_array($attributes)){ return "Attributes must be an array"; }
    +        if (!array_key_exists("group_name", $attributes)){ return "Missing compulsory field [group_name]"; }
    +        if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
    +        if (!array_key_exists("description", $attributes)){ return "Missing compulsory field [description]"; }
    +        if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
    +        $attributes["container"] = array_reverse($attributes["container"]);
    +
    +        //$member_array = array();
    +        //$member_array[0] = "cn=user1,cn=Users,dc=yourdomain,dc=com";
    +        //$member_array[1] = "cn=administrator,cn=Users,dc=yourdomain,dc=com";
    +        
    +        $add = array();
    +        $add["cn"] = $attributes["group_name"];
    +        $add["samaccountname"] = $attributes["group_name"];
    +        $add["objectClass"] = "Group";
    +        $add["description"] = $attributes["description"];
    +        //$add["member"] = $member_array; UNTESTED
    +
    +        $container = "OU=" . implode(",OU=", $attributes["container"]);
    +        $result = ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
    +        if ($result != true) { 
    +            return false; 
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Delete a group account 
    +    * 
    +    * @param string $group The group to delete (please be careful here!) 
    +    * 
    +    * @return array 
    +    */
    +    public function delete($group) {
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +        if ($group === null){ return "Missing compulsory field [group]"; }
    +        
    +        $groupInfo = $this->info($group, array("*"));
    +        $dn = $groupInfo[0]['distinguishedname'][0]; 
    +        $result = $this->adldap->folder()->delete($dn); 
    +        if ($result !== true) { 
    +            return false; 
    +        } return true;   
    +    }
    +
    +    /**
    +    * Remove a group from a group
    +    * 
    +    * @param string $parent The parent group name
    +    * @param string $child The child group name
    +    * @return bool
    +    */
    +    public function removeGroup($parent , $child)
    +    {
    +    
    +        // Find the parent dn
    +        $parentGroup = $this->info($parent, array("cn"));
    +        if ($parentGroup[0]["dn"] === NULL) { 
    +            return false; 
    +        }
    +        $parentDn = $parentGroup[0]["dn"];
    +        
    +        // Find the child dn
    +        $childGroup = $this->info($child, array("cn"));
    +        if ($childGroup[0]["dn"] === NULL) { 
    +            return false; 
    +        }
    +        $childDn = $childGroup[0]["dn"];
    +        
    +        $del = array();
    +        $del["member"] = $childDn;
    +        
    +        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $parentDn, $del);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Remove a user from a group
    +    * 
    +    * @param string $group The group to remove a user from
    +    * @param string $user The AD user to remove from the group
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function removeUser($group, $user, $isGUID = false)
    +    {
    +    
    +        // Find the parent dn
    +        $groupInfo = $this->info($group, array("cn"));
    +        if ($groupInfo[0]["dn"] === NULL){ 
    +            return false; 
    +        }
    +        $groupDn = $groupInfo[0]["dn"];
    +        
    +        // Find the users dn
    +        $userDn = $this->adldap->user()->dn($user, $isGUID);
    +        if ($userDn === false) {
    +            return false; 
    +        }
    +
    +        $del = array();
    +        $del["member"] = $userDn;
    +        
    +        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
    +        if ($result == false) {
    +            return false; 
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Remove a contact from a group
    +    * 
    +    * @param string $group The group to remove a user from
    +    * @param string $contactDn The DN of a contact to remove from the group
    +    * @return bool
    +    */
    +    public function removeContact($group, $contactDn)
    +    {
    +    
    +        // Find the parent dn
    +        $groupInfo = $this->info($group, array("cn"));
    +        if ($groupInfo[0]["dn"] === NULL) { 
    +            return false; 
    +        }
    +        $groupDn = $groupInfo[0]["dn"];
    +    
    +        $del = array();
    +        $del["member"] = $contactDn;
    +        
    +        $result = @ldap_mod_del($this->adldap->getLdapConnection(), $groupDn, $del);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Return a list of groups in a group
    +    * 
    +    * @param string $group The group to query
    +    * @param bool $recursive Recursively get groups
    +    * @return array
    +    */
    +    public function inGroup($group, $recursive = NULL)
    +    {
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +        if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it 
    +        
    +        // Search the directory for the members of a group
    +        $info = $this->info($group, array("member","cn"));
    +        $groups = $info[0]["member"];
    +        if (!is_array($groups)) {
    +            return false;   
    +        }
    + 
    +        $groupArray = array();
    +
    +        for ($i=0; $i<$groups["count"]; $i++){ 
    +             $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";
    +             $fields = array("samaccountname", "distinguishedname", "objectClass");
    +             $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +             $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +             // not a person, look for a group  
    +             if ($entries['count'] == 0 && $recursive == true) {  
    +                $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($groups[$i]) . "))";  
    +                $fields = array("distinguishedname");  
    +                $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);  
    +                $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);  
    +                if (!isset($entries[0]['distinguishedname'][0])) {
    +                    continue;  
    +                }
    +                $subGroups = $this->inGroup($entries[0]['distinguishedname'][0], $recursive);  
    +                if (is_array($subGroups)) {
    +                    $groupArray = array_merge($groupArray, $subGroups); 
    +                    $groupArray = array_unique($groupArray);  
    +                }
    +                continue;  
    +             } 
    +
    +             $groupArray[] = $entries[0]['distinguishedname'][0];
    +        }
    +        return $groupArray;
    +    }
    +    
    +    /**
    +    * Return a list of members in a group
    +    * 
    +    * @param string $group The group to query
    +    * @param bool $recursive Recursively get group members
    +    * @return array
    +    */
    +    public function members($group, $recursive = NULL)
    +    {
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +        if ($recursive === NULL){ $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it 
    +        // Search the directory for the members of a group
    +        $info = $this->info($group, array("member","cn"));
    +        $users = $info[0]["member"];
    +        if (!is_array($users)) {
    +            return false;   
    +        }
    + 
    +        $userArray = array();
    +
    +        for ($i=0; $i<$users["count"]; $i++){ 
    +             $filter = "(&(objectCategory=person)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";
    +             $fields = array("samaccountname", "distinguishedname", "objectClass");
    +             $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +             $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +             // not a person, look for a group  
    +             if ($entries['count'] == 0 && $recursive == true) {  
    +                $filter = "(&(objectCategory=group)(distinguishedName=" . $this->adldap->utilities()->ldapSlashes($users[$i]) . "))";  
    +                $fields = array("samaccountname");  
    +                $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);  
    +                $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);  
    +                if (!isset($entries[0]['samaccountname'][0])) {
    +                    continue;  
    +                }
    +                $subUsers = $this->members($entries[0]['samaccountname'][0], $recursive);  
    +                if (is_array($subUsers)) {
    +                    $userArray = array_merge($userArray, $subUsers); 
    +                    $userArray = array_unique($userArray);  
    +                }
    +                continue;  
    +             } 
    +             else if ($entries['count'] == 0) {   
    +                continue; 
    +             } 
    +
    +             if ((!isset($entries[0]['samaccountname'][0]) || $entries[0]['samaccountname'][0] === NULL) && $entries[0]['distinguishedname'][0] !== NULL) {
    +                 $userArray[] = $entries[0]['distinguishedname'][0];
    +             }
    +             else if ($entries[0]['samaccountname'][0] !== NULL) {
    +                $userArray[] = $entries[0]['samaccountname'][0];
    +             }
    +        }
    +        return $userArray;
    +    }
    +    
    +    /**
    +    * Group Information.  Returns an array of raw information about a group.
    +    * The group name is case sensitive
    +    * 
    +    * @param string $groupName The group name to retrieve info about
    +    * @param array $fields Fields to retrieve
    +    * @return array
    +    */
    +    public function info($groupName, $fields = NULL)
    +    {
    +        if ($groupName === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        if (stristr($groupName, '+')) {
    +            $groupName = stripslashes($groupName);   
    +        }
    +        
    +        $filter = "(&(objectCategory=group)(name=" . $this->adldap->utilities()->ldapSlashes($groupName) . "))";
    +        if ($fields === NULL) { 
    +            $fields = array("member","memberof","cn","description","distinguishedname","objectcategory","samaccountname"); 
    +        }
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +        return $entries;
    +    }
    +    
    +    /**
    +    * Group Information.  Returns an collection
    +    * The group name is case sensitive
    +    * 
    +    * @param string $groupName The group name to retrieve info about
    +    * @param array $fields Fields to retrieve
    +    * @return adLDAPGroupCollection
    +    */
    +    public function infoCollection($groupName, $fields = NULL)
    +    {
    +        if ($groupName === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        $info = $this->info($groupName, $fields);
    +        if ($info !== false) {
    +            $collection = new adLDAPGroupCollection($info, $this->adldap);
    +            return $collection;
    +        }
    +        return false;
    +    }
    +    
    +    /**
    +    * Return a complete list of "groups in groups"
    +    * 
    +    * @param string $group The group to get the list from
    +    * @return array
    +    */
    +    public function recursiveGroups($group)
    +    {
    +        if ($group === NULL) { return false; }
    +
    +        $stack = array(); 
    +        $processed = array(); 
    +        $retGroups = array(); 
    +     
    +        array_push($stack, $group); // Initial Group to Start with 
    +        while (count($stack) > 0) {
    +            $parent = array_pop($stack);
    +            array_push($processed, $parent);
    +            
    +            $info = $this->info($parent, array("memberof"));
    +            
    +            if (isset($info[0]["memberof"]) && is_array($info[0]["memberof"])) {
    +                $groups = $info[0]["memberof"]; 
    +                if ($groups) {
    +                    $groupNames = $this->adldap->utilities()->niceNames($groups);  
    +                    $retGroups = array_merge($retGroups, $groupNames); //final groups to return
    +                    foreach ($groupNames as $id => $groupName) { 
    +                        if (!in_array($groupName, $processed)) {
    +                            array_push($stack, $groupName);
    +                        }
    +                    }
    +                }
    +            }
    +        }
    +        
    +        return $retGroups;
    +    }
    +    
    +    /**
    +    * Returns a complete list of the groups in AD based on a SAM Account Type  
    +    * 
    +    * @param string $sAMAaccountType The account type to return
    +    * @param bool $includeDescription Whether to return a description
    +    * @param string $search Search parameters
    +    * @param bool $sorted Whether to sort the results
    +    * @return array
    +    */
    +    public function search($sAMAaccountType = adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription = false, $search = "*", $sorted = true) {
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        $filter = '(&(objectCategory=group)';
    +        if ($sAMAaccountType !== null) {
    +            $filter .= '(samaccounttype='. $sAMAaccountType .')';
    +        }
    +        $filter .= '(cn=' . $search . '))';
    +        // Perform the search and grab all their details
    +        $fields = array("samaccountname", "description");
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +        $groupsArray = array();        
    +        for ($i=0; $i<$entries["count"]; $i++){
    +            if ($includeDescription && strlen($entries[$i]["description"][0]) > 0 ) {
    +                $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["description"][0];
    +            }
    +            else if ($includeDescription){
    +                $groupsArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
    +            }
    +            else {
    +                array_push($groupsArray, $entries[$i]["samaccountname"][0]);
    +            }
    +        }
    +        if ($sorted) { 
    +            asort($groupsArray); 
    +        }
    +        return $groupsArray;
    +    }
    +    
    +    /**
    +    * Returns a complete list of all groups in AD
    +    * 
    +    * @param bool $includeDescription Whether to return a description
    +    * @param string $search Search parameters
    +    * @param bool $sorted Whether to sort the results
    +    * @return array
    +    */
    +    public function all($includeDescription = false, $search = "*", $sorted = true){
    +        $groupsArray = $this->search(null, $includeDescription, $search, $sorted);
    +        return $groupsArray;
    +    }
    +    
    +    /**
    +    * Returns a complete list of security groups in AD
    +    * 
    +    * @param bool $includeDescription Whether to return a description
    +    * @param string $search Search parameters
    +    * @param bool $sorted Whether to sort the results
    +    * @return array
    +    */
    +    public function allSecurity($includeDescription = false, $search = "*", $sorted = true){
    +        $groupsArray = $this->search(adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP, $includeDescription, $search, $sorted);
    +        return $groupsArray;
    +    }
    +    
    +    /**
    +    * Returns a complete list of distribution lists in AD
    +    * 
    +    * @param bool $includeDescription Whether to return a description
    +    * @param string $search Search parameters
    +    * @param bool $sorted Whether to sort the results
    +    * @return array
    +    */
    +    public function allDistribution($includeDescription = false, $search = "*", $sorted = true){
    +        $groupsArray = $this->search(adLDAP::ADLDAP_DISTRIBUTION_GROUP, $includeDescription, $search, $sorted);
    +        return $groupsArray;
    +    }
    +    
    +    /**
    +    * Coping with AD not returning the primary group
    +    * http://support.microsoft.com/?kbid=321360 
    +    * 
    +    * This is a re-write based on code submitted by Bruce which prevents the 
    +    * need to search each security group to find the true primary group
    +    * 
    +    * @param string $gid Group ID
    +    * @param string $usersid User's Object SID
    +    * @return mixed
    +    */
    +    public function getPrimaryGroup($gid, $usersid)
    +    {
    +        if ($gid === NULL || $usersid === NULL) { return false; }
    +        $sr = false;
    +
    +        $gsid = substr_replace($usersid, pack('V',$gid), strlen($usersid)-4,4);
    +        $filter = '(objectsid=' . $this->adldap->utilities()->getTextSID($gsid).')';
    +        $fields = array("samaccountname","distinguishedname");
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +        if (isset($entries[0]['distinguishedname'][0])) {
    +            return $entries[0]['distinguishedname'][0];
    +        }
    +        return false;
    +     }
    +     
    +     /**
    +    * Coping with AD not returning the primary group
    +    * http://support.microsoft.com/?kbid=321360 
    +    * 
    +    * For some reason it's not possible to search on primarygrouptoken=XXX
    +    * If someone can show otherwise, I'd like to know about it :)
    +    * this way is resource intensive and generally a pain in the @#%^
    +    * 
    +    * @deprecated deprecated since version 3.1, see get get_primary_group
    +    * @param string $gid Group ID
    +    * @return string
    +    */
    +    public function cn($gid){    
    +        if ($gid === NULL) { return false; }
    +        $sr = false;
    +        $r = '';
    +        
    +        $filter = "(&(objectCategory=group)(samaccounttype=" . adLDAP::ADLDAP_SECURITY_GLOBAL_GROUP . "))";
    +        $fields = array("primarygrouptoken", "samaccountname", "distinguishedname");
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +        
    +        for ($i=0; $i<$entries["count"]; $i++){
    +            if ($entries[$i]["primarygrouptoken"][0] == $gid) {
    +                $r = $entries[$i]["distinguishedname"][0];
    +                $i = $entries["count"];
    +            }
    +        }
    +
    +        return $r;
    +    }
    +}
    +?>
    diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPUsers.php b/lib/plugins/authad/adLDAP/classes/adLDAPUsers.php
    index 96a93b512..839fd592d 100644
    --- a/lib/plugins/authad/adLDAP/classes/adLDAPUsers.php
    +++ b/lib/plugins/authad/adLDAP/classes/adLDAPUsers.php
    @@ -1,682 +1,682 @@
    -adldap = $adldap;
    -    }
    -    
    -    /**
    -    * Validate a user's login credentials
    -    * 
    -    * @param string $username A user's AD username
    -    * @param string $password A user's AD password
    -    * @param bool optional $prevent_rebind
    -    * @return bool
    -    */
    -    public function authenticate($username, $password, $preventRebind = false) {
    -        return $this->adldap->authenticate($username, $password, $preventRebind);
    -    }
    -    
    -    /**
    -    * Create a user
    -    * 
    -    * If you specify a password here, this can only be performed over SSL
    -    * 
    -    * @param array $attributes The attributes to set to the user account
    -    * @return bool
    -    */
    -    public function create($attributes)
    -    {
    -        // Check for compulsory fields
    -        if (!array_key_exists("username", $attributes)){ return "Missing compulsory field [username]"; }
    -        if (!array_key_exists("firstname", $attributes)){ return "Missing compulsory field [firstname]"; }
    -        if (!array_key_exists("surname", $attributes)){ return "Missing compulsory field [surname]"; }
    -        if (!array_key_exists("email", $attributes)){ return "Missing compulsory field [email]"; }
    -        if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
    -        if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
    -
    -        if (array_key_exists("password",$attributes) && (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS())){ 
    -            throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
    -        }
    -
    -        if (!array_key_exists("display_name", $attributes)) { 
    -            $attributes["display_name"] = $attributes["firstname"] . " " . $attributes["surname"]; 
    -        }
    -
    -        // Translate the schema
    -        $add = $this->adldap->adldap_schema($attributes);
    -        
    -        // Additional stuff only used for adding accounts
    -        $add["cn"][0] = $attributes["display_name"];
    -        $add["samaccountname"][0] = $attributes["username"];
    -        $add["objectclass"][0] = "top";
    -        $add["objectclass"][1] = "person";
    -        $add["objectclass"][2] = "organizationalPerson";
    -        $add["objectclass"][3] = "user"; //person?
    -        //$add["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
    -
    -        // Set the account control attribute
    -        $control_options = array("NORMAL_ACCOUNT");
    -        if (!$attributes["enabled"]) { 
    -            $control_options[] = "ACCOUNTDISABLE"; 
    -        }
    -        $add["userAccountControl"][0] = $this->accountControl($control_options);
    -        
    -        // Determine the container
    -        $attributes["container"] = array_reverse($attributes["container"]);
    -        $container = "OU=" . implode(", OU=",$attributes["container"]);
    -
    -        // Add the entry
    -        $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"][0] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
    -        if ($result != true) { 
    -            return false; 
    -        }
    -        
    -        return true;
    -    }
    -    
    -    /**
    -    * Account control options
    -    *
    -    * @param array $options The options to convert to int 
    -    * @return int
    -    */
    -    protected function accountControl($options)
    -    {
    -        $val=0;
    -
    -        if (is_array($options)) {
    -            if (in_array("SCRIPT",$options)){ $val=$val+1; }
    -            if (in_array("ACCOUNTDISABLE",$options)){ $val=$val+2; }
    -            if (in_array("HOMEDIR_REQUIRED",$options)){ $val=$val+8; }
    -            if (in_array("LOCKOUT",$options)){ $val=$val+16; }
    -            if (in_array("PASSWD_NOTREQD",$options)){ $val=$val+32; }
    -            //PASSWD_CANT_CHANGE Note You cannot assign this permission by directly modifying the UserAccountControl attribute.
    -            //For information about how to set the permission programmatically, see the "Property flag descriptions" section.
    -            if (in_array("ENCRYPTED_TEXT_PWD_ALLOWED",$options)){ $val=$val+128; }
    -            if (in_array("TEMP_DUPLICATE_ACCOUNT",$options)){ $val=$val+256; }
    -            if (in_array("NORMAL_ACCOUNT",$options)){ $val=$val+512; }
    -            if (in_array("INTERDOMAIN_TRUST_ACCOUNT",$options)){ $val=$val+2048; }
    -            if (in_array("WORKSTATION_TRUST_ACCOUNT",$options)){ $val=$val+4096; }
    -            if (in_array("SERVER_TRUST_ACCOUNT",$options)){ $val=$val+8192; }
    -            if (in_array("DONT_EXPIRE_PASSWORD",$options)){ $val=$val+65536; }
    -            if (in_array("MNS_LOGON_ACCOUNT",$options)){ $val=$val+131072; }
    -            if (in_array("SMARTCARD_REQUIRED",$options)){ $val=$val+262144; }
    -            if (in_array("TRUSTED_FOR_DELEGATION",$options)){ $val=$val+524288; }
    -            if (in_array("NOT_DELEGATED",$options)){ $val=$val+1048576; }
    -            if (in_array("USE_DES_KEY_ONLY",$options)){ $val=$val+2097152; }
    -            if (in_array("DONT_REQ_PREAUTH",$options)){ $val=$val+4194304; } 
    -            if (in_array("PASSWORD_EXPIRED",$options)){ $val=$val+8388608; }
    -            if (in_array("TRUSTED_TO_AUTH_FOR_DELEGATION",$options)){ $val=$val+16777216; }
    -        }
    -        return $val;
    -    }
    -    
    -    /**
    -    * Delete a user account
    -    * 
    -    * @param string $username The username to delete (please be careful here!)
    -    * @param bool $isGUID Is the username a GUID or a samAccountName
    -    * @return array
    -    */
    -    public function delete($username, $isGUID = false) 
    -    {      
    -        $userinfo = $this->info($username, array("*"), $isGUID);
    -        $dn = $userinfo[0]['distinguishedname'][0];
    -        $result = $this->adldap->folder()->delete($dn);
    -        if ($result != true) { 
    -            return false;
    -        }        
    -        return true;
    -    }
    -    
    -    /**
    -    * Groups the user is a member of
    -    * 
    -    * @param string $username The username to query
    -    * @param bool $recursive Recursive list of groups
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return array
    -    */
    -    public function groups($username, $recursive = NULL, $isGUID = false)
    -    {
    -        if ($username === NULL) { return false; }
    -        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        // Search the directory for their information
    -        $info = @$this->info($username, array("memberof", "primarygroupid"), $isGUID);
    -        $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); // Presuming the entry returned is our guy (unique usernames)
    -
    -        if ($recursive === true){
    -            foreach ($groups as $id => $groupName){
    -                $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
    -                $groups = array_merge($groups, $extraGroups);
    -            }
    -        }
    -        
    -        return $groups;
    -    }
    -    
    -    /**
    -    * Find information about the users. Returned in a raw array format from AD
    -    * 
    -    * @param string $username The username to query
    -    * @param array $fields Array of parameters to query
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return array
    -    */
    -    public function info($username, $fields = NULL, $isGUID = false)
    -    {
    -        if ($username === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -
    -        if ($isGUID === true) {
    -            $username = $this->adldap->utilities()->strGuidToHex($username);
    -            $filter = "objectguid=" . $username;
    -        }
    -        else if (strstr($username, "@")) {
    -             $filter = "userPrincipalName=" . $username;
    -        }
    -        else {
    -             $filter = "samaccountname=" . $username;
    -        }
    -        $filter = "(&(objectCategory=person)({$filter}))";
    -        if ($fields === NULL) { 
    -            $fields = array("samaccountname","mail","memberof","department","displayname","telephonenumber","primarygroupid","objectsid"); 
    -        }
    -        if (!in_array("objectsid", $fields)) {
    -            $fields[] = "objectsid";
    -        }
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -        
    -        if (isset($entries[0])) {
    -            if ($entries[0]['count'] >= 1) {
    -                if (in_array("memberof", $fields)) {
    -                    // AD does not return the primary group in the ldap query, we may need to fudge it
    -                    if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["objectsid"][0])){
    -                        //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
    -                        $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
    -                    } else {
    -                        $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
    -                    }
    -                    if (!isset($entries[0]["memberof"]["count"])) {
    -                        $entries[0]["memberof"]["count"] = 0;
    -                    }
    -                    $entries[0]["memberof"]["count"]++;
    -                }
    -            }
    -            
    -            return $entries;
    -        }
    -        return false;
    -    }
    -    
    -    /**
    -    * Find information about the users. Returned in a raw array format from AD
    -    * 
    -    * @param string $username The username to query
    -    * @param array $fields Array of parameters to query
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return mixed
    -    */
    -    public function infoCollection($username, $fields = NULL, $isGUID = false)
    -    {
    -        if ($username === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        $info = $this->info($username, $fields, $isGUID);
    -        
    -        if ($info !== false) {
    -            $collection = new adLDAPUserCollection($info, $this->adldap);
    -            return $collection;
    -        }
    -        return false;
    -    }
    -    
    -    /**
    -    * Determine if a user is in a specific group
    -    * 
    -    * @param string $username The username to query
    -    * @param string $group The name of the group to check against
    -    * @param bool $recursive Check groups recursively
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function inGroup($username, $group, $recursive = NULL, $isGUID = false)
    -    {
    -        if ($username === NULL) { return false; }
    -        if ($group === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
    -        
    -        // Get a list of the groups
    -        $groups = $this->groups($username, $recursive, $isGUID);
    -        
    -        // Return true if the specified group is in the group list
    -        if (in_array($group, $groups)) { 
    -            return true; 
    -        }
    -
    -        return false;
    -    }
    -    
    -    /**
    -    * Determine a user's password expiry date
    -    * 
    -    * @param string $username The username to query
    -    * @param book $isGUID Is the username passed a GUID or a samAccountName
    -    * @requires bcmath http://www.php.net/manual/en/book.bc.php
    -    * @return array
    -    */
    -    public function passwordExpiry($username, $isGUID = false) 
    -    {
    -        if ($username === NULL) { return "Missing compulsory field [username]"; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        if (!function_exists('bcmod')) { throw new adLDAPException("Missing function support [bcmod] http://www.php.net/manual/en/book.bc.php"); };
    -        
    -        $userInfo = $this->info($username, array("pwdlastset", "useraccountcontrol"), $isGUID);
    -        $pwdLastSet = $userInfo[0]['pwdlastset'][0];
    -        $status = array();
    -        
    -        if ($userInfo[0]['useraccountcontrol'][0] == '66048') {
    -            // Password does not expire
    -            return "Does not expire";
    -        }
    -        if ($pwdLastSet === '0') {
    -            // Password has already expired
    -            return "Password has expired";
    -        }
    -        
    -         // Password expiry in AD can be calculated from TWO values:
    -         //   - User's own pwdLastSet attribute: stores the last time the password was changed
    -         //   - Domain's maxPwdAge attribute: how long passwords last in the domain
    -         //
    -         // Although Microsoft chose to use a different base and unit for time measurements.
    -         // This function will convert them to Unix timestamps
    -         $sr = ldap_read($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), 'objectclass=*', array('maxPwdAge'));
    -         if (!$sr) {
    -             return false;
    -         }
    -         $info = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -         $maxPwdAge = $info[0]['maxpwdage'][0];
    -         
    -
    -         // See MSDN: http://msdn.microsoft.com/en-us/library/ms974598.aspx
    -         //
    -         // pwdLastSet contains the number of 100 nanosecond intervals since January 1, 1601 (UTC), 
    -         // stored in a 64 bit integer. 
    -         //
    -         // The number of seconds between this date and Unix epoch is 11644473600.
    -         //
    -         // maxPwdAge is stored as a large integer that represents the number of 100 nanosecond
    -         // intervals from the time the password was set before the password expires.
    -         //
    -         // We also need to scale this to seconds but also this value is a _negative_ quantity!
    -         //
    -         // If the low 32 bits of maxPwdAge are equal to 0 passwords do not expire
    -         //
    -         // Unfortunately the maths involved are too big for PHP integers, so I've had to require
    -         // BCMath functions to work with arbitrary precision numbers.
    -         if (bcmod($maxPwdAge, 4294967296) === '0') {
    -            return "Domain does not expire passwords";
    -        }
    -        
    -        // Add maxpwdage and pwdlastset and we get password expiration time in Microsoft's
    -        // time units.  Because maxpwd age is negative we need to subtract it.
    -        $pwdExpire = bcsub($pwdLastSet, $maxPwdAge);
    -    
    -        // Convert MS's time to Unix time
    -        $status['expiryts'] = bcsub(bcdiv($pwdExpire, '10000000'), '11644473600');
    -        $status['expiryformat'] = date('Y-m-d H:i:s', bcsub(bcdiv($pwdExpire, '10000000'), '11644473600'));
    -        
    -        return $status;
    -    }
    -    
    -    /**
    -    * Modify a user
    -    * 
    -    * @param string $username The username to query
    -    * @param array $attributes The attributes to modify.  Note if you set the enabled attribute you must not specify any other attributes
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function modify($username, $attributes, $isGUID = false)
    -    {
    -        if ($username === NULL) { return "Missing compulsory field [username]"; }
    -        if (array_key_exists("password", $attributes) && !$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) { 
    -            throw new adLDAPException('SSL/TLS must be configured on your webserver and enabled in the class to set passwords.');
    -        }
    -
    -        // Find the dn of the user
    -        $userDn = $this->dn($username, $isGUID);
    -        if ($userDn === false) { 
    -            return false; 
    -        }
    -        
    -        // Translate the update to the LDAP schema                
    -        $mod = $this->adldap->adldap_schema($attributes);
    -        
    -        // Check to see if this is an enabled status update
    -        if (!$mod && !array_key_exists("enabled", $attributes)){ 
    -            return false; 
    -        }
    -        
    -        // Set the account control attribute (only if specified)
    -        if (array_key_exists("enabled", $attributes)){
    -            if ($attributes["enabled"]){ 
    -                $controlOptions = array("NORMAL_ACCOUNT"); 
    -            }
    -            else { 
    -                $controlOptions = array("NORMAL_ACCOUNT", "ACCOUNTDISABLE"); 
    -            }
    -            $mod["userAccountControl"][0] = $this->accountControl($controlOptions);
    -        }
    -
    -        // Do the update
    -        $result = @ldap_modify($this->adldap->getLdapConnection(), $userDn, $mod);
    -        if ($result == false) { 
    -            return false; 
    -        }
    -        
    -        return true;
    -    }
    -    
    -    /**
    -    * Disable a user account
    -    * 
    -    * @param string $username The username to disable
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function disable($username, $isGUID = false)
    -    {
    -        if ($username === NULL) { return "Missing compulsory field [username]"; }
    -        $attributes = array("enabled" => 0);
    -        $result = $this->modify($username, $attributes, $isGUID);
    -        if ($result == false) { return false; }
    -        
    -        return true;
    -    }
    -    
    -    /**
    -    * Enable a user account
    -    * 
    -    * @param string $username The username to enable
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function enable($username, $isGUID = false)
    -    {
    -        if ($username === NULL) { return "Missing compulsory field [username]"; }
    -        $attributes = array("enabled" => 1);
    -        $result = $this->modify($username, $attributes, $isGUID);
    -        if ($result == false) { return false; }
    -        
    -        return true;
    -    }
    -    
    -    /**
    -    * Set the password of a user - This must be performed over SSL
    -    * 
    -    * @param string $username The username to modify
    -    * @param string $password The new password
    -    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    -    * @return bool
    -    */
    -    public function password($username, $password, $isGUID = false)
    -    {
    -        if ($username === NULL) { return false; }
    -        if ($password === NULL) { return false; }
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        if (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) { 
    -            throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
    -        }
    -        
    -        $userDn = $this->dn($username, $isGUID);
    -        if ($userDn === false) { 
    -            return false; 
    -        }
    -                
    -        $add=array();
    -        $add["unicodePwd"][0] = $this->encodePassword($password);
    -        
    -        $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $add);
    -        if ($result === false){
    -            $err = ldap_errno($this->adldap->getLdapConnection());
    -            if ($err) {
    -                $msg = 'Error ' . $err . ': ' . ldap_err2str($err) . '.';
    -                if($err == 53) {
    -                    $msg .= ' Your password might not match the password policy.';
    -                }
    -                throw new adLDAPException($msg);
    -            }
    -            else {
    -                return false;
    -            }
    -        }
    -        
    -        return true;
    -    }
    -    
    -    /**
    -    * Encode a password for transmission over LDAP
    -    *
    -    * @param string $password The password to encode
    -    * @return string
    -    */
    -    public function encodePassword($password)
    -    {
    -        $password="\"".$password."\"";
    -        $encoded="";
    -        for ($i=0; $i info($username, array("cn"), $isGUID);
    -        if ($user[0]["dn"] === NULL) { 
    -            return false; 
    -        }
    -        $userDn = $user[0]["dn"];
    -        return $userDn;
    -    }
    -    
    -    /**
    -    * Return a list of all users in AD
    -    * 
    -    * @param bool $includeDescription Return a description of the user
    -    * @param string $search Search parameter
    -    * @param bool $sorted Sort the user accounts
    -    * @return array
    -    */
    -    public function all($includeDescription = false, $search = "*", $sorted = true)
    -    {
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        
    -        // Perform the search and grab all their details
    -        $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(cn=" . $search . "))";
    -        $fields = array("samaccountname","displayname");
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -        $usersArray = array();
    -        for ($i=0; $i<$entries["count"]; $i++){
    -            if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
    -                $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
    -            } elseif ($includeDescription){
    -                $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
    -            } else {
    -                array_push($usersArray, $entries[$i]["samaccountname"][0]);
    -            }
    -        }
    -        if ($sorted) { 
    -            asort($usersArray); 
    -        }
    -        return $usersArray;
    -    }
    -    
    -    /**
    -    * Converts a username (samAccountName) to a GUID
    -    * 
    -    * @param string $username The username to query
    -    * @return string
    -    */
    -    public function usernameToGuid($username) 
    -    {
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -        if ($username === null){ return "Missing compulsory field [username]"; }
    -        
    -        $filter = "samaccountname=" . $username; 
    -        $fields = array("objectGUID"); 
    -        $sr = @ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields); 
    -        if (ldap_count_entries($this->adldap->getLdapConnection(), $sr) > 0) { 
    -            $entry = @ldap_first_entry($this->adldap->getLdapConnection(), $sr); 
    -            $guid = @ldap_get_values_len($this->adldap->getLdapConnection(), $entry, 'objectGUID'); 
    -            $strGUID = $this->adldap->utilities()->binaryToText($guid[0]);          
    -            return $strGUID; 
    -        }
    -        return false; 
    -    }
    -    
    -    /**
    -    * Return a list of all users in AD that have a specific value in a field
    -    *
    -    * @param bool $includeDescription Return a description of the user
    -    * @param string $searchField Field to search search for
    -    * @param string $searchFilter Value to search for in the specified field
    -    * @param bool $sorted Sort the user accounts
    -    * @return array
    -    */
    -    public function find($includeDescription = false, $searchField = false, $searchFilter = false, $sorted = true){
    -        if (!$this->adldap->getLdapBind()){ return false; }
    -          
    -        // Perform the search and grab all their details
    -        $searchParams = "";
    -        if ($searchField) {
    -            $searchParams = "(" . $searchField . "=" . $searchFilter . ")";
    -        }                           
    -        $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)" . $searchParams . ")";
    -        $fields = array("samaccountname","displayname");
    -        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    -        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    -
    -        $usersArray = array();
    -        for ($i=0; $i < $entries["count"]; $i++) {
    -            if ($includeDescription && strlen($entries[$i]["displayname"][0]) > 0) {
    -                $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
    -            }
    -            else if ($includeDescription) {
    -                $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
    -            }
    -            else {
    -                array_push($usersArray, $entries[$i]["samaccountname"][0]);
    -            }
    -        }
    -        if ($sorted){ 
    -          asort($usersArray); 
    -        }
    -        return ($usersArray);
    -    }
    -    
    -    /**
    -    * Move a user account to a different OU
    -    *
    -    * @param string $username The username to move (please be careful here!)
    -    * @param array $container The container or containers to move the user to (please be careful here!).
    -    * accepts containers in 1. parent 2. child order
    -    * @return array
    -    */
    -    public function move($username, $container) 
    -    {
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        if ($username === null) { return "Missing compulsory field [username]"; }
    -        if ($container === null) { return "Missing compulsory field [container]"; }
    -        if (!is_array($container)) { return "Container must be an array"; }
    -        
    -        $userInfo = $this->info($username, array("*"));
    -        $dn = $userInfo[0]['distinguishedname'][0];
    -        $newRDn = "cn=" . $username;
    -        $container = array_reverse($container);
    -        $newContainer = "ou=" . implode(",ou=",$container);
    -        $newBaseDn = strtolower($newContainer) . "," . $this->adldap->getBaseDn();
    -        $result = @ldap_rename($this->adldap->getLdapConnection(), $dn, $newRDn, $newBaseDn, true);
    -        if ($result !== true) {
    -            return false;
    -        }
    -        return true;
    -    }
    -    
    -    /**
    -    * Get the last logon time of any user as a Unix timestamp
    -    * 
    -    * @param string $username
    -    * @return long $unixTimestamp
    -    */
    -    public function getLastLogon($username) {
    -        if (!$this->adldap->getLdapBind()) { return false; }
    -        if ($username === null) { return "Missing compulsory field [username]"; }
    -        $userInfo = $this->info($username, array("lastLogonTimestamp"));
    -        $lastLogon = adLDAPUtils::convertWindowsTimeToUnixTime($userInfo[0]['lastLogonTimestamp'][0]);
    -        return $lastLogon;
    -    }
    -    
    -}
    -?>
    +adldap = $adldap;
    +    }
    +    
    +    /**
    +    * Validate a user's login credentials
    +    * 
    +    * @param string $username A user's AD username
    +    * @param string $password A user's AD password
    +    * @param bool optional $prevent_rebind
    +    * @return bool
    +    */
    +    public function authenticate($username, $password, $preventRebind = false) {
    +        return $this->adldap->authenticate($username, $password, $preventRebind);
    +    }
    +    
    +    /**
    +    * Create a user
    +    * 
    +    * If you specify a password here, this can only be performed over SSL
    +    * 
    +    * @param array $attributes The attributes to set to the user account
    +    * @return bool
    +    */
    +    public function create($attributes)
    +    {
    +        // Check for compulsory fields
    +        if (!array_key_exists("username", $attributes)){ return "Missing compulsory field [username]"; }
    +        if (!array_key_exists("firstname", $attributes)){ return "Missing compulsory field [firstname]"; }
    +        if (!array_key_exists("surname", $attributes)){ return "Missing compulsory field [surname]"; }
    +        if (!array_key_exists("email", $attributes)){ return "Missing compulsory field [email]"; }
    +        if (!array_key_exists("container", $attributes)){ return "Missing compulsory field [container]"; }
    +        if (!is_array($attributes["container"])){ return "Container attribute must be an array."; }
    +
    +        if (array_key_exists("password",$attributes) && (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS())){ 
    +            throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
    +        }
    +
    +        if (!array_key_exists("display_name", $attributes)) { 
    +            $attributes["display_name"] = $attributes["firstname"] . " " . $attributes["surname"]; 
    +        }
    +
    +        // Translate the schema
    +        $add = $this->adldap->adldap_schema($attributes);
    +        
    +        // Additional stuff only used for adding accounts
    +        $add["cn"][0] = $attributes["display_name"];
    +        $add["samaccountname"][0] = $attributes["username"];
    +        $add["objectclass"][0] = "top";
    +        $add["objectclass"][1] = "person";
    +        $add["objectclass"][2] = "organizationalPerson";
    +        $add["objectclass"][3] = "user"; //person?
    +        //$add["name"][0]=$attributes["firstname"]." ".$attributes["surname"];
    +
    +        // Set the account control attribute
    +        $control_options = array("NORMAL_ACCOUNT");
    +        if (!$attributes["enabled"]) { 
    +            $control_options[] = "ACCOUNTDISABLE"; 
    +        }
    +        $add["userAccountControl"][0] = $this->accountControl($control_options);
    +        
    +        // Determine the container
    +        $attributes["container"] = array_reverse($attributes["container"]);
    +        $container = "OU=" . implode(", OU=",$attributes["container"]);
    +
    +        // Add the entry
    +        $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $add["cn"][0] . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
    +        if ($result != true) { 
    +            return false; 
    +        }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Account control options
    +    *
    +    * @param array $options The options to convert to int 
    +    * @return int
    +    */
    +    protected function accountControl($options)
    +    {
    +        $val=0;
    +
    +        if (is_array($options)) {
    +            if (in_array("SCRIPT",$options)){ $val=$val+1; }
    +            if (in_array("ACCOUNTDISABLE",$options)){ $val=$val+2; }
    +            if (in_array("HOMEDIR_REQUIRED",$options)){ $val=$val+8; }
    +            if (in_array("LOCKOUT",$options)){ $val=$val+16; }
    +            if (in_array("PASSWD_NOTREQD",$options)){ $val=$val+32; }
    +            //PASSWD_CANT_CHANGE Note You cannot assign this permission by directly modifying the UserAccountControl attribute.
    +            //For information about how to set the permission programmatically, see the "Property flag descriptions" section.
    +            if (in_array("ENCRYPTED_TEXT_PWD_ALLOWED",$options)){ $val=$val+128; }
    +            if (in_array("TEMP_DUPLICATE_ACCOUNT",$options)){ $val=$val+256; }
    +            if (in_array("NORMAL_ACCOUNT",$options)){ $val=$val+512; }
    +            if (in_array("INTERDOMAIN_TRUST_ACCOUNT",$options)){ $val=$val+2048; }
    +            if (in_array("WORKSTATION_TRUST_ACCOUNT",$options)){ $val=$val+4096; }
    +            if (in_array("SERVER_TRUST_ACCOUNT",$options)){ $val=$val+8192; }
    +            if (in_array("DONT_EXPIRE_PASSWORD",$options)){ $val=$val+65536; }
    +            if (in_array("MNS_LOGON_ACCOUNT",$options)){ $val=$val+131072; }
    +            if (in_array("SMARTCARD_REQUIRED",$options)){ $val=$val+262144; }
    +            if (in_array("TRUSTED_FOR_DELEGATION",$options)){ $val=$val+524288; }
    +            if (in_array("NOT_DELEGATED",$options)){ $val=$val+1048576; }
    +            if (in_array("USE_DES_KEY_ONLY",$options)){ $val=$val+2097152; }
    +            if (in_array("DONT_REQ_PREAUTH",$options)){ $val=$val+4194304; } 
    +            if (in_array("PASSWORD_EXPIRED",$options)){ $val=$val+8388608; }
    +            if (in_array("TRUSTED_TO_AUTH_FOR_DELEGATION",$options)){ $val=$val+16777216; }
    +        }
    +        return $val;
    +    }
    +    
    +    /**
    +    * Delete a user account
    +    * 
    +    * @param string $username The username to delete (please be careful here!)
    +    * @param bool $isGUID Is the username a GUID or a samAccountName
    +    * @return array
    +    */
    +    public function delete($username, $isGUID = false) 
    +    {      
    +        $userinfo = $this->info($username, array("*"), $isGUID);
    +        $dn = $userinfo[0]['distinguishedname'][0];
    +        $result = $this->adldap->folder()->delete($dn);
    +        if ($result != true) { 
    +            return false;
    +        }        
    +        return true;
    +    }
    +    
    +    /**
    +    * Groups the user is a member of
    +    * 
    +    * @param string $username The username to query
    +    * @param bool $recursive Recursive list of groups
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return array
    +    */
    +    public function groups($username, $recursive = NULL, $isGUID = false)
    +    {
    +        if ($username === NULL) { return false; }
    +        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        // Search the directory for their information
    +        $info = @$this->info($username, array("memberof", "primarygroupid"), $isGUID);
    +        $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); // Presuming the entry returned is our guy (unique usernames)
    +
    +        if ($recursive === true){
    +            foreach ($groups as $id => $groupName){
    +                $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
    +                $groups = array_merge($groups, $extraGroups);
    +            }
    +        }
    +        
    +        return $groups;
    +    }
    +    
    +    /**
    +    * Find information about the users. Returned in a raw array format from AD
    +    * 
    +    * @param string $username The username to query
    +    * @param array $fields Array of parameters to query
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return array
    +    */
    +    public function info($username, $fields = NULL, $isGUID = false)
    +    {
    +        if ($username === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +
    +        if ($isGUID === true) {
    +            $username = $this->adldap->utilities()->strGuidToHex($username);
    +            $filter = "objectguid=" . $username;
    +        }
    +        else if (strstr($username, "@")) {
    +             $filter = "userPrincipalName=" . $username;
    +        }
    +        else {
    +             $filter = "samaccountname=" . $username;
    +        }
    +        $filter = "(&(objectCategory=person)({$filter}))";
    +        if ($fields === NULL) { 
    +            $fields = array("samaccountname","mail","memberof","department","displayname","telephonenumber","primarygroupid","objectsid"); 
    +        }
    +        if (!in_array("objectsid", $fields)) {
    +            $fields[] = "objectsid";
    +        }
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +        
    +        if (isset($entries[0])) {
    +            if ($entries[0]['count'] >= 1) {
    +                if (in_array("memberof", $fields)) {
    +                    // AD does not return the primary group in the ldap query, we may need to fudge it
    +                    if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["objectsid"][0])){
    +                        //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
    +                        $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
    +                    } else {
    +                        $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
    +                    }
    +                    if (!isset($entries[0]["memberof"]["count"])) {
    +                        $entries[0]["memberof"]["count"] = 0;
    +                    }
    +                    $entries[0]["memberof"]["count"]++;
    +                }
    +            }
    +            
    +            return $entries;
    +        }
    +        return false;
    +    }
    +    
    +    /**
    +    * Find information about the users. Returned in a raw array format from AD
    +    * 
    +    * @param string $username The username to query
    +    * @param array $fields Array of parameters to query
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return mixed
    +    */
    +    public function infoCollection($username, $fields = NULL, $isGUID = false)
    +    {
    +        if ($username === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        $info = $this->info($username, $fields, $isGUID);
    +        
    +        if ($info !== false) {
    +            $collection = new adLDAPUserCollection($info, $this->adldap);
    +            return $collection;
    +        }
    +        return false;
    +    }
    +    
    +    /**
    +    * Determine if a user is in a specific group
    +    * 
    +    * @param string $username The username to query
    +    * @param string $group The name of the group to check against
    +    * @param bool $recursive Check groups recursively
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function inGroup($username, $group, $recursive = NULL, $isGUID = false)
    +    {
    +        if ($username === NULL) { return false; }
    +        if ($group === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } // Use the default option if they haven't set it
    +        
    +        // Get a list of the groups
    +        $groups = $this->groups($username, $recursive, $isGUID);
    +        
    +        // Return true if the specified group is in the group list
    +        if (in_array($group, $groups)) { 
    +            return true; 
    +        }
    +
    +        return false;
    +    }
    +    
    +    /**
    +    * Determine a user's password expiry date
    +    * 
    +    * @param string $username The username to query
    +    * @param book $isGUID Is the username passed a GUID or a samAccountName
    +    * @requires bcmath http://www.php.net/manual/en/book.bc.php
    +    * @return array
    +    */
    +    public function passwordExpiry($username, $isGUID = false) 
    +    {
    +        if ($username === NULL) { return "Missing compulsory field [username]"; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        if (!function_exists('bcmod')) { throw new adLDAPException("Missing function support [bcmod] http://www.php.net/manual/en/book.bc.php"); };
    +        
    +        $userInfo = $this->info($username, array("pwdlastset", "useraccountcontrol"), $isGUID);
    +        $pwdLastSet = $userInfo[0]['pwdlastset'][0];
    +        $status = array();
    +        
    +        if ($userInfo[0]['useraccountcontrol'][0] == '66048') {
    +            // Password does not expire
    +            return "Does not expire";
    +        }
    +        if ($pwdLastSet === '0') {
    +            // Password has already expired
    +            return "Password has expired";
    +        }
    +        
    +         // Password expiry in AD can be calculated from TWO values:
    +         //   - User's own pwdLastSet attribute: stores the last time the password was changed
    +         //   - Domain's maxPwdAge attribute: how long passwords last in the domain
    +         //
    +         // Although Microsoft chose to use a different base and unit for time measurements.
    +         // This function will convert them to Unix timestamps
    +         $sr = ldap_read($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), 'objectclass=*', array('maxPwdAge'));
    +         if (!$sr) {
    +             return false;
    +         }
    +         $info = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +         $maxPwdAge = $info[0]['maxpwdage'][0];
    +         
    +
    +         // See MSDN: http://msdn.microsoft.com/en-us/library/ms974598.aspx
    +         //
    +         // pwdLastSet contains the number of 100 nanosecond intervals since January 1, 1601 (UTC), 
    +         // stored in a 64 bit integer. 
    +         //
    +         // The number of seconds between this date and Unix epoch is 11644473600.
    +         //
    +         // maxPwdAge is stored as a large integer that represents the number of 100 nanosecond
    +         // intervals from the time the password was set before the password expires.
    +         //
    +         // We also need to scale this to seconds but also this value is a _negative_ quantity!
    +         //
    +         // If the low 32 bits of maxPwdAge are equal to 0 passwords do not expire
    +         //
    +         // Unfortunately the maths involved are too big for PHP integers, so I've had to require
    +         // BCMath functions to work with arbitrary precision numbers.
    +         if (bcmod($maxPwdAge, 4294967296) === '0') {
    +            return "Domain does not expire passwords";
    +        }
    +        
    +        // Add maxpwdage and pwdlastset and we get password expiration time in Microsoft's
    +        // time units.  Because maxpwd age is negative we need to subtract it.
    +        $pwdExpire = bcsub($pwdLastSet, $maxPwdAge);
    +    
    +        // Convert MS's time to Unix time
    +        $status['expiryts'] = bcsub(bcdiv($pwdExpire, '10000000'), '11644473600');
    +        $status['expiryformat'] = date('Y-m-d H:i:s', bcsub(bcdiv($pwdExpire, '10000000'), '11644473600'));
    +        
    +        return $status;
    +    }
    +    
    +    /**
    +    * Modify a user
    +    * 
    +    * @param string $username The username to query
    +    * @param array $attributes The attributes to modify.  Note if you set the enabled attribute you must not specify any other attributes
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function modify($username, $attributes, $isGUID = false)
    +    {
    +        if ($username === NULL) { return "Missing compulsory field [username]"; }
    +        if (array_key_exists("password", $attributes) && !$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) { 
    +            throw new adLDAPException('SSL/TLS must be configured on your webserver and enabled in the class to set passwords.');
    +        }
    +
    +        // Find the dn of the user
    +        $userDn = $this->dn($username, $isGUID);
    +        if ($userDn === false) { 
    +            return false; 
    +        }
    +        
    +        // Translate the update to the LDAP schema                
    +        $mod = $this->adldap->adldap_schema($attributes);
    +        
    +        // Check to see if this is an enabled status update
    +        if (!$mod && !array_key_exists("enabled", $attributes)){ 
    +            return false; 
    +        }
    +        
    +        // Set the account control attribute (only if specified)
    +        if (array_key_exists("enabled", $attributes)){
    +            if ($attributes["enabled"]){ 
    +                $controlOptions = array("NORMAL_ACCOUNT"); 
    +            }
    +            else { 
    +                $controlOptions = array("NORMAL_ACCOUNT", "ACCOUNTDISABLE"); 
    +            }
    +            $mod["userAccountControl"][0] = $this->accountControl($controlOptions);
    +        }
    +
    +        // Do the update
    +        $result = @ldap_modify($this->adldap->getLdapConnection(), $userDn, $mod);
    +        if ($result == false) { 
    +            return false; 
    +        }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Disable a user account
    +    * 
    +    * @param string $username The username to disable
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function disable($username, $isGUID = false)
    +    {
    +        if ($username === NULL) { return "Missing compulsory field [username]"; }
    +        $attributes = array("enabled" => 0);
    +        $result = $this->modify($username, $attributes, $isGUID);
    +        if ($result == false) { return false; }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Enable a user account
    +    * 
    +    * @param string $username The username to enable
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function enable($username, $isGUID = false)
    +    {
    +        if ($username === NULL) { return "Missing compulsory field [username]"; }
    +        $attributes = array("enabled" => 1);
    +        $result = $this->modify($username, $attributes, $isGUID);
    +        if ($result == false) { return false; }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Set the password of a user - This must be performed over SSL
    +    * 
    +    * @param string $username The username to modify
    +    * @param string $password The new password
    +    * @param bool $isGUID Is the username passed a GUID or a samAccountName
    +    * @return bool
    +    */
    +    public function password($username, $password, $isGUID = false)
    +    {
    +        if ($username === NULL) { return false; }
    +        if ($password === NULL) { return false; }
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        if (!$this->adldap->getUseSSL() && !$this->adldap->getUseTLS()) { 
    +            throw new adLDAPException('SSL must be configured on your webserver and enabled in the class to set passwords.');
    +        }
    +        
    +        $userDn = $this->dn($username, $isGUID);
    +        if ($userDn === false) { 
    +            return false; 
    +        }
    +                
    +        $add=array();
    +        $add["unicodePwd"][0] = $this->encodePassword($password);
    +        
    +        $result = @ldap_mod_replace($this->adldap->getLdapConnection(), $userDn, $add);
    +        if ($result === false){
    +            $err = ldap_errno($this->adldap->getLdapConnection());
    +            if ($err) {
    +                $msg = 'Error ' . $err . ': ' . ldap_err2str($err) . '.';
    +                if($err == 53) {
    +                    $msg .= ' Your password might not match the password policy.';
    +                }
    +                throw new adLDAPException($msg);
    +            }
    +            else {
    +                return false;
    +            }
    +        }
    +        
    +        return true;
    +    }
    +    
    +    /**
    +    * Encode a password for transmission over LDAP
    +    *
    +    * @param string $password The password to encode
    +    * @return string
    +    */
    +    public function encodePassword($password)
    +    {
    +        $password="\"".$password."\"";
    +        $encoded="";
    +        for ($i=0; $i info($username, array("cn"), $isGUID);
    +        if ($user[0]["dn"] === NULL) { 
    +            return false; 
    +        }
    +        $userDn = $user[0]["dn"];
    +        return $userDn;
    +    }
    +    
    +    /**
    +    * Return a list of all users in AD
    +    * 
    +    * @param bool $includeDescription Return a description of the user
    +    * @param string $search Search parameter
    +    * @param bool $sorted Sort the user accounts
    +    * @return array
    +    */
    +    public function all($includeDescription = false, $search = "*", $sorted = true)
    +    {
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        
    +        // Perform the search and grab all their details
    +        $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)(cn=" . $search . "))";
    +        $fields = array("samaccountname","displayname");
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +        $usersArray = array();
    +        for ($i=0; $i<$entries["count"]; $i++){
    +            if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
    +                $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
    +            } elseif ($includeDescription){
    +                $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
    +            } else {
    +                array_push($usersArray, $entries[$i]["samaccountname"][0]);
    +            }
    +        }
    +        if ($sorted) { 
    +            asort($usersArray); 
    +        }
    +        return $usersArray;
    +    }
    +    
    +    /**
    +    * Converts a username (samAccountName) to a GUID
    +    * 
    +    * @param string $username The username to query
    +    * @return string
    +    */
    +    public function usernameToGuid($username) 
    +    {
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +        if ($username === null){ return "Missing compulsory field [username]"; }
    +        
    +        $filter = "samaccountname=" . $username; 
    +        $fields = array("objectGUID"); 
    +        $sr = @ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields); 
    +        if (ldap_count_entries($this->adldap->getLdapConnection(), $sr) > 0) { 
    +            $entry = @ldap_first_entry($this->adldap->getLdapConnection(), $sr); 
    +            $guid = @ldap_get_values_len($this->adldap->getLdapConnection(), $entry, 'objectGUID'); 
    +            $strGUID = $this->adldap->utilities()->binaryToText($guid[0]);          
    +            return $strGUID; 
    +        }
    +        return false; 
    +    }
    +    
    +    /**
    +    * Return a list of all users in AD that have a specific value in a field
    +    *
    +    * @param bool $includeDescription Return a description of the user
    +    * @param string $searchField Field to search search for
    +    * @param string $searchFilter Value to search for in the specified field
    +    * @param bool $sorted Sort the user accounts
    +    * @return array
    +    */
    +    public function find($includeDescription = false, $searchField = false, $searchFilter = false, $sorted = true){
    +        if (!$this->adldap->getLdapBind()){ return false; }
    +          
    +        // Perform the search and grab all their details
    +        $searchParams = "";
    +        if ($searchField) {
    +            $searchParams = "(" . $searchField . "=" . $searchFilter . ")";
    +        }                           
    +        $filter = "(&(objectClass=user)(samaccounttype=" . adLDAP::ADLDAP_NORMAL_ACCOUNT .")(objectCategory=person)" . $searchParams . ")";
    +        $fields = array("samaccountname","displayname");
    +        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
    +        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
    +
    +        $usersArray = array();
    +        for ($i=0; $i < $entries["count"]; $i++) {
    +            if ($includeDescription && strlen($entries[$i]["displayname"][0]) > 0) {
    +                $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["displayname"][0];
    +            }
    +            else if ($includeDescription) {
    +                $usersArray[$entries[$i]["samaccountname"][0]] = $entries[$i]["samaccountname"][0];
    +            }
    +            else {
    +                array_push($usersArray, $entries[$i]["samaccountname"][0]);
    +            }
    +        }
    +        if ($sorted){ 
    +          asort($usersArray); 
    +        }
    +        return ($usersArray);
    +    }
    +    
    +    /**
    +    * Move a user account to a different OU
    +    *
    +    * @param string $username The username to move (please be careful here!)
    +    * @param array $container The container or containers to move the user to (please be careful here!).
    +    * accepts containers in 1. parent 2. child order
    +    * @return array
    +    */
    +    public function move($username, $container) 
    +    {
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        if ($username === null) { return "Missing compulsory field [username]"; }
    +        if ($container === null) { return "Missing compulsory field [container]"; }
    +        if (!is_array($container)) { return "Container must be an array"; }
    +        
    +        $userInfo = $this->info($username, array("*"));
    +        $dn = $userInfo[0]['distinguishedname'][0];
    +        $newRDn = "cn=" . $username;
    +        $container = array_reverse($container);
    +        $newContainer = "ou=" . implode(",ou=",$container);
    +        $newBaseDn = strtolower($newContainer) . "," . $this->adldap->getBaseDn();
    +        $result = @ldap_rename($this->adldap->getLdapConnection(), $dn, $newRDn, $newBaseDn, true);
    +        if ($result !== true) {
    +            return false;
    +        }
    +        return true;
    +    }
    +    
    +    /**
    +    * Get the last logon time of any user as a Unix timestamp
    +    * 
    +    * @param string $username
    +    * @return long $unixTimestamp
    +    */
    +    public function getLastLogon($username) {
    +        if (!$this->adldap->getLdapBind()) { return false; }
    +        if ($username === null) { return "Missing compulsory field [username]"; }
    +        $userInfo = $this->info($username, array("lastLogonTimestamp"));
    +        $lastLogon = adLDAPUtils::convertWindowsTimeToUnixTime($userInfo[0]['lastLogonTimestamp'][0]);
    +        return $lastLogon;
    +    }
    +    
    +}
    +?>
    diff --git a/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php b/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php
    index f039a4290..5e8644188 100644
    --- a/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php
    +++ b/lib/plugins/authad/adLDAP/classes/adLDAPUtils.php
    @@ -1,264 +1,264 @@
    -adldap = $adldap;
    -    }
    -    
    -    
    -    /**
    -    * Take an LDAP query and return the nice names, without all the LDAP prefixes (eg. CN, DN)
    -    *
    -    * @param array $groups
    -    * @return array
    -    */
    -    public function niceNames($groups)
    -    {
    -
    -        $groupArray = array();
    -        for ($i=0; $i<$groups["count"]; $i++){ // For each group
    -            $line = $groups[$i];
    -            
    -            if (strlen($line)>0) { 
    -                // More presumptions, they're all prefixed with CN=
    -                // so we ditch the first three characters and the group
    -                // name goes up to the first comma
    -                $bits=explode(",", $line);
    -                $groupArray[] = substr($bits[0], 3, (strlen($bits[0])-3));
    -            }
    -        }
    -        return $groupArray;    
    -    }
    -    
    -    /**
    -    * Escape characters for use in an ldap_create function
    -    * 
    -    * @param string $str
    -    * @return string
    -    */
    -    public function escapeCharacters($str) {
    -        $str = str_replace(",", "\,", $str);
    -        return $str;
    -    }
    -    
    -    /**
    -    * Escape strings for the use in LDAP filters
    -    * 
    -    * DEVELOPERS SHOULD BE DOING PROPER FILTERING IF THEY'RE ACCEPTING USER INPUT
    -    * Ported from Perl's Net::LDAP::Util escape_filter_value
    -    *
    -    * @param string $str The string the parse
    -    * @author Port by Andreas Gohr 
    -    * @return string
    -    */
    -    public function ldapSlashes($str){
    -        return preg_replace('/([\x00-\x1F\*\(\)\\\\])/e',
    -                            '"\\\\\".join("",unpack("H2","$1"))',
    -                            $str);
    -    }
    -    
    -    /**
    -    * Converts a string GUID to a hexdecimal value so it can be queried
    -    * 
    -    * @param string $strGUID A string representation of a GUID
    -    * @return string
    -    */
    -    public function strGuidToHex($strGUID) 
    -    {
    -        $strGUID = str_replace('-', '', $strGUID);
    -
    -        $octet_str = '\\' . substr($strGUID, 6, 2);
    -        $octet_str .= '\\' . substr($strGUID, 4, 2);
    -        $octet_str .= '\\' . substr($strGUID, 2, 2);
    -        $octet_str .= '\\' . substr($strGUID, 0, 2);
    -        $octet_str .= '\\' . substr($strGUID, 10, 2);
    -        $octet_str .= '\\' . substr($strGUID, 8, 2);
    -        $octet_str .= '\\' . substr($strGUID, 14, 2);
    -        $octet_str .= '\\' . substr($strGUID, 12, 2);
    -        //$octet_str .= '\\' . substr($strGUID, 16, strlen($strGUID));
    -        for ($i=16; $i<=(strlen($strGUID)-2); $i++) {
    -            if (($i % 2) == 0) {
    -                $octet_str .= '\\' . substr($strGUID, $i, 2);
    -            }
    -        }
    -        
    -        return $octet_str;
    -    }
    -    
    -    /**
    -    * Convert a binary SID to a text SID
    -    * 
    -    * @param string $binsid A Binary SID
    -    * @return string
    -    */
    -     public function getTextSID($binsid) {
    -        $hex_sid = bin2hex($binsid);
    -        $rev = hexdec(substr($hex_sid, 0, 2));
    -        $subcount = hexdec(substr($hex_sid, 2, 2));
    -        $auth = hexdec(substr($hex_sid, 4, 12));
    -        $result = "$rev-$auth";
    -
    -        for ($x=0;$x < $subcount; $x++) {
    -            $subauth[$x] =
    -                hexdec($this->littleEndian(substr($hex_sid, 16 + ($x * 8), 8)));
    -                $result .= "-" . $subauth[$x];
    -        }
    -
    -        // Cheat by tacking on the S-
    -        return 'S-' . $result;
    -     }
    -     
    -    /**
    -    * Converts a little-endian hex number to one that hexdec() can convert
    -    * 
    -    * @param string $hex A hex code
    -    * @return string
    -    */
    -     public function littleEndian($hex) 
    -     {
    -        $result = '';
    -        for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) {
    -            $result .= substr($hex, $x, 2);
    -        }
    -        return $result;
    -     }
    -     
    -     /**
    -    * Converts a binary attribute to a string
    -    * 
    -    * @param string $bin A binary LDAP attribute
    -    * @return string
    -    */
    -    public function binaryToText($bin) 
    -    {
    -        $hex_guid = bin2hex($bin); 
    -        $hex_guid_to_guid_str = ''; 
    -        for($k = 1; $k <= 4; ++$k) { 
    -            $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2); 
    -        } 
    -        $hex_guid_to_guid_str .= '-'; 
    -        for($k = 1; $k <= 2; ++$k) { 
    -            $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2); 
    -        } 
    -        $hex_guid_to_guid_str .= '-'; 
    -        for($k = 1; $k <= 2; ++$k) { 
    -            $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2); 
    -        } 
    -        $hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4); 
    -        $hex_guid_to_guid_str .= '-' . substr($hex_guid, 20); 
    -        return strtoupper($hex_guid_to_guid_str);   
    -    }
    -    
    -    /**
    -    * Converts a binary GUID to a string GUID
    -    * 
    -    * @param string $binaryGuid The binary GUID attribute to convert
    -    * @return string
    -    */
    -    public function decodeGuid($binaryGuid) 
    -    {
    -        if ($binaryGuid === null){ return "Missing compulsory field [binaryGuid]"; }
    -        
    -        $strGUID = $this->binaryToText($binaryGuid);          
    -        return $strGUID; 
    -    }
    -    
    -    /**
    -    * Convert a boolean value to a string
    -    * You should never need to call this yourself
    -    *
    -    * @param bool $bool Boolean value
    -    * @return string
    -    */
    -    public function boolToStr($bool) 
    -    {
    -        return ($bool) ? 'TRUE' : 'FALSE';
    -    }
    -    
    -    /**
    -    * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
    -    */
    -    public function encode8Bit(&$item, $key) {
    -        $encode = false;
    -        if (is_string($item)) {
    -            for ($i=0; $i> 7) {
    -                    $encode = true;
    -                }
    -            }
    -        }
    -        if ($encode === true && $key != 'password') {
    -            $item = utf8_encode($item);   
    -        }
    -    }  
    -    
    -    /**
    -    * Get the current class version number
    -    * 
    -    * @return string
    -    */
    -    public function getVersion() {
    -        return self::ADLDAP_VERSION;
    -    }
    -    
    -    /**
    -    * Round a Windows timestamp down to seconds and remove the seconds between 1601-01-01 and 1970-01-01
    -    * 
    -    * @param long $windowsTime
    -    * @return long $unixTime
    -    */
    -    public static function convertWindowsTimeToUnixTime($windowsTime) {
    -      $unixTime = round($windowsTime / 10000000) - 11644477200; 
    -      return $unixTime; 
    -    }
    -}
    -
    +adldap = $adldap;
    +    }
    +    
    +    
    +    /**
    +    * Take an LDAP query and return the nice names, without all the LDAP prefixes (eg. CN, DN)
    +    *
    +    * @param array $groups
    +    * @return array
    +    */
    +    public function niceNames($groups)
    +    {
    +
    +        $groupArray = array();
    +        for ($i=0; $i<$groups["count"]; $i++){ // For each group
    +            $line = $groups[$i];
    +            
    +            if (strlen($line)>0) { 
    +                // More presumptions, they're all prefixed with CN=
    +                // so we ditch the first three characters and the group
    +                // name goes up to the first comma
    +                $bits=explode(",", $line);
    +                $groupArray[] = substr($bits[0], 3, (strlen($bits[0])-3));
    +            }
    +        }
    +        return $groupArray;    
    +    }
    +    
    +    /**
    +    * Escape characters for use in an ldap_create function
    +    * 
    +    * @param string $str
    +    * @return string
    +    */
    +    public function escapeCharacters($str) {
    +        $str = str_replace(",", "\,", $str);
    +        return $str;
    +    }
    +    
    +    /**
    +    * Escape strings for the use in LDAP filters
    +    * 
    +    * DEVELOPERS SHOULD BE DOING PROPER FILTERING IF THEY'RE ACCEPTING USER INPUT
    +    * Ported from Perl's Net::LDAP::Util escape_filter_value
    +    *
    +    * @param string $str The string the parse
    +    * @author Port by Andreas Gohr 
    +    * @return string
    +    */
    +    public function ldapSlashes($str){
    +        return preg_replace('/([\x00-\x1F\*\(\)\\\\])/e',
    +                            '"\\\\\".join("",unpack("H2","$1"))',
    +                            $str);
    +    }
    +    
    +    /**
    +    * Converts a string GUID to a hexdecimal value so it can be queried
    +    * 
    +    * @param string $strGUID A string representation of a GUID
    +    * @return string
    +    */
    +    public function strGuidToHex($strGUID) 
    +    {
    +        $strGUID = str_replace('-', '', $strGUID);
    +
    +        $octet_str = '\\' . substr($strGUID, 6, 2);
    +        $octet_str .= '\\' . substr($strGUID, 4, 2);
    +        $octet_str .= '\\' . substr($strGUID, 2, 2);
    +        $octet_str .= '\\' . substr($strGUID, 0, 2);
    +        $octet_str .= '\\' . substr($strGUID, 10, 2);
    +        $octet_str .= '\\' . substr($strGUID, 8, 2);
    +        $octet_str .= '\\' . substr($strGUID, 14, 2);
    +        $octet_str .= '\\' . substr($strGUID, 12, 2);
    +        //$octet_str .= '\\' . substr($strGUID, 16, strlen($strGUID));
    +        for ($i=16; $i<=(strlen($strGUID)-2); $i++) {
    +            if (($i % 2) == 0) {
    +                $octet_str .= '\\' . substr($strGUID, $i, 2);
    +            }
    +        }
    +        
    +        return $octet_str;
    +    }
    +    
    +    /**
    +    * Convert a binary SID to a text SID
    +    * 
    +    * @param string $binsid A Binary SID
    +    * @return string
    +    */
    +     public function getTextSID($binsid) {
    +        $hex_sid = bin2hex($binsid);
    +        $rev = hexdec(substr($hex_sid, 0, 2));
    +        $subcount = hexdec(substr($hex_sid, 2, 2));
    +        $auth = hexdec(substr($hex_sid, 4, 12));
    +        $result = "$rev-$auth";
    +
    +        for ($x=0;$x < $subcount; $x++) {
    +            $subauth[$x] =
    +                hexdec($this->littleEndian(substr($hex_sid, 16 + ($x * 8), 8)));
    +                $result .= "-" . $subauth[$x];
    +        }
    +
    +        // Cheat by tacking on the S-
    +        return 'S-' . $result;
    +     }
    +     
    +    /**
    +    * Converts a little-endian hex number to one that hexdec() can convert
    +    * 
    +    * @param string $hex A hex code
    +    * @return string
    +    */
    +     public function littleEndian($hex) 
    +     {
    +        $result = '';
    +        for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) {
    +            $result .= substr($hex, $x, 2);
    +        }
    +        return $result;
    +     }
    +     
    +     /**
    +    * Converts a binary attribute to a string
    +    * 
    +    * @param string $bin A binary LDAP attribute
    +    * @return string
    +    */
    +    public function binaryToText($bin) 
    +    {
    +        $hex_guid = bin2hex($bin); 
    +        $hex_guid_to_guid_str = ''; 
    +        for($k = 1; $k <= 4; ++$k) { 
    +            $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2); 
    +        } 
    +        $hex_guid_to_guid_str .= '-'; 
    +        for($k = 1; $k <= 2; ++$k) { 
    +            $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2); 
    +        } 
    +        $hex_guid_to_guid_str .= '-'; 
    +        for($k = 1; $k <= 2; ++$k) { 
    +            $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2); 
    +        } 
    +        $hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4); 
    +        $hex_guid_to_guid_str .= '-' . substr($hex_guid, 20); 
    +        return strtoupper($hex_guid_to_guid_str);   
    +    }
    +    
    +    /**
    +    * Converts a binary GUID to a string GUID
    +    * 
    +    * @param string $binaryGuid The binary GUID attribute to convert
    +    * @return string
    +    */
    +    public function decodeGuid($binaryGuid) 
    +    {
    +        if ($binaryGuid === null){ return "Missing compulsory field [binaryGuid]"; }
    +        
    +        $strGUID = $this->binaryToText($binaryGuid);          
    +        return $strGUID; 
    +    }
    +    
    +    /**
    +    * Convert a boolean value to a string
    +    * You should never need to call this yourself
    +    *
    +    * @param bool $bool Boolean value
    +    * @return string
    +    */
    +    public function boolToStr($bool) 
    +    {
    +        return ($bool) ? 'TRUE' : 'FALSE';
    +    }
    +    
    +    /**
    +    * Convert 8bit characters e.g. accented characters to UTF8 encoded characters
    +    */
    +    public function encode8Bit(&$item, $key) {
    +        $encode = false;
    +        if (is_string($item)) {
    +            for ($i=0; $i> 7) {
    +                    $encode = true;
    +                }
    +            }
    +        }
    +        if ($encode === true && $key != 'password') {
    +            $item = utf8_encode($item);   
    +        }
    +    }  
    +    
    +    /**
    +    * Get the current class version number
    +    * 
    +    * @return string
    +    */
    +    public function getVersion() {
    +        return self::ADLDAP_VERSION;
    +    }
    +    
    +    /**
    +    * Round a Windows timestamp down to seconds and remove the seconds between 1601-01-01 and 1970-01-01
    +    * 
    +    * @param long $windowsTime
    +    * @return long $unixTime
    +    */
    +    public static function convertWindowsTimeToUnixTime($windowsTime) {
    +      $unixTime = round($windowsTime / 10000000) - 11644477200; 
    +      return $unixTime; 
    +    }
    +}
    +
     ?>
    \ No newline at end of file
    diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPCollection.php
    index c0a2eb2fa..433d39f18 100644
    --- a/lib/plugins/authad/adLDAP/collections/adLDAPCollection.php
    +++ b/lib/plugins/authad/adLDAP/collections/adLDAPCollection.php
    @@ -1,137 +1,137 @@
    -setInfo($info);   
    -        $this->adldap = $adldap;
    -    }
    -    
    -    /**
    -    * Set the raw info array from Active Directory
    -    * 
    -    * @param array $info
    -    */
    -    public function setInfo(array $info) 
    -    {
    -        if ($this->info && sizeof($info) >= 1) {
    -            unset($this->info);
    -        }
    -        $this->info = $info;   
    -    }
    -    
    -    /**
    -    * Magic get method to retrieve data from the raw array in a formatted way
    -    * 
    -    * @param string $attribute
    -    * @return mixed
    -    */
    -    public function __get($attribute)
    -    {
    -        if (isset($this->info[0]) && is_array($this->info[0])) {
    -            foreach ($this->info[0] as $keyAttr => $valueAttr) {
    -                if (strtolower($keyAttr) == strtolower($attribute)) {
    -                    if ($this->info[0][strtolower($attribute)]['count'] == 1) {
    -                        return $this->info[0][strtolower($attribute)][0];   
    -                    }
    -                    else {
    -                        $array = array();
    -                        foreach ($this->info[0][strtolower($attribute)] as $key => $value) {
    -                            if ((string)$key != 'count') {
    -                                $array[$key] = $value;
    -                            } 
    -                        }  
    -                        return $array;   
    -                    }
    -                }   
    -            }
    -        }
    -        else {
    -            return NULL;   
    -        }
    -    }    
    -    
    -    /**
    -    * Magic set method to update an attribute
    -    * 
    -    * @param string $attribute
    -    * @param string $value
    -    * @return bool
    -    */
    -    abstract public function __set($attribute, $value);
    -    
    -    /** 
    -    * Magic isset method to check for the existence of an attribute 
    -    * 
    -    * @param string $attribute 
    -    * @return bool 
    -    */ 
    -    public function __isset($attribute) {
    -        if (isset($this->info[0]) && is_array($this->info[0])) { 
    -            foreach ($this->info[0] as $keyAttr => $valueAttr) { 
    -                if (strtolower($keyAttr) == strtolower($attribute)) { 
    -                    return true; 
    -                } 
    -            } 
    -        } 
    -        return false; 
    -     } 
    -}
    -?>
    +setInfo($info);   
    +        $this->adldap = $adldap;
    +    }
    +    
    +    /**
    +    * Set the raw info array from Active Directory
    +    * 
    +    * @param array $info
    +    */
    +    public function setInfo(array $info) 
    +    {
    +        if ($this->info && sizeof($info) >= 1) {
    +            unset($this->info);
    +        }
    +        $this->info = $info;   
    +    }
    +    
    +    /**
    +    * Magic get method to retrieve data from the raw array in a formatted way
    +    * 
    +    * @param string $attribute
    +    * @return mixed
    +    */
    +    public function __get($attribute)
    +    {
    +        if (isset($this->info[0]) && is_array($this->info[0])) {
    +            foreach ($this->info[0] as $keyAttr => $valueAttr) {
    +                if (strtolower($keyAttr) == strtolower($attribute)) {
    +                    if ($this->info[0][strtolower($attribute)]['count'] == 1) {
    +                        return $this->info[0][strtolower($attribute)][0];   
    +                    }
    +                    else {
    +                        $array = array();
    +                        foreach ($this->info[0][strtolower($attribute)] as $key => $value) {
    +                            if ((string)$key != 'count') {
    +                                $array[$key] = $value;
    +                            } 
    +                        }  
    +                        return $array;   
    +                    }
    +                }   
    +            }
    +        }
    +        else {
    +            return NULL;   
    +        }
    +    }    
    +    
    +    /**
    +    * Magic set method to update an attribute
    +    * 
    +    * @param string $attribute
    +    * @param string $value
    +    * @return bool
    +    */
    +    abstract public function __set($attribute, $value);
    +    
    +    /** 
    +    * Magic isset method to check for the existence of an attribute 
    +    * 
    +    * @param string $attribute 
    +    * @return bool 
    +    */ 
    +    public function __isset($attribute) {
    +        if (isset($this->info[0]) && is_array($this->info[0])) { 
    +            foreach ($this->info[0] as $keyAttr => $valueAttr) { 
    +                if (strtolower($keyAttr) == strtolower($attribute)) { 
    +                    return true; 
    +                } 
    +            } 
    +        } 
    +        return false; 
    +     } 
    +}
    +?>
    diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php
    index 4f11d8f41..09f82cadc 100644
    --- a/lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php
    +++ b/lib/plugins/authad/adLDAP/collections/adLDAPComputerCollection.php
    @@ -1,46 +1,46 @@
    -
    +
    diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php
    index d42fe6d4c..a9efad5a9 100644
    --- a/lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php
    +++ b/lib/plugins/authad/adLDAP/collections/adLDAPContactCollection.php
    @@ -1,46 +1,46 @@
    -
    +
    diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php
    index cff12fc20..ef4af8df2 100644
    --- a/lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php
    +++ b/lib/plugins/authad/adLDAP/collections/adLDAPGroupCollection.php
    @@ -1,46 +1,46 @@
    -
    +
    diff --git a/lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php b/lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php
    index 801d90296..63fce5f96 100644
    --- a/lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php
    +++ b/lib/plugins/authad/adLDAP/collections/adLDAPUserCollection.php
    @@ -1,46 +1,46 @@
    -
    +
    diff --git a/lib/scripts/jquery/jquery-migrate.js b/lib/scripts/jquery/jquery-migrate.js
    index e99f954e6..942cb8b4d 100644
    --- a/lib/scripts/jquery/jquery-migrate.js
    +++ b/lib/scripts/jquery/jquery-migrate.js
    @@ -1,511 +1,511 @@
    -/*!
    - * jQuery Migrate - v1.1.1 - 2013-02-16
    - * https://github.com/jquery/jquery-migrate
    - * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors; Licensed MIT
    - */
    -(function( jQuery, window, undefined ) {
    -// See http://bugs.jquery.com/ticket/13335
    -// "use strict";
    -
    -
    -var warnedAbout = {};
    -
    -// List of warnings already given; public read only
    -jQuery.migrateWarnings = [];
    -
    -// Set to true to prevent console output; migrateWarnings still maintained
    -// jQuery.migrateMute = false;
    -
    -// Show a message on the console so devs know we're active
    -if ( !jQuery.migrateMute && window.console && console.log ) {
    -	console.log("JQMIGRATE: Logging is active");
    -}
    -
    -// Set to false to disable traces that appear with warnings
    -if ( jQuery.migrateTrace === undefined ) {
    -	jQuery.migrateTrace = true;
    -}
    -
    -// Forget any warnings we've already given; public
    -jQuery.migrateReset = function() {
    -	warnedAbout = {};
    -	jQuery.migrateWarnings.length = 0;
    -};
    -
    -function migrateWarn( msg) {
    -	if ( !warnedAbout[ msg ] ) {
    -		warnedAbout[ msg ] = true;
    -		jQuery.migrateWarnings.push( msg );
    -		if ( window.console && console.warn && !jQuery.migrateMute ) {
    -			console.warn( "JQMIGRATE: " + msg );
    -			if ( jQuery.migrateTrace && console.trace ) {
    -				console.trace();
    -			}
    -		}
    -	}
    -}
    -
    -function migrateWarnProp( obj, prop, value, msg ) {
    -	if ( Object.defineProperty ) {
    -		// On ES5 browsers (non-oldIE), warn if the code tries to get prop;
    -		// allow property to be overwritten in case some other plugin wants it
    -		try {
    -			Object.defineProperty( obj, prop, {
    -				configurable: true,
    -				enumerable: true,
    -				get: function() {
    -					migrateWarn( msg );
    -					return value;
    -				},
    -				set: function( newValue ) {
    -					migrateWarn( msg );
    -					value = newValue;
    -				}
    -			});
    -			return;
    -		} catch( err ) {
    -			// IE8 is a dope about Object.defineProperty, can't warn there
    -		}
    -	}
    -
    -	// Non-ES5 (or broken) browser; just set the property
    -	jQuery._definePropertyBroken = true;
    -	obj[ prop ] = value;
    -}
    -
    -if ( document.compatMode === "BackCompat" ) {
    -	// jQuery has never supported or tested Quirks Mode
    -	migrateWarn( "jQuery is not compatible with Quirks Mode" );
    -}
    -
    -
    -var attrFn = jQuery( "", { size: 1 } ).attr("size") && jQuery.attrFn,
    -	oldAttr = jQuery.attr,
    -	valueAttrGet = jQuery.attrHooks.value && jQuery.attrHooks.value.get ||
    -		function() { return null; },
    -	valueAttrSet = jQuery.attrHooks.value && jQuery.attrHooks.value.set ||
    -		function() { return undefined; },
    -	rnoType = /^(?:input|button)$/i,
    -	rnoAttrNodeType = /^[238]$/,
    -	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
    -	ruseDefault = /^(?:checked|selected)$/i;
    -
    -// jQuery.attrFn
    -migrateWarnProp( jQuery, "attrFn", attrFn || {}, "jQuery.attrFn is deprecated" );
    -
    -jQuery.attr = function( elem, name, value, pass ) {
    -	var lowerName = name.toLowerCase(),
    -		nType = elem && elem.nodeType;
    -
    -	if ( pass ) {
    -		// Since pass is used internally, we only warn for new jQuery
    -		// versions where there isn't a pass arg in the formal params
    -		if ( oldAttr.length < 4 ) {
    -			migrateWarn("jQuery.fn.attr( props, pass ) is deprecated");
    -		}
    -		if ( elem && !rnoAttrNodeType.test( nType ) &&
    -			(attrFn ? name in attrFn : jQuery.isFunction(jQuery.fn[name])) ) {
    -			return jQuery( elem )[ name ]( value );
    -		}
    -	}
    -
    -	// Warn if user tries to set `type`, since it breaks on IE 6/7/8; by checking
    -	// for disconnected elements we don't warn on $( "