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/helper/extension.php | 289 +++++++++++++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 lib/plugins/extension/helper/extension.php (limited to 'lib/plugins/extension/helper/extension.php') 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: -- 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 +++++++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 8 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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); } } -- 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/plugins/extension/helper/extension.php') 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/plugins/extension/helper/extension.php') 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/plugins/extension/helper/extension.php') 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 ++++++++++++++++++++++++++++- 1 file changed, 360 insertions(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') 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: -- 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/helper/extension.php | 189 ++++++++++++++++++++++++----- 1 file changed, 156 insertions(+), 33 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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]; -- 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 ++ 1 file changed, 2 insertions(+) (limited to 'lib/plugins/extension/helper/extension.php') 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); } /** -- 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/helper/extension.php | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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 * -- 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/helper/extension.php | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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; -- 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/helper/extension.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') 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); -- 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/helper/extension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') 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]; -- 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/helper/extension.php | 190 ++++++++++++++--------------- 1 file changed, 90 insertions(+), 100 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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/helper/extension.php | 33 ++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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; } /** -- 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/plugins/extension/helper/extension.php') 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 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/plugins/extension/helper/extension.php') 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 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/helper/extension.php | 98 +++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 14 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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'); } /** -- 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') 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]; -- 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 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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; } -- 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 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') 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; -- cgit v1.2.3 From 9a2e74c192a89e048b53aca9260e70759e8dfdc6 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 5 Jan 2014 19:55:36 +0100 Subject: the plugin is called testing not test --- lib/plugins/extension/helper/extension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 6ad8f5185..04eb24a66 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -94,7 +94,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->base, - array('acl', 'info', 'extension', 'test', 'revert', 'popularity', + array('acl', 'info', 'extension', 'testing', 'revert', 'popularity', 'config', 'plugin', 'safefnrecode', 'authplain', 'testing', 'template:dokuwiki', 'template:default' ) -- cgit v1.2.3 From 947a0472355a8591b0ef449ad9add9c0b782ddcf Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 5 Jan 2014 19:57:07 +0100 Subject: template:default is no longer bundled --- lib/plugins/extension/helper/extension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 04eb24a66..2d0e91301 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -96,7 +96,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { return in_array($this->base, array('acl', 'info', 'extension', 'testing', 'revert', 'popularity', 'config', 'plugin', 'safefnrecode', 'authplain', 'testing', - 'template:dokuwiki', 'template:default' + 'template:dokuwiki' ) ); } -- cgit v1.2.3 From 220ab8d2dfa86c96112098922b40017448d3500a Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 5 Jan 2014 20:01:45 +0100 Subject: even more fixes for the bundled extension list --- lib/plugins/extension/helper/extension.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 2d0e91301..4eedb2a25 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -94,10 +94,10 @@ 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', 'testing', 'revert', 'popularity', - 'config', 'plugin', 'safefnrecode', 'authplain', 'testing', - 'template:dokuwiki' - ) + array( + 'authad', 'authldap', 'authmysql', 'authpgsql', 'authplain', 'acl', 'info', 'extension', + 'revert', 'popularity', 'config', 'plugin', 'safefnrecode', 'testing', 'template:dokuwiki' + ) ); } -- cgit v1.2.3 From 16660d32b7c1e36a9940ee0ee9b692bf0dd1c313 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 5 Jan 2014 20:29:14 +0100 Subject: use config for firguring out if an extension is protected --- lib/plugins/extension/helper/extension.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 4eedb2a25..e3cb8a410 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -107,7 +107,10 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return bool if the extension is protected */ public function isProtected() { - return in_array($this->id, array('acl', 'config', 'info', 'plugin', 'revert', 'usermanager', 'template:dokuwiki')); + /** @var Doku_Plugin_Controller $plugin_controller */ + global $plugin_controller; + $cascade = $plugin_controller->getCascade(); + return (isset($cascade['protected'][$this->id]) && $cascade['protected'][$this->id]); } /** -- cgit v1.2.3 From bcdcd3d147fd8bcc680f24de88120c23d9533b50 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 5 Jan 2014 20:39:25 +0100 Subject: do not show updates for bundled plugins --- lib/plugins/extension/helper/extension.php | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index e3cb8a410..be29f95d8 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -145,6 +145,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function updateAvailable() { if(!$this->isInstalled()) return false; + if($this->isBundled()) return false; $lastupdate = $this->getLastUpdate(); if ($lastupdate === false) return false; $installed = $this->getInstalledVersion(); -- cgit v1.2.3 From 5284857cb2f94bc347eb56c694d894283fc41703 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 5 Jan 2014 20:45:32 +0100 Subject: protect authplain and current auth plugin --- lib/plugins/extension/helper/extension.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index be29f95d8..2a7119189 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -102,11 +102,15 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } /** - * If the extension is protected + * If the extension is protected against any modification (disable/uninstall) * * @return bool if the extension is protected */ public function isProtected() { + // never allow deinstalling the current auth plugin: + global $conf; + if ($this->id == $conf['authtype']) return true; + /** @var Doku_Plugin_Controller $plugin_controller */ global $plugin_controller; $cascade = $plugin_controller->getCascade(); -- cgit v1.2.3 From 9672d9f3bf51a5b383078874035796c6ac776eb1 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 5 Jan 2014 20:58:48 +0100 Subject: removed the old plugin manager --- lib/plugins/extension/helper/extension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 2a7119189..9cf4848ad 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -96,7 +96,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { return in_array($this->base, array( 'authad', 'authldap', 'authmysql', 'authpgsql', 'authplain', 'acl', 'info', 'extension', - 'revert', 'popularity', 'config', 'plugin', 'safefnrecode', 'testing', 'template:dokuwiki' + 'revert', 'popularity', 'config', 'safefnrecode', 'testing', 'template:dokuwiki' ) ); } -- cgit v1.2.3 From a4667104ff9b4131c1aceaea022e65d0976a15d6 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sun, 5 Jan 2014 21:22:31 +0100 Subject: added git warning --- lib/plugins/extension/helper/extension.php | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 9cf4848ad..d200d5ab0 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -86,6 +86,16 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { return is_dir($this->getInstallDir()); } + /** + * If the extension is under git control + * + * @return bool + */ + public function isGitControlled() { + if(!$this->isInstalled()) return false; + return is_dir($this->getInstallDir().'/.git'); + } + /** * If the extension is bundled * -- cgit v1.2.3 From 77da6d6ca677e783f5e104226a179b5f09ab121d Mon Sep 17 00:00:00 2001 From: Anika Henke Date: Sun, 5 Jan 2014 22:25:41 +0000 Subject: added css and html changes for RTL scripts to extension manager --- lib/plugins/extension/helper/extension.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index d200d5ab0..02c2cc8ad 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -829,7 +829,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { // download if(!$file = io_download($url, $tmp.'/', true, $file, 0)) { $this->dir_delete($tmp); - throw new Exception(sprintf($this->getLang('error_download'), hsc($url))); + throw new Exception(sprintf($this->getLang('error_download'), ''.hsc($url).'')); } return $tmp.'/'.$file; @@ -921,7 +921,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { 'action' => $action ); } else { - throw new Exception(sprintf($this->getLang('error_copy').DOKU_LF, $item['base'])); + throw new Exception(sprintf($this->getLang('error_copy').DOKU_LF, ''.$item['base'].'')); } } -- cgit v1.2.3 From 0826f6cbd906e92fd040dfd3377f1b2a9db13873 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 6 Jan 2014 21:06:09 +0100 Subject: now use new core funtion to recursively delete --- lib/plugins/extension/helper/extension.php | 32 ++++-------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 02c2cc8ad..f91d237f7 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -33,7 +33,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function __destruct() { foreach($this->temporary as $dir){ - $this->dir_delete($dir); + io_rmdir($dir, true); } } @@ -640,7 +640,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function uninstall() { $this->purgeCache(); - return $this->dir_delete($this->getInstallDir()); + return io_rmdir($this->getInstallDir(), true); } /** @@ -768,30 +768,6 @@ 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); - } - } - /** * Returns a temporary directory * @@ -828,7 +804,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { // download if(!$file = io_download($url, $tmp.'/', true, $file, 0)) { - $this->dir_delete($tmp); + io_rmdir($tmp, true); throw new Exception(sprintf($this->getLang('error_download'), ''.hsc($url).'')); } @@ -926,7 +902,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } // cleanup - if($tmp) $this->dir_delete($tmp); + if($tmp) io_rmdir($tmp, true); return $installed_extensions; } -- cgit v1.2.3 From 189c9cabe204e2493f7d44f66361ad167f7e1c02 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 6 Jan 2014 21:29:52 +0100 Subject: purge cache only once on install this is not a extension specific cache but a global one. no need to purge for each installed extension --- lib/plugins/extension/helper/extension.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index f91d237f7..3f4906463 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -575,12 +575,8 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { try { $installed = $this->installArchive("$tmp/upload.archive", true, $basename); - - // purge caches - foreach($installed as $ext => $info){ - $this->setExtension($ext); - $this->purgeCache(); - } + // purge cache + $this->purgeCache(); }catch (Exception $e){ throw $e; } -- cgit v1.2.3 From cf37525f0abe7425193f3ec2bf426cf834a949a3 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Mon, 6 Jan 2014 21:31:14 +0100 Subject: typo fix --- lib/plugins/extension/helper/extension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 3f4906463..1676e3962 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -632,7 +632,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { /** * Uninstall the extension * - * @return bool If the plugin was sucessfully installed + * @return bool If the plugin was sucessfully uninstalled */ public function uninstall() { $this->purgeCache(); -- cgit v1.2.3 From ec8911d4970372f2a513cf4f1fe78c46c29ed67c Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 8 Jan 2014 20:18:04 +0100 Subject: remove unneeded try/catch blocks they were just catching and rethrowing --- lib/plugins/extension/helper/extension.php | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 1676e3962..3ff2ebcd8 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -613,19 +613,15 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { * @return array The list of installed extensions */ public function installOrUpdate() { - try { - $path = $this->download($this->getDownloadURL()); - $installed = $this->installArchive($path, $this->isInstalled(), $this->getBase()); + $path = $this->download($this->getDownloadURL()); + $installed = $this->installArchive($path, $this->isInstalled(), $this->getBase()); - // refresh extension information - if (!isset($installed[$this->getID()])) { - throw new Exception('Error, the requested extension hasn\'t been installed or updated'); - } - $this->setExtension($this->getID()); - $this->purgeCache(); - }catch (Exception $e){ - throw $e; + // refresh extension information + if (!isset($installed[$this->getID()])) { + throw new Exception('Error, the requested extension hasn\'t been installed or updated'); } + $this->setExtension($this->getID()); + $this->purgeCache(); return $installed; } @@ -828,11 +824,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { } // decompress - try{ - $this->decompress($file, "$tmp/".$base); - } catch (Exception $e) { - throw $e; - } + $this->decompress($file, "$tmp/".$base); // search $tmp/$base for the folder(s) that has been created // move the folder(s) to lib/.. -- cgit v1.2.3 From 4bad83d828217dc64292223b268c6a3674984070 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 8 Jan 2014 20:18:55 +0100 Subject: use DOKU_LF PHP_EOL is platform dependent, so you get in trouble while migrating between platforms. --- lib/plugins/extension/helper/extension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index 3ff2ebcd8..c13aa983d 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -737,7 +737,7 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { $file = @file($managerpath); if(!empty($file)) { foreach($file as $line) { - list($key, $value) = explode('=', trim($line, PHP_EOL), 2); + list($key, $value) = explode('=', trim($line, DOKU_LF), 2); $key = trim($key); $value = trim($value); // backwards compatible with old plugin manager -- cgit v1.2.3 From bc1b7a8a0fdd1812e352cab5e2362bd5770d5b3b Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Wed, 8 Jan 2014 20:28:17 +0100 Subject: better filename parsing The filename found in the URL will be used for old plugins missing a base entry in their plugin.info.txt and lacking a subdirectory inside the archive as well. This patch makes sure possible query strings aren't included in the filename. Note: io_download() will also try to get a filename from any content-disposition header. If no filename can be found we simply use an md5 sum of the URL and hope the plugin will contain it's own hint for naming. --- lib/plugins/extension/helper/extension.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib/plugins/extension/helper/extension.php') diff --git a/lib/plugins/extension/helper/extension.php b/lib/plugins/extension/helper/extension.php index c13aa983d..7958cd2da 100644 --- a/lib/plugins/extension/helper/extension.php +++ b/lib/plugins/extension/helper/extension.php @@ -783,11 +783,17 @@ class helper_plugin_extension_extension extends DokuWiki_Plugin { */ public function download($url) { // check the url - $matches = array(); - if(!preg_match('/[^\/]*$/', $url, $matches) || !$matches[0]) { + if(!preg_match('/https?:\/\//i', $url)){ throw new Exception($this->getLang('error_badurl')); } - $file = $matches[0]; + + // try to get the file from the path (used as plugin name fallback) + $file = parse_url($url, PHP_URL_PATH); + if(is_null($file)){ + $file = md5($url); + }else{ + $file = utf8_basename($file); + } // create tmp directory for download if(!($tmp = $this->mkTmpDir())) { -- cgit v1.2.3