PageRenderTime 62ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/models/updates.php

https://github.com/widgetfactory/jce-admin
PHP | 389 lines | 214 code | 75 blank | 100 comment | 53 complexity | 63f40a835f35d157cff2042568228541 MD5 | raw file
  1. <?php
  2. /**
  3. * @package JCE
  4. * @copyright Copyright (c) 2009-2015 Ryan Demmer. All rights reserved.
  5. * @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  6. * JCE is free software. This version may have been modified pursuant
  7. * to the GNU General Public License, and as distributed it includes or
  8. * is derivative of works licensed under the GNU General Public License or
  9. * other free or open source software licenses.
  10. */
  11. defined('_JEXEC') or die('RESTRICTED');
  12. // load base model
  13. require_once (dirname(__FILE__) . '/model.php');
  14. // load helper class
  15. require_once(dirname(dirname(__FILE__)) . '/helpers/updates.php');
  16. class WFModelUpdates extends WFModel {
  17. protected static $updateURL = 'https://www.joomlacontenteditor.net/index.php?option=com_updates&format=raw';
  18. public static function canUpdate() {
  19. if (UpdatesHelper::hasCURL() === false) {
  20. return UpdatesHelper::hasFOPEN();
  21. }
  22. return true;
  23. }
  24. /**
  25. * Get extension versions
  26. * @return Array
  27. */
  28. public function getVersions() {
  29. $db = JFactory::getDBO();
  30. $versions = array('joomla' => array(), 'jce' => array());
  31. // Get Component xml
  32. $com_xml = WFXMLHelper::parseInstallManifest(JPATH_ADMINISTRATOR . '/components/com_jce/jce.xml');
  33. // set component version
  34. $versions['joomla']['com_jce'] = $com_xml['version'];
  35. // get mediabox version
  36. $mediabox_xml_file = WF_JOOMLA15 ? JPATH_PLUGINS . '/system/jcemediabox.xml' : JPATH_PLUGINS . '/system/jcemediabox/jcemediabox.xml';
  37. // set mediabox version
  38. if (file_exists($mediabox_xml_file)) {
  39. $mediabox_xml = WFXMLHelper::parseInstallManifest($mediabox_xml_file);
  40. $versions['joomla']['plg_jcemediabox'] = $mediabox_xml['version'];
  41. }
  42. wfimport('admin.models.plugins');
  43. $model = new WFModelPlugins();
  44. // get all plugins
  45. $plugins = $model->getPlugins();
  46. // get all extensions
  47. $extensions = $model->getExtensions();
  48. foreach ($plugins as $plugin) {
  49. if ($plugin->core == 0) {
  50. $file = WF_EDITOR_PLUGINS . '/' . $plugin->name . '/' . $plugin->name . '.xml';
  51. $xml = WFXMLHelper::parseInstallManifest($file);
  52. $versions['jce']['jce_' . $plugin->name] = $xml['version'];
  53. }
  54. }
  55. foreach ($extensions as $extension) {
  56. if ($extension->core == 0) {
  57. $file = WF_EDITOR_EXTENSIONS . '/' . $extension->folder . '/' . $extension->extension . '.xml';
  58. $xml = WFXMLHelper::parseInstallManifest($file);
  59. $versions['jce']['jce_' . $extension->folder . '_' . $extension->extension] = $xml['version'];
  60. }
  61. }
  62. return $versions;
  63. }
  64. /**
  65. * Check for extension updates
  66. * @return String JSON string of updates
  67. */
  68. public function check() {
  69. $result = false;
  70. // Get all extensions and version numbers
  71. $data = array('task' => 'check', 'jversion' => WF_JOOMLA15 ? '1.5' : '2.5');
  72. wfimport('admin.helpers.extension');
  73. $component = WFExtensionHelper::getComponent();
  74. $params = new WFParameter($component->params, '', 'preferences');
  75. // get update key
  76. $key = $params->get('updates_key', '');
  77. $type = $params->get('updates_type', '');
  78. // encode it
  79. if (!empty($key)) {
  80. $data['key'] = urlencode($key);
  81. }
  82. if ($type) {
  83. $data['type'] = $type;
  84. }
  85. $req = array();
  86. // create request data
  87. foreach ($this->getVersions() as $type => $extension) {
  88. foreach ($extension as $item => $value) {
  89. $data[$type . '[' . urlencode($item) . ']'] = urlencode($value);
  90. }
  91. }
  92. foreach ($data as $key => $value) {
  93. $req[] = $key . '=' . urlencode($value);
  94. }
  95. // connect
  96. $result = $this->connect(self::$updateURL, implode('&', $req));
  97. return $result;
  98. }
  99. /**
  100. * Download update
  101. * @return String JSON string
  102. */
  103. public function download() {
  104. $app = JFactory::getApplication();
  105. jimport('joomla.filesystem.folder');
  106. jimport('joomla.filesystem.file');
  107. $config = JFactory::getConfig();
  108. $result = array('error' => WFText::_('WF_UPDATES_DOWNLOAD_ERROR'));
  109. $id = JRequest::getInt('id');
  110. $data = $this->connect(self::$updateURL . '&task=download&id=' . $id);
  111. if ($data) {
  112. $data = json_decode($data);
  113. if (isset($data->error)) {
  114. return json_encode(array('error' => $data->error));
  115. }
  116. // get update file
  117. if ($data->name && $data->url && $data->hash) {
  118. // create path for package file
  119. $path = $app->getCfg('tmp_path') . '/' . basename($data->name);
  120. // download file
  121. if ($this->connect($data->url, null, $path)) {
  122. if (JFile::exists($path) && @filesize($path) > 0) {
  123. // check hash and file type
  124. if ($data->hash == md5(md5_file($path)) && preg_match('/\.(zip|tar|gz)$/', $path)) {
  125. $result = array('file' => basename($path), 'hash' => $data->hash, 'installer' => $data->installer, 'type' => isset($data->type) ? $data->type : '');
  126. } else {
  127. // fail and delete file
  128. $result = array('error' => WFText::_('WF_UPDATES_ERROR_FILE_VERIFICATION_FAIL'));
  129. if (JFile::exists($path)) {
  130. @JFile::delete($path);
  131. }
  132. }
  133. } else {
  134. $result = array('error' => WFText::_('WF_UPDATES_ERROR_FILE_MISSING_OR_INVALID'));
  135. }
  136. } else {
  137. $result = array('error' => WFText::_('WF_UPDATES_DOWNLOAD_ERROR_DATA_TRANSFER'));
  138. }
  139. } else {
  140. $result = array('error' => WFText::_('WF_UPDATES_DOWNLOAD_ERROR_MISSING_DATA'));
  141. }
  142. }
  143. return json_encode($result);
  144. }
  145. /**
  146. * Method to detect the extension type from a package directory
  147. *
  148. * @param string $dir Path to package directory
  149. * @return mixed Extension type string or boolean false on fail
  150. *
  151. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  152. */
  153. public static function detectType($dir) {
  154. // Search the install dir for an XML file
  155. $files = JFolder::files($dir, '\.xml$', 1, true);
  156. if (!count($files)) {
  157. return false;
  158. }
  159. foreach ($files as $file) {
  160. $xml = @simplexml_load_file($file);
  161. if (!$xml) {
  162. continue;
  163. }
  164. $name = $xml->getName();
  165. if ($name != 'extension' && $name != 'install') {
  166. unset($xml);
  167. continue;
  168. }
  169. $type = (string) $xml->attributes()->type;
  170. // Free up memory
  171. unset($xml);
  172. return $type;
  173. }
  174. // Free up memory.
  175. unset($xml);
  176. return false;
  177. }
  178. /**
  179. * Unpacks a file and verifies it as a Joomla element package
  180. * Supports .gz .tar .tar.gz and .zip
  181. *
  182. * @param string $archive The uploaded package filename or install directory
  183. * @return mixed Array on success or boolean false on failure
  184. *
  185. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  186. */
  187. private static function unpack($archive) {
  188. jimport('joomla.filesystem.file');
  189. jimport('joomla.filesystem.archive');
  190. jimport('joomla.installer.helper');
  191. // Temporary folder to extract the archive into
  192. $tmpdir = uniqid('install_');
  193. // Clean the paths to use for archive extraction
  194. $extractdir = JPath::clean(dirname($archive) . '/' . $tmpdir);
  195. // Do the unpacking of the archive
  196. try {
  197. JArchive::extract($archive, $extractdir);
  198. } catch (Exception $e) {
  199. JInstallerHelper::cleanupInstall($archive, $extractdir);
  200. return false;
  201. }
  202. /*
  203. * Let's set the extraction directory and package file in the result array so we can
  204. * cleanup everything properly later on.
  205. */
  206. $retval['extractdir'] = $extractdir;
  207. $retval['packagefile'] = $archive;
  208. /*
  209. * Try to find the correct install directory. In case the package is inside a
  210. * subdirectory detect this and set the install directory to the correct path.
  211. *
  212. * List all the items in the installation directory. If there is only one, and
  213. * it is a folder, then we will set that folder to be the installation folder.
  214. */
  215. $dirList = array_merge(JFolder::files($extractdir, ''), JFolder::folders($extractdir, ''));
  216. if (count($dirList) == 1) {
  217. if (JFolder::exists($extractdir . '/' . $dirList[0])) {
  218. $extractdir = JPath::clean($extractdir . '/' . $dirList[0]);
  219. }
  220. }
  221. $retval['dir'] = $extractdir;
  222. /*
  223. * Get the extension type and return the directory/type array on success or
  224. * false on fail.
  225. */
  226. $retval['type'] = self::detectType($extractdir);
  227. if ($retval['type']) {
  228. return $retval;
  229. } else {
  230. JInstallerHelper::cleanupInstall($archive, $extractdir);
  231. return false;
  232. }
  233. }
  234. /**
  235. * Install extension update
  236. * @return String JSON string
  237. */
  238. public function install() {
  239. jimport('joomla.installer.installer');
  240. jimport('joomla.installer.helper');
  241. jimport('joomla.filesystem.file');
  242. $app = JFactory::getApplication();
  243. $result = array('error' => WFText::_('WF_UPDATES_INSTALL_ERROR'));
  244. // get vars
  245. $file = JRequest::getCmd('file');
  246. $hash = JRequest::getVar('hash', '', 'POST', 'alnum');
  247. $method = JRequest::getWord('installer');
  248. $type = JRequest::getWord('type');
  249. // check for vars
  250. if ($file && $hash && $method) {
  251. $path = $app->getCfg('tmp_path') . '/' . $file;
  252. // check if file exists
  253. if (JFile::exists($path)) {
  254. // check hash
  255. if ($hash == md5(md5_file($path))) {
  256. $package = self::unpack($path);
  257. if ($package) {
  258. // Install a JCE Add-on
  259. if ($method == 'jce') {
  260. wfimport('admin.classes.installer');
  261. $installer = WFInstaller::getInstance();
  262. // install
  263. if ($installer->install($package['dir'])) {
  264. // installer message
  265. $result = array('error' => '', 'text' => WFText::_($installer->get('message'), $installer->get('message')));
  266. }
  267. // Install a Joomla! Extension
  268. } else {
  269. jimport('joomla.installer.installer');
  270. // get new Installer instance
  271. $installer = JInstaller::getInstance();
  272. if ($installer->install($package['dir'])) {
  273. // installer message
  274. $result = array('error' => '', 'text' => WFText::_($installer->get('message'), $installer->get('message')));
  275. }
  276. }
  277. // Cleanup the install files
  278. JInstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
  279. } else {
  280. $result = array('error' => WFText::_('WF_UPDATES_ERROR_FILE_EXTRACT_FAIL'));
  281. JFile::delete($path);
  282. }
  283. } else {
  284. $result = array('error' => WFText::_('WF_UPDATES_ERROR_FILE_VERIFICATION_FAIL'));
  285. }
  286. } else {
  287. $result = array('error' => WFText::_('WF_UPDATES_ERROR_FILE_MISSING_OR_INVALID'));
  288. }
  289. }
  290. return json_encode($result);
  291. }
  292. /**
  293. * @copyright Copyright (C) 2009 Ryan Demmer. All rights reserved.
  294. * @copyright Copyright (C) 2006-2010 Nicholas K. Dionysopoulos
  295. * @param String $url URL to resource
  296. * @param Array $data [optional] Array of key value pairs
  297. * @param String $download [optional] path to file to write to
  298. * @return Mixed Boolean or JSON String on error
  299. */
  300. protected function connect($url, $data = '', $download = '') {
  301. @error_reporting(E_ERROR);
  302. $result = false;
  303. if ($download) {
  304. return UpdatesHelper::download($url, $download);
  305. } else {
  306. $result = UpdatesHelper::check($url, $data);
  307. if ($result === false) {
  308. return array('error' => WFText::_('Update check failed : Invalid response from update server'));
  309. }
  310. }
  311. return $result;
  312. }
  313. }
  314. ?>