2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Affero General Public License version 3 as published by the
8 * Free Software Foundation with the addition of the following permission added
9 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18 * You should have received a copy of the GNU Affero General Public License along with
19 * this program; if not, see http://www.gnu.org/licenses or write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU Affero General Public License version 3.
30 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33 * technical reasons, the Appropriate Legal Notices must display the words
34 * "Powered by SugarCRM".
35 ********************************************************************************/
38 define("CREDENTIAL_CATEGORY", "ml");
39 define("CREDENTIAL_USERNAME", "username");
40 define("CREDENTIAL_PASSWORD", "password");
42 require_once('include/nusoap/nusoap.php');
43 require_once('include/utils/zip_utils.php');
44 require_once('ModuleInstall/PackageManager/PackageManagerDisplay.php');
45 require_once('ModuleInstall/ModuleInstaller.php');
46 require_once('include/entryPoint.php');
47 require_once('ModuleInstall/PackageManager/PackageManagerComm.php');
53 * Constructor: In this method we will initialize the nusoap client to point to the hearbeat server
55 function PackageManager(){
56 $this->db = DBManagerFactory::getInstance();
57 $this->upload_dir = empty($GLOBALS['sugar_config']['upload_dir']) ? 'upload' : rtrim($GLOBALS['sugar_config']['upload_dir'], '/\\');
60 function initializeComm(){
65 * Obtain a promotion from SugarDepot
66 * @return string the string from the promotion
68 function getPromotion(){
69 $name_value_list = PackageManagerComm::getPromotion();
70 if(!empty($name_value_list)){
71 $name_value_list = PackageManager::fromNameValueList($name_value_list);
72 return $name_value_list['description'];
79 * Obtain a list of category/packages/releases for use within the module loader
81 function getModuleLoaderCategoryPackages($category_id = ''){
83 $filter = array('type' => "'module', 'theme', 'langpack'");
84 $filter = PackageManager::toNameValueList($filter);
85 return PackageManager::getCategoryPackages($category_id, $filter);
89 * Obtain the list of category_packages from SugarDepot
90 * @return category_packages
92 function getCategoryPackages($category_id = '', $filter = array()){
93 $results = PackageManagerComm::getCategoryPackages($category_id, $filter);
94 PackageManagerComm::errorCheck();
97 $nodes[$category_id]['packages'] = array();
98 if(!empty($results['categories'])){
99 foreach($results['categories'] as $category){
100 $mycat = PackageManager::fromNameValueList($category);
101 $nodes[$mycat['id']] = array('id' => $mycat['id'], 'label' => $mycat['name'], 'description' => $mycat['description'], 'type' => 'cat', 'parent' => $mycat['parent_id']);
102 $nodes[$mycat['id']]['packages'] = array();
105 if(!empty($results['packages'])){
106 $uh = new UpgradeHistory();
107 foreach($results['packages'] as $package){
108 $mypack = PackageManager::fromNameValueList($package);
109 $nodes[$mypack['category_id']]['packages'][$mypack['id']] = array('id' => $mypack['id'], 'label' => $mypack['name'], 'description' => $mypack['description'], 'category_id' => $mypack['category_id'], 'type' => 'package');
110 $releases = PackageManager::getReleases($category_id, $mypack['id'], $filter);
111 $arr_releases = array();
112 $nodes[$mypack['category_id']]['packages'][$mypack['id']]['releases'] = array();
113 if(!empty($releases['packages'])){
114 foreach($releases['packages'] as $release){
115 $myrelease = PackageManager::fromNameValueList($release);
116 //check to see if we already this one installed
117 $result = $uh->determineIfUpgrade($myrelease['id_name'], $myrelease['version']);
119 if($result == true || is_array($result))
121 $nodes[$mypack['category_id']]['packages'][$mypack['id']]['releases'][$myrelease['id']] = array('id' => $myrelease['id'], 'version' => $myrelease['version'], 'label' => $myrelease['description'], 'category_id' => $mypack['category_id'], 'package_id' => $mypack['id'], 'type' => 'release', 'enable' => $enable);
124 //array_push($nodes[$mypack['category_id']]['packages'], $package_arr);
127 $GLOBALS['log']->debug("NODES". var_export($nodes, true));
132 * Get a list of categories from the SugarDepot
133 * @param category_id the category id of parent to obtain
134 * @param filter an array of filters to pass to limit the query
135 * @return array an array of categories for display on the client
137 function getCategories($category_id, $filter = array()){
139 $results = PackageManagerComm::getCategories($category_id, $filter);
140 PackageManagerComm::errorCheck();
141 if(!empty($results['categories'])){
142 foreach($results['categories'] as $category){
143 $mycat = PackageManager::fromNameValueList($category);
144 $nodes[] = array('id' => $mycat['id'], 'label' => $mycat['name'], 'description' => $mycat['description'], 'type' => 'cat', 'parent' => $mycat['parent_id']);
150 function getPackages($category_id, $filter = array()){
152 $results = PackageManagerComm::getPackages($category_id, $filter);
153 PackageManagerComm::errorCheck();
156 //$xml .= '<packages>';
157 if(!empty($results['packages'])){
158 foreach($results['packages'] as $package){
159 $mypack = PackageManager::fromNameValueList($package);
160 $packages[$mypack['id']] = array('package_id' => $mypack['id'], 'name' => $mypack['name'], 'description' => $mypack['description'], 'category_id' => $mypack['category_id']);
161 $releases = PackageManager::getReleases($category_id, $mypack['id']);
162 $arr_releases = array();
163 foreach($releases['packages'] as $release){
164 $myrelease = PackageManager::fromNameValueList($release);
165 $arr_releases[$myrelease['id']] = array('release_id' => $myrelease['id'], 'version' => $myrelease['version'], 'description' => $myrelease['description'], 'category_id' => $mypack['category_id'], 'package_id' => $mypack['id']);
167 $packages[$mypack['id']]['releases'] = $arr_releases;
173 function getReleases($category_id, $package_id, $filter = array()){
174 $releases = PackageManagerComm::getReleases($category_id, $package_id, $filter);
175 PackageManagerComm::errorCheck();
180 * Retrieve the package as specified by the $id from the heartbeat server
182 * @param category_id the category_id to which the release belongs
183 * @param package_id the package_id to which the release belongs
184 * @param release_id the release_id to download
185 * @return filename - the path to which the zip file was saved
187 public function download($category_id, $package_id, $release_id)
189 $GLOBALS['log']->debug('RELEASE _ID: '.$release_id);
190 if(!empty($release_id)){
191 $filename = PackageManagerComm::addDownload($category_id, $package_id, $release_id);
193 $GLOBALS['log']->debug('RESULT: '.$filename);
194 PackageManagerComm::errorCheck();
195 $filepath = PackageManagerComm::performDownload($filename);
204 * Given the Mambo username, password, and download key attempt to authenticate, if
205 * successful then store these credentials
207 * @param username Mambo username
208 * @param password Mambo password
209 * @param systemname the user's download key
210 * @return true if successful, false otherwise
212 function authenticate($username, $password, $systemname='', $terms_checked = true){
213 PackageManager::setCredentials($username, $password, $systemname);
214 PackageManagerComm::clearSession();
215 $result = PackageManagerComm::login($terms_checked);
216 if(is_array($result))
222 function setCredentials($username, $password, $systemname){
224 $admin = new Administration();
225 $admin->retrieveSettings();
226 $admin->saveSetting(CREDENTIAL_CATEGORY, CREDENTIAL_USERNAME, $username);
227 $admin->saveSetting(CREDENTIAL_CATEGORY, CREDENTIAL_PASSWORD, $password);
228 if(!empty($systemname)){
229 $admin->saveSetting('system', 'name', $systemname);
233 function getCredentials(){
235 $admin = new Administration();
236 $admin->retrieveSettings(CREDENTIAL_CATEGORY, true);
237 $credentials = array();
238 $credentials['username'] = '';
239 $credentials['password'] = '';
240 $credentials['system_name'] = '';
241 if(!empty($admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_USERNAME])){
242 $credentials['username'] = $admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_USERNAME];
244 if(!empty($admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_USERNAME])){
245 $credentials['password'] = $admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_PASSWORD];
247 if(!empty($admin->settings['system_name'])){
248 $credentials['system_name'] = $admin->settings['system_name'];
253 function getTermsAndConditions(){
254 return PackageManagerComm::getTermsAndConditions();
259 * Retrieve documentation for the given release or package
261 * @param package_id the specified package to retrieve documentation
262 * @param release_id the specified release to retrieve documentation
266 function getDocumentation($package_id, $release_id){
267 if(!empty($release_id) || !empty($package_id)){
268 $documents = PackageManagerComm::getDocumentation($package_id, $release_id);
276 * Grab the list of installed modules and send that list to the depot.
277 * The depot will then send back a list of modules that need to be updated
279 function checkForUpdates(){
280 $lists = $this->buildInstalledReleases(array('module'), true);
283 $updates = PackageManagerComm::checkForUpdates($lists);
288 ////////////////////////////////////////////////////////
289 /////////// HELPER FUNCTIONS
290 function toNameValueList($array){
292 foreach($array as $name=>$value){
293 $list[] = array('name'=>$name, 'value'=>$value);
298 function toNameValueLists($arrays){
300 foreach($arrays as $array){
301 $lists[] = PackageManager::toNameValueList($array);
306 function fromNameValueList($nvl){
308 foreach($nvl as $list){
309 $array[$list['name']] = $list['value'];
314 function buildInstalledReleases($types = array('module')){
315 //1) get list of installed modules
316 $installeds = $this->getInstalled($types);
318 foreach($installeds as $installed){
319 $releases[] = array('name' => $installed->name, 'id_name' => $installed->id_name, 'version' => $installed->version, 'filename' => $installed->filename, 'type' => $installed->type);
323 $name_value_list = array();
324 if(!empty($releases)){
325 $lists = $this->toNameValueLists($releases);
330 function buildPackageXML($package, $releases = array()){
332 $xml .= '<package_id>'.$package['id'].'</package_id>';
333 $xml .= '<name>'.$package['name'].'</name>';
334 $xml .= '<description>'.$package['description'].'</description>';
335 if(!empty($releases)){
336 $xml .= '<releases>';
337 foreach($releases['packages'] as $release){
339 $myrelease = PackageManager::fromNameValueList($release);
341 $xml .= '<release_id>'.$myrelease['id'].'</release_id>';
342 $xml .= '<version>'.$myrelease['version'].'</version>';
343 $xml .= '<description>'.$myrelease['description'].'</description>';
344 $xml .= '<package_id>'.$package['id'].'</package_id>';
345 $xml .= '<category_id>'.$package['category_id'].'</category_id>';
346 $xml .= '</release>';
348 $xml .= '</releases>';
350 $xml .= '</package>';
354 private $cleanUpDirs = array();
356 private function addToCleanup($dir)
358 if(empty($this->cleanUpDirs)) {
359 register_shutdown_function(array($this, "cleanUpTempDir"));
361 $this->cleanUpDirs[] = $dir;
364 public function cleanUpTempDir()
366 foreach($this->cleanUpDirs as $dir) {
367 rmdir_recursive($dir);
371 //////////////////////////////////////////////////////////////////////
372 /////////// INSTALL SECTION
373 function extractFile( $zip_file, $file_in_zip, $base_tmp_upgrade_dir){
374 $my_zip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
375 $this->addToCleanup($my_zip_dir);
376 unzip_file( $zip_file, $file_in_zip, $my_zip_dir );
377 return( "$my_zip_dir/$file_in_zip" );
380 function extractManifest( $zip_file,$base_tmp_upgrade_dir ) {
381 global $sugar_config;
382 $base_upgrade_dir = $this->upload_dir."/upgrades";
383 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
384 return $this->extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir );
387 function validate_manifest( $manifest ){
388 // takes a manifest.php manifest array and validates contents
390 global $sugar_version;
391 global $sugar_flavor;
394 if( !isset($manifest['type']) ){
395 die($mod_strings['ERROR_MANIFEST_TYPE']);
397 $type = $manifest['type'];
398 $GLOBALS['log']->debug("Getting InstallType");
399 if( $this->getInstallType( "/$type/" ) == "" ){
400 $GLOBALS['log']->debug("Error with InstallType".$type);
401 die($mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'." );
403 $GLOBALS['log']->debug("Passed with InstallType");
404 if( isset($manifest['acceptable_sugar_versions']) ){
406 $matches_empty = true;
407 if( isset($manifest['acceptable_sugar_versions']['exact_matches']) ){
408 $matches_empty = false;
409 foreach( $manifest['acceptable_sugar_versions']['exact_matches'] as $match ){
410 if( $match == $sugar_version ){
415 if( !$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches']) ){
416 $matches_empty = false;
417 foreach( $manifest['acceptable_sugar_versions']['regex_matches'] as $match ){
418 if( preg_match( "/$match/", $sugar_version ) ){
424 if( !$matches_empty && !$version_ok ){
425 die( $mod_strings['ERROR_VERSION_INCOMPATIBLE'] . $sugar_version );
429 if( isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0 ){
431 foreach( $manifest['acceptable_sugar_flavors'] as $match ){
432 if( $match == $sugar_flavor ){
437 //die( $mod_strings['ERROR_FLAVOR_INCOMPATIBLE'] . $sugar_flavor );
442 function getInstallType( $type_string ){
445 $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
448 foreach( $subdirs as $subdir ){
449 if( preg_match( "#/$subdir/#", $type_string ) ){
453 // return empty if no match
457 function performSetup($tempFile, $view = 'module', $display_messages = true){
458 global $sugar_config,$mod_strings;
459 $base_filename = urldecode($tempFile);
460 $GLOBALS['log']->debug("BaseFileName: ".$base_filename);
461 $base_upgrade_dir = $this->upload_dir.'/upgrades';
462 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
463 $manifest_file = $this->extractManifest( $base_filename,$base_tmp_upgrade_dir);
464 $GLOBALS['log']->debug("Manifest: ".$manifest_file);
465 if($view == 'module')
466 $license_file = $this->extractFile($base_filename, 'LICENSE.txt', $base_tmp_upgrade_dir);
467 if(is_file($manifest_file)){
468 $GLOBALS['log']->debug("VALIDATING MANIFEST". $manifest_file);
469 require_once( $manifest_file );
470 $this->validate_manifest($manifest );
471 $upgrade_zip_type = $manifest['type'];
472 $GLOBALS['log']->debug("VALIDATED MANIFEST");
473 // exclude the bad permutations
474 if( $view == "module" ){
475 if ($upgrade_zip_type != "module" && $upgrade_zip_type != "theme" && $upgrade_zip_type != "langpack"){
476 $this->unlinkTempFiles();
477 if($display_messages)
478 die($mod_strings['ERR_UW_NOT_ACCEPTIBLE_TYPE']);
480 }elseif( $view == "default" ){
481 if($upgrade_zip_type != "patch" ){
482 $this->unlinkTempFiles();
483 if($display_messages)
484 die($mod_strings['ERR_UW_ONLY_PATCHES']);
488 $base_filename = preg_replace( "#\\\\#", "/", $base_filename );
489 $base_filename = basename( $base_filename );
490 mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" );
491 $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename";
492 $target_manifest = remove_file_extension( $target_path ) . "-manifest.php";
494 if( isset($manifest['icon']) && $manifest['icon'] != "" ){
495 $icon_location = $this->extractFile( $tempFile ,$manifest['icon'], $base_tmp_upgrade_dir );
496 $path_parts = pathinfo( $icon_location );
497 copy( $icon_location, remove_file_extension( $target_path ) . "-icon." . $path_parts['extension'] );
500 if( copy( $tempFile , $target_path ) ){
501 copy( $manifest_file, $target_manifest );
502 if($display_messages)
503 $messages = '<script>ajaxStatus.flashStatus("' .$base_filename.$mod_strings['LBL_UW_UPLOAD_SUCCESS'] . ', 5000");</script>';
505 if($display_messages)
506 $messages = '<script>ajaxStatus.flashStatus("' .$mod_strings['ERR_UW_UPLOAD_ERROR'] . ', 5000");</script>';
510 $this->unlinkTempFiles();
511 if($display_messages)
512 die($mod_strings['ERR_UW_NO_MANIFEST']);
518 function unlinkTempFiles() {
519 global $sugar_config;
520 @unlink($_FILES['upgrade_zip']['tmp_name']);
521 @unlink("upload://".$_FILES['upgrade_zip']['name']);
524 function performInstall($file, $silent=true){
525 global $sugar_config;
527 global $current_language;
528 $base_upgrade_dir = $this->upload_dir.'/upgrades';
529 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
530 if(!file_exists($base_tmp_upgrade_dir)){
531 mkdir_recursive($base_tmp_upgrade_dir, true);
534 $GLOBALS['log']->debug("INSTALLING: ".$file);
535 $mi = new ModuleInstaller();
536 $mi->silent = $silent;
537 $mod_strings = return_module_language($current_language, "Administration");
538 $GLOBALS['log']->debug("ABOUT TO INSTALL: ".$file);
539 if(preg_match("#.*\.zip\$#", $file)) {
540 $GLOBALS['log']->debug("1: ".$file);
541 // handle manifest.php
542 $target_manifest = remove_file_extension( $file ) . '-manifest.php';
543 include($target_manifest);
544 $GLOBALS['log']->debug("2: ".$file);
545 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
546 $this->addToCleanup($unzip_dir);
547 unzip($file, $unzip_dir );
548 $GLOBALS['log']->debug("3: ".$unzip_dir);
549 $id_name = $installdefs['id'];
550 $version = $manifest['version'];
551 $uh = new UpgradeHistory();
552 $previous_install = array();
553 if(!empty($id_name) & !empty($version))
554 $previous_install = $uh->determineIfUpgrade($id_name, $version);
555 $previous_version = (empty($previous_install['version'])) ? '' : $previous_install['version'];
556 $previous_id = (empty($previous_install['id'])) ? '' : $previous_install['id'];
558 if(!empty($previous_version)){
559 $mi->install($unzip_dir, true, $previous_version);
561 $mi->install($unzip_dir);
563 $GLOBALS['log']->debug("INSTALLED: ".$file);
564 $new_upgrade = new UpgradeHistory();
565 $new_upgrade->filename = $file;
566 $new_upgrade->md5sum = md5_file($file);
567 $new_upgrade->type = $manifest['type'];
568 $new_upgrade->version = $manifest['version'];
569 $new_upgrade->status = "installed";
570 //$new_upgrade->author = $manifest['author'];
571 $new_upgrade->name = $manifest['name'];
572 $new_upgrade->description = $manifest['description'];
573 $new_upgrade->id_name = $id_name;
574 $serial_manifest = array();
575 $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
576 $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
577 $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
578 $new_upgrade->manifest = base64_encode(serialize($serial_manifest));
579 //$new_upgrade->unique_key = (isset($manifest['unique_key'])) ? $manifest['unique_key'] : '';
580 $new_upgrade->save();
585 function performUninstall($name){
586 $uh = new UpgradeHistory();
588 $uh->id_name = $name;
589 $found = $uh->checkForExisting($uh);
591 global $sugar_config;
593 global $current_language;
594 $base_upgrade_dir = $this->upload_dir.'/upgrades';
595 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
596 if(is_file($found->filename)){
597 if(!isset($GLOBALS['mi_remove_tables']))$GLOBALS['mi_remove_tables'] = true;
598 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
599 unzip($found->filename, $unzip_dir );
600 $mi = new ModuleInstaller();
602 $mi->uninstall( "$unzip_dir");
604 unlink(remove_file_extension( $found->filename ) . '-manifest.php');
605 unlink($found->filename);
607 //file(s_ have been deleted or are not found in the directory, allow database delete to happen but no need to change filesystem
613 function getUITextForType( $type ){
614 if( $type == "full" ){
615 return( "Full Upgrade" );
617 if( $type == "langpack" ){
618 return( "Language Pack" );
620 if( $type == "module" ){
623 if( $type == "patch" ){
626 if( $type == "theme" ){
631 function getImageForType( $type ){
636 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "" ,null,null,'.gif', "Upgrade");
640 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',"Language Packs" );
644 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "" ,null,null,'.gif', "Module Loader");
648 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif', "Patch Upgrades" );
652 $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif', "Themes" );
661 function getPackagesInStaging($view = 'module'){
662 global $sugar_config;
663 global $current_language;
664 $uh = new UpgradeHistory();
665 $base_upgrade_dir = "upload://upgrades";
666 $uContent = findAllFiles( $base_upgrade_dir, array() , false, 'zip');
667 $upgrade_contents = array();
668 $content_values = array_values($uContent);
669 $alreadyProcessed = array();
670 foreach($content_values as $val){
671 if(empty($alreadyProcessed[$val])){
672 $upgrade_contents[] = $val;
673 $alreadyProcessed[$val] = true;
677 $upgrades_available = 0;
679 $mod_strings = return_module_language($current_language, "Administration");
680 foreach($upgrade_contents as $upgrade_content) {
681 if(!preg_match('#.*\.zip$#', strtolower($upgrade_content)) || preg_match("#.*./zips/.*#", strtolower($upgrade_content))) {
685 $the_base = basename($upgrade_content);
686 $the_md5 = md5_file($upgrade_content);
687 $md5_matches = $uh->findByMd5($the_md5);
688 $file_install = $upgrade_content;
689 if(empty($md5_matches))
691 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
692 if(file_exists($target_manifest)) {
693 require_once($target_manifest);
695 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
696 $version = empty($manifest['version']) ? '' : $manifest['version'];
697 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
699 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
700 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
701 $type = $this->getUITextForType( $manifest['type'] );
702 $manifest_type = $manifest['type'];
703 $dependencies = array();
704 if( isset( $manifest['dependencies']) ){
705 $dependencies = $manifest['dependencies'];
709 //check dependencies first
710 if(!empty($dependencies)) {
711 $uh = new UpgradeHistory();
712 $not_found = $uh->checkDependencies($dependencies);
713 if(!empty($not_found) && count($not_found) > 0){
714 $file_install = 'errors_'.$mod_strings['ERR_UW_NO_DEPENDENCY']."[".implode(',', $not_found)."]";
718 if($view == 'default' && $manifest_type != 'patch') {
723 && $manifest_type != 'module' && $manifest_type != 'theme' && $manifest_type != 'langpack') {
727 if(empty($manifest['icon'])) {
728 $icon = $this->getImageForType( $manifest['type'] );
730 $path_parts = pathinfo( $manifest['icon'] );
731 $icon = "<img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
734 $upgrades_available++;
736 $packages[] = array('name' => $name, 'version' => $version, 'published_date' => $published_date,
737 'description' => $description, 'uninstallable' =>$uninstallable, 'type' => $type,
738 'file' => fileToHash($upgrade_content), 'file_install' => fileToHash($upgrade_content), 'unFile' => fileToHash($upgrade_content));
744 function getLicenseFromFile($file){
745 global $sugar_config;
746 $base_upgrade_dir = $this->upload_dir.'/upgrades';
747 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
748 $license_file = $this->extractFile($file, 'LICENSE.txt', $base_tmp_upgrade_dir);
749 if(is_file($license_file)){
750 $contents = file_get_contents($license_file);
758 * Run the query to obtain the list of installed types as specified by the type param
760 * @param type an array of types you would like to search for
761 * type options include (theme, langpack, module, patch)
763 * @return an array of installed upgrade_history objects
765 function getInstalled($types = array('module')){
766 $uh = new UpgradeHistory();
768 for($i = 0; $i < count($types); $i++){
769 $in .= "'".$types[$i]."'";
770 if(($i+1) < count($types)){
774 $query = "SELECT * FROM ".$uh->table_name." WHERE type IN (".$in.")";
775 return $uh->getList($query);
778 function getinstalledPackages($types = array('module', 'langpack')){
779 global $sugar_config;
780 $installeds = $this->getInstalled($types);
782 $upgrades_installed = 0;
783 $uh = new UpgradeHistory();
784 $base_upgrade_dir = $this->upload_dir.'/upgrades';
785 $base_tmp_upgrade_dir = "$base_upgrade_dir/temp";
786 foreach($installeds as $installed)
789 $filename = from_html($installed->filename);
790 $date_entered = $installed->date_entered;
791 $type = $installed->type;
792 $version = $installed->version;
793 $uninstallable = false;
795 $description = $installed->description;
796 $name = $installed->name;
798 $enabled_string = 'ENABLED';
799 //if the name is empty then we should try to pull from manifest and populate upgrade_history_table
803 $upgrades_installed++;
811 $manifest_file = $this->extractManifest($filename, $base_tmp_upgrade_dir);
812 require_once($manifest_file);
813 $GLOBALS['log']->info("Filling in upgrade_history table");
815 if( isset( $manifest['name'] ) ){
816 $name = $manifest['name'];
817 $installed->name = $name;
819 if( isset( $manifest['description'] ) ){
820 $description = $manifest['description'];
821 $installed->description = $description;
823 if(isset($installdefs) && isset( $installdefs['id'] ) ){
824 $id_name = $installdefs['id'];
825 $installed->id_name = $id_name;
828 $serial_manifest = array();
829 $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
830 $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
831 $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
832 $installed->manifest = base64_encode(serialize($serial_manifest));
835 $serial_manifest = unserialize(base64_decode($installed->manifest));
836 $manifest = $serial_manifest['manifest'];
838 if(($upgrades_installed==0 || $uh->UninstallAvailable($installeds, $installed))
839 && is_file($filename) && !empty($manifest['is_uninstallable']))
841 $uninstallable = true;
843 $enabled = $installed->enabled;
845 $enabled_string = 'DISABLED';
846 $file_uninstall = $filename;
848 $file_uninstall = 'UNINSTALLABLE';
849 $enabled_string = 'UNINSTALLABLE';
851 $file_uninstall = fileToHash( $file_uninstall );
856 'version' => $version,
858 'published_date' => $date_entered,
859 'description' => $description,
860 'uninstallable' =>$uninstallable,
861 'file_install' => $file_uninstall ,
862 'file' => fileToHash($filename),
863 'enabled' => $enabled_string