BxDolStudioInstallerUtils.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup DolphinStudio Dolphin Studio
  7. * @{
  8. */
  9. bx_import('BxDolInstallerUtils');
  10. define('BX_DOL_UNITY_URL_ROOT', 'http://www.boonex.com/');
  11. define('BX_DOL_UNITY_URL_MARKET', BX_DOL_UNITY_URL_ROOT . 'market/');
  12. class BxDolStudioInstallerUtils extends BxDolInstallerUtils implements iBxDolSingleton
  13. {
  14. public function __construct()
  15. {
  16. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  17. trigger_error ('Multiple instances are not allowed for the class: ' . get_class($this), E_USER_ERROR);
  18. parent::__construct();
  19. }
  20. /**
  21. * Prevent cloning the instance
  22. */
  23. public function __clone()
  24. {
  25. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  26. trigger_error('Clone is not allowed for the class: ' . get_class($this), E_USER_ERROR);
  27. }
  28. /**
  29. * Get singleton instance of the class
  30. */
  31. public static function getInstance()
  32. {
  33. if (!isset($GLOBALS['bxDolClasses'][__CLASS__]))
  34. $GLOBALS['bxDolClasses'][__CLASS__] = new BxDolStudioInstallerUtils();
  35. return $GLOBALS['bxDolClasses'][__CLASS__];
  36. }
  37. public function perform($sDirectory, $sOperation, $aParams = array())
  38. {
  39. $sConfigFile = 'install/config.php';
  40. $sInstallerFile = 'install/installer.php';
  41. $sInstallerClass = $sOperation == 'update' ? 'Updater' : 'Installer';
  42. $aConfig = self::getModuleConfig(BX_DIRECTORY_PATH_MODULES . $sDirectory . $sConfigFile);
  43. $sPathInstaller = BX_DIRECTORY_PATH_MODULES . $sDirectory . $sInstallerFile;
  44. if(!empty($aConfig) && file_exists($sPathInstaller)) {
  45. require_once($sPathInstaller);
  46. $sClassName = $aConfig['class_prefix'] . $sInstallerClass;
  47. $oInstaller = new $sClassName($aConfig);
  48. $aResult = $oInstaller->$sOperation($aParams);
  49. $aResult = array(
  50. 'code' => $aResult['result'] ? 0 : 1,
  51. 'message' => $aResult['message'],
  52. );
  53. }
  54. else
  55. $aResult = array(
  56. 'code' => 2,
  57. 'message' => _t('_adm_mod_err_process_operation_failed', $sOperation, $sDirectory),
  58. );
  59. return $aResult;
  60. }
  61. public function getModules()
  62. {
  63. $aModules = array();
  64. $oTemplate = BxDolStudioTemplate::getInstance();
  65. $aInstalledPathes = $aInstalledInfo = array();
  66. $this->getInstalledInfo($aInstalledPathes, $aInstalledInfo);
  67. $sPath = BX_DIRECTORY_PATH_MODULES;
  68. if(($rHandleVendor = opendir($sPath)) !== false) {
  69. while(($sVendor = readdir($rHandleVendor)) !== false) {
  70. if(substr($sVendor, 0, 1) == '.' || !is_dir($sPath . $sVendor))
  71. continue;
  72. if(($rHandleModule = opendir($sPath . $sVendor)) !== false) {
  73. while(($sModule = readdir($rHandleModule)) !== false) {
  74. if(!is_dir($sPath . $sVendor . '/' . $sModule) || substr($sModule, 0, 1) == '.')
  75. continue;
  76. $sConfigPath = $sPath . $sVendor . '/' . $sModule . '/install/config.php';
  77. $aModule = $this->getConfigModule($sConfigPath, $aInstalledPathes, $aInstalledInfo);
  78. if(empty($aModule))
  79. continue;
  80. $aModules[$aModule['title']] = $aModule;
  81. }
  82. closedir($rHandleModule);
  83. }
  84. }
  85. closedir($rHandleVendor);
  86. }
  87. ksort($aModules);
  88. return $aModules;
  89. }
  90. public function getUpdates()
  91. {
  92. $aUpdates = array();
  93. bx_import('BxDolStudioTemplate');
  94. $oTemplate = BxDolStudioTemplate::getInstance();
  95. $aInstalledPathes = $aInstalledInfo = array();
  96. $this->getInstalledInfo($aInstalledPathes, $aInstalledInfo);
  97. $sPath = BX_DIRECTORY_PATH_MODULES;
  98. if(($rHandleVendor = opendir($sPath)) !== false) {
  99. while(($sVendor = readdir($rHandleVendor)) !== false) {
  100. if(substr($sVendor, 0, 1) == '.' || !is_dir($sPath . $sVendor))
  101. continue;
  102. if(($rHandleModule = opendir($sPath . $sVendor . '/')) !== false) {
  103. while(($sModule = readdir($rHandleModule)) !== false) {
  104. if(!is_dir($sPath . $sVendor . '/' . $sModule) || substr($sModule, 0, 1) == '.')
  105. continue;
  106. if(($rHandleUpdate = @opendir($sPath . $sVendor . '/' . $sModule . '/updates/')) !== false) {
  107. while(($sUpdate = readdir($rHandleUpdate)) !== false) {
  108. if(!is_dir($sPath . $sVendor . '/' . $sModule . '/updates/' . $sUpdate) || substr($sUpdate, 0, 1) == '.')
  109. continue;
  110. $sConfigPathModule = $sPath . $sVendor . '/' . $sModule . '/install/config.php';
  111. $sConfigPathUpdate = $sPath . $sVendor . '/' . $sModule . '/updates/' . $sUpdate . '/install/config.php';
  112. $aUpdate = $this->getConfigUpdate($sConfigPathModule, $sConfigPathUpdate, $aInstalledPathes, $aInstalledInfo);
  113. if(empty($aUpdate))
  114. continue;
  115. $aUpdates[$aUpdate['title']] = $aUpdate;
  116. }
  117. closedir($rHandleUpdate);
  118. }
  119. }
  120. closedir($rHandleModule);
  121. }
  122. }
  123. closedir($rHandleVendor);
  124. }
  125. ksort($aUpdates);
  126. return $aUpdates;
  127. }
  128. public function checkUpdates($bAuthorizedAccess = false)
  129. {
  130. bx_import('BxDolModuleQuery');
  131. $aModules = BxDolModuleQuery::getInstance()->getModules();
  132. $aProducts = array();
  133. foreach($aModules as $aModule) {
  134. if(empty($aModule['name']))
  135. continue;
  136. $aProducts[] = array(
  137. 'name' => $aModule['name'],
  138. 'version' => $aModule['version'],
  139. 'hash' => $aModule['hash'],
  140. );
  141. }
  142. $sProducts = base64_encode(serialize($aProducts));
  143. if($bAuthorizedAccess) {
  144. bx_import('BxDolStudioOAuth');
  145. return BxDolStudioOAuth::getInstance()->loadItems(array('dol_type' => 'available_updates', 'dol_products' => $sProducts));
  146. }
  147. bx_import('BxDolStudioJson');
  148. return BxDolStudioJson::getInstance()->load(BX_DOL_UNITY_URL_MARKET . 'json_browse_updates', array(
  149. 'products' => $sProducts,
  150. 'domain' => BX_DOL_URL_ROOT,
  151. 'user' => (int)getParam('sys_oauth_user')
  152. ));
  153. }
  154. public function downloadFileAuthorized($iFileId)
  155. {
  156. bx_import('BxDolStudioOAuth');
  157. $aItem = BxDolStudioOAuth::getInstance()->loadItems(array('dol_type' => 'product_file', 'dol_file_id' => $iFileId));
  158. return $this->downloadFile($aItem);
  159. }
  160. public function downloadUpdatePublic($sModuleName)
  161. {
  162. bx_import('BxDolModuleQuery');
  163. $aModule = BxDolModuleQuery::getInstance()->getModuleByName($sModuleName);
  164. bx_import('BxDolStudioJson');
  165. $aItem = BxDolStudioJson::getInstance()->load(BX_DOL_UNITY_URL_MARKET . 'json_download_update', array(
  166. 'product' => base64_encode(serialize(array(
  167. 'name' => $aModule['name'],
  168. 'version' => $aModule['version'],
  169. 'hash' => $aModule['hash'],
  170. ))),
  171. 'domain' => BX_DOL_URL_ROOT,
  172. 'user' => (int)getParam('sys_oauth_user')
  173. ));
  174. return $this->downloadFile($aItem);
  175. }
  176. protected function downloadFile($aItem, $bUseFtp = BX_FORCE_USE_FTP_FILE_TRANSFER)
  177. {
  178. if(empty($aItem) || !is_array($aItem))
  179. return $aItem;
  180. //--- write ZIP archive.
  181. $sFilePath = BX_DIRECTORY_PATH_TMP . $aItem['name'];
  182. if (!$rHandler = fopen($sFilePath, 'w'))
  183. return _t('_adm_str_err_cannot_write');
  184. if (!fwrite($rHandler, urldecode($aItem['content'])))
  185. return _t('_adm_str_err_cannot_write');
  186. fclose($rHandler);
  187. //--- Unarchive package.
  188. if(!class_exists('ZipArchive'))
  189. return _t('_adm_str_err_zip_not_available');
  190. $oZip = new ZipArchive();
  191. if($oZip->open($sFilePath) !== true)
  192. return _t('_adm_str_err_cannot_unzip_package');
  193. $sPackageRootFolder = $oZip->numFiles > 0 ? $oZip->getNameIndex(0) : false;
  194. if($sPackageRootFolder && file_exists(BX_DIRECTORY_PATH_TMP . $sPackageRootFolder)) // remove existing tmp folder with the same name
  195. bx_rrmdir(BX_DIRECTORY_PATH_TMP . $sPackageRootFolder);
  196. if($sPackageRootFolder && !$oZip->extractTo(BX_DIRECTORY_PATH_TMP))
  197. return _t('_adm_str_err_cannot_unzip_package');
  198. $oZip->close();
  199. //--- Move unarchived package.
  200. if($bUseFtp) {
  201. $sLogin = getParam('sys_ftp_login');
  202. $sPassword = getParam('sys_ftp_password');
  203. $sPath = getParam('sys_ftp_dir');
  204. if(empty($sLogin) || empty($sPassword) || empty($sPath))
  205. return _t('_adm_str_err_no_ftp_info');
  206. bx_import('BxDolFtp');
  207. $oFile = new BxDolFtp($_SERVER['HTTP_HOST'], $sLogin, $sPassword, $sPath);
  208. if(!$oFile->connect())
  209. return _t('_adm_str_err_cannot_connect_to_ftp');
  210. if(!$oFile->isDolphin())
  211. return _t('_adm_str_err_destination_not_valid');
  212. }
  213. else {
  214. bx_import('BxDolFile');
  215. $oFile = BxDolFile::getInstance();
  216. }
  217. $aConfig = self::getModuleConfig(BX_DIRECTORY_PATH_TMP . $sPackageRootFolder . 'install/config.php');
  218. if(empty($aConfig) || !is_array($aConfig) || empty($aConfig['home_dir']))
  219. return _t('_adm_str_err_wrong_package_format');
  220. if(!$oFile->copy(BX_DIRECTORY_PATH_TMP . $sPackageRootFolder, 'modules/' . $aConfig['home_dir']))
  221. return _t('_adm_str_err_files_copy_failed');
  222. return true;
  223. }
  224. protected function getConfigModule($sConfigPath, $aInstalledPathes = array(), $aInstalledInfo = array())
  225. {
  226. $aConfig = self::getModuleConfig($sConfigPath);
  227. if(empty($aConfig) || !is_array($aConfig))
  228. return array();
  229. $sModulePath = $aConfig['home_dir'];
  230. $bInstalled = !empty($aInstalledPathes) && in_array($sModulePath, $aInstalledPathes);
  231. $bEnabled = $bInstalled && !empty($aInstalledInfo) && (int)$aInstalledInfo[$sModulePath]['enabled'] == 1;
  232. return array(
  233. 'type' => $aConfig['type'],
  234. 'name' => isset($aConfig['name']) ? $aConfig['name'] : $aConfig['home_uri'],
  235. 'title' => bx_process_output($aConfig['title']),
  236. 'vendor' => $aConfig['vendor'],
  237. 'version' => $aConfig['version'],
  238. 'uri' => $aConfig['home_uri'],
  239. 'dir' => $aConfig['home_dir'],
  240. 'note' => isset($aConfig['note']) ? bx_process_output($aConfig['note']) : '',
  241. 'installed' => $bInstalled,
  242. 'enabled' => $bInstalled && $bEnabled
  243. );
  244. }
  245. protected function getConfigUpdate($sConfigPathModule, $sConfigPathUpdate, $aInstalledPathes = array(), $aInstalledInfo = array())
  246. {
  247. $aModule = $this->getConfigModule($sConfigPathModule, $aInstalledPathes, $aInstalledInfo);
  248. if(empty($aModule) || !$aModule['installed'])
  249. return array();
  250. $aConfig = self::getModuleConfig($sConfigPathUpdate);
  251. if(empty($aConfig) || !is_array($aConfig))
  252. return array();
  253. return array(
  254. 'title' => bx_process_output($aConfig['title']),
  255. 'vendor' => $aConfig['vendor'],
  256. 'version_from' => $aConfig['version_from'],
  257. 'version_to' => $aConfig['version_to'],
  258. 'dir' => $aConfig['home_dir'],
  259. 'module_type' => $aModule['type'],
  260. 'module_name' => $aModule['name'],
  261. 'module_dir' => $aModule['dir']
  262. );
  263. }
  264. private function getInstalledInfo(&$aInstalledPathes, &$aInstalledInfo)
  265. {
  266. bx_import('BxDolModuleDb');
  267. $aModules = BxDolModuleDb::getInstance()->getModules();
  268. $aInstalledInfo = array();
  269. foreach($aModules as $aModule)
  270. $aInstalledInfo[$aModule['path']] = $aModule;
  271. $aInstalledPathes = array_keys($aInstalledInfo);
  272. }
  273. }
  274. /** @} */