]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - ModuleInstall/PackageManager/PackageManager.php
Release 6.5.15
[Github/sugarcrm.git] / ModuleInstall / PackageManager / PackageManager.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5  * 
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.
12  * 
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
16  * details.
17  * 
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
21  * 02110-1301 USA.
22  * 
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.
25  * 
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.
29  * 
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  ********************************************************************************/
36
37
38 define("CREDENTIAL_CATEGORY", "ml");
39 define("CREDENTIAL_USERNAME", "username");
40 define("CREDENTIAL_PASSWORD", "password");
41
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');
48
49 class PackageManager{
50     var $soap_client;
51
52     /**
53      * Constructor: In this method we will initialize the nusoap client to point to the hearbeat server
54      */
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'], '/\\');
58     }
59
60     function initializeComm(){
61
62     }
63
64     /**
65      * Obtain a promotion from SugarDepot
66      * @return string   the string from the promotion
67      */
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'];
73         }else {
74            return '';
75         }
76     }
77
78     /**
79      * Obtain a list of category/packages/releases for use within the module loader
80      */
81     function getModuleLoaderCategoryPackages($category_id = ''){
82         $filter = array();
83         $filter = array('type' => "'module', 'theme', 'langpack'");
84         $filter = PackageManager::toNameValueList($filter);
85         return PackageManager::getCategoryPackages($category_id, $filter);
86     }
87
88     /**
89      * Obtain the list of category_packages from SugarDepot
90      * @return category_packages
91      */
92     function getCategoryPackages($category_id = '', $filter = array()){
93          $results = PackageManagerComm::getCategoryPackages($category_id, $filter);
94          PackageManagerComm::errorCheck();
95          $nodes = array();
96
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();
103                  }
104         }
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']);
118                                  $enable = false;
119                                  if($result == true || is_array($result))
120                                          $enable = true;
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);
122                                 }
123                     }
124                     //array_push($nodes[$mypack['category_id']]['packages'], $package_arr);
125                  }
126          }
127          $GLOBALS['log']->debug("NODES". var_export($nodes, true));
128         return $nodes;
129     }
130
131     /**
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
136      */
137     function getCategories($category_id, $filter = array()){
138         $nodes = 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']);
145                 }
146         }
147         return $nodes;
148     }
149
150     function getPackages($category_id, $filter = array()){
151         $nodes = array();
152         $results = PackageManagerComm::getPackages($category_id, $filter);
153         PackageManagerComm::errorCheck();
154         $packages = array();
155         //$xml = '';
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']);
166                     }
167                     $packages[$mypack['id']]['releases'] = $arr_releases;
168                 }
169         }
170         return $packages;
171     }
172
173     function getReleases($category_id, $package_id, $filter = array()){
174         $releases = PackageManagerComm::getReleases($category_id, $package_id, $filter);
175         PackageManagerComm::errorCheck();
176         return $releases;
177     }
178
179     /**
180      * Retrieve the package as specified by the $id from the heartbeat server
181      *
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
186      */
187     public function download($category_id, $package_id, $release_id)
188     {
189         $GLOBALS['log']->debug('RELEASE _ID: '.$release_id);
190         if(!empty($release_id)){
191             $filename = PackageManagerComm::addDownload($category_id, $package_id, $release_id);
192             if($filename){
193                     $GLOBALS['log']->debug('RESULT: '.$filename);
194                     PackageManagerComm::errorCheck();
195                         $filepath = PackageManagerComm::performDownload($filename);
196                         return $filepath;
197             }
198         }else{
199             return null;
200         }
201     }
202
203     /**
204      * Given the Mambo username, password, and download key attempt to authenticate, if
205      * successful then store these credentials
206      *
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
211      */
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))
217                 return $result;
218         else
219                 return true;
220     }
221
222     function setCredentials($username, $password, $systemname){
223
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);
230          }
231     }
232
233     function getCredentials(){
234
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];
243         }
244         if(!empty($admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_USERNAME])){
245            $credentials['password'] = $admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_PASSWORD];
246         }
247         if(!empty($admin->settings['system_name'])){
248            $credentials['system_name'] = $admin->settings['system_name'];
249         }
250         return $credentials;
251     }
252
253     function getTermsAndConditions(){
254         return PackageManagerComm::getTermsAndConditions();
255
256     }
257
258     /**
259      * Retrieve documentation for the given release or package
260      *
261      * @param package_id        the specified package to retrieve documentation
262      * @param release_id        the specified release to retrieve documentation
263      *
264      * @return documents
265      */
266     function getDocumentation($package_id, $release_id){
267          if(!empty($release_id) || !empty($package_id)){
268             $documents = PackageManagerComm::getDocumentation($package_id, $release_id);
269             return $documents;
270         }else{
271             return null;
272         }
273     }
274
275     /**
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
278      */
279     function checkForUpdates(){
280         $lists = $this->buildInstalledReleases(array('module'), true);
281                 $updates = array();
282                 if(!empty($lists)){
283                         $updates = PackageManagerComm::checkForUpdates($lists);
284                 }//fi
285                 return $updates;
286     }
287
288      ////////////////////////////////////////////////////////
289      /////////// HELPER FUNCTIONS
290     function toNameValueList($array){
291                 $list = array();
292                 foreach($array as $name=>$value){
293                         $list[] = array('name'=>$name, 'value'=>$value);
294                 }
295                 return $list;
296         }
297
298         function toNameValueLists($arrays){
299                 $lists = array();
300                 foreach($arrays as $array){
301                         $lists[] = PackageManager::toNameValueList($array);
302                 }
303                 return $lists;
304         }
305
306      function fromNameValueList($nvl){
307         $array = array();
308         foreach($nvl as $list){
309             $array[$list['name']] = $list['value'];
310         }
311         return $array;
312     }
313
314     function buildInstalledReleases($types = array('module')){
315         //1) get list of installed modules
316                 $installeds = $this->getInstalled($types);
317                 $releases = array();
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);
320                 }
321
322                 $lists = array();
323                 $name_value_list = array();
324                 if(!empty($releases)){
325                         $lists = $this->toNameValueLists($releases);
326                 }//fi
327                 return $lists;
328     }
329
330     function buildPackageXML($package, $releases = array()){
331         $xml = '<package>';
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){
338
339                  $myrelease = PackageManager::fromNameValueList($release);
340                  $xml .= '<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>';
347              }
348              $xml .= '</releases>';
349         }
350         $xml .= '</package>';
351         return $xml;
352     }
353
354     private $cleanUpDirs = array();
355
356     private function addToCleanup($dir)
357     {
358         if(empty($this->cleanUpDirs)) {
359             register_shutdown_function(array($this, "cleanUpTempDir"));
360         }
361         $this->cleanUpDirs[] = $dir;
362     }
363
364     public function cleanUpTempDir()
365     {
366         foreach($this->cleanUpDirs as $dir) {
367             rmdir_recursive($dir);
368         }
369     }
370
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" );
378     }
379
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 );
385     }
386
387     function validate_manifest( $manifest ){
388     // takes a manifest.php manifest array and validates contents
389     global $subdirs;
390     global $sugar_version;
391     global $sugar_flavor;
392     global $mod_strings;
393
394     if( !isset($manifest['type']) ){
395         die($mod_strings['ERROR_MANIFEST_TYPE']);
396     }
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 . "'." );
402     }
403     $GLOBALS['log']->debug("Passed with InstallType");
404     if( isset($manifest['acceptable_sugar_versions']) ){
405             $version_ok = false;
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 ){
411                         $version_ok = true;
412                     }
413                 }
414             }
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 ) ){
419                         $version_ok = true;
420                     }
421                 }
422             }
423
424             if( !$matches_empty && !$version_ok ){
425                 die( $mod_strings['ERROR_VERSION_INCOMPATIBLE'] . $sugar_version );
426             }
427         }
428
429      if( isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0 ){
430             $flavor_ok = false;
431             foreach( $manifest['acceptable_sugar_flavors'] as $match ){
432                 if( $match == $sugar_flavor ){
433                     $flavor_ok = true;
434                 }
435             }
436             if( !$flavor_ok ){
437                 //die( $mod_strings['ERROR_FLAVOR_INCOMPATIBLE'] . $sugar_flavor );
438             }
439         }
440     }
441
442     function getInstallType( $type_string ){
443         // detect file type
444         global $subdirs;
445         $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
446
447
448         foreach( $subdirs as $subdir ){
449             if( preg_match( "#/$subdir/#", $type_string ) ){
450                 return( $subdir );
451             }
452         }
453         // return empty if no match
454         return( "" );
455     }
456
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']);
479                 }
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']);
485                 }
486             }
487
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";
493
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'] );
498             }
499
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>';
504             }else{
505                 if($display_messages)
506                         $messages = '<script>ajaxStatus.flashStatus("' .$mod_strings['ERR_UW_UPLOAD_ERROR'] . ', 5000");</script>';
507             }
508         }//fi
509         else{
510             $this->unlinkTempFiles();
511             if($display_messages)
512                 die($mod_strings['ERR_UW_NO_MANIFEST']);
513         }
514         if(isset($messages))
515             return $messages;
516     }
517
518     function unlinkTempFiles() {
519         global $sugar_config;
520         @unlink($_FILES['upgrade_zip']['tmp_name']);
521         @unlink("upload://".$_FILES['upgrade_zip']['name']);
522     }
523
524     function performInstall($file, $silent=true){
525         global $sugar_config;
526         global $mod_strings;
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);
532         }
533
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'];
557
558             if(!empty($previous_version)){
559                 $mi->install($unzip_dir, true, $previous_version);
560             }else{
561                 $mi->install($unzip_dir);
562             }
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();
581                     //unlink($file);
582         }//fi
583     }
584
585     function performUninstall($name){
586         $uh = new UpgradeHistory();
587         $uh->name = $name;
588         $uh->id_name = $name;
589         $found = $uh->checkForExisting($uh);
590         if($found != null){
591                 global $sugar_config;
592                 global $mod_strings;
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();
601                 $mi->silent = true;
602                 $mi->uninstall( "$unzip_dir");
603                 $found->delete();
604                 unlink(remove_file_extension( $found->filename ) . '-manifest.php');
605                 unlink($found->filename);
606             }else{
607                 //file(s_ have been deleted or are not found in the directory, allow database delete to happen but no need to change filesystem
608                 $found->delete();
609             }
610         }
611     }
612
613     function getUITextForType( $type ){
614         if( $type == "full" ){
615             return( "Full Upgrade" );
616         }
617         if( $type == "langpack" ){
618             return( "Language Pack" );
619         }
620         if( $type == "module" ){
621             return( "Module" );
622         }
623         if( $type == "patch" ){
624             return( "Patch" );
625         }
626         if( $type == "theme" ){
627             return( "Theme" );
628         }
629     }
630
631     function getImageForType( $type ){
632
633         $icon = "";
634         switch( $type ){
635             case "full":
636                 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "" ,null,null,'.gif', "Upgrade");
637
638                 break;
639             case "langpack":
640                 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "",null,null,'.gif',"Language Packs" );
641
642                 break;
643             case "module":
644                 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "" ,null,null,'.gif', "Module Loader");
645
646                 break;
647             case "patch":
648                 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "",null,null,'.gif', "Patch Upgrades" );
649
650                 break;
651             case "theme":
652                 $icon = SugarThemeRegistry::current()->getImage("Themes", "",null,null,'.gif', "Themes" );
653
654                 break;
655             default:
656                 break;
657         }
658         return( $icon );
659     }
660
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;
674                 }
675         }
676
677         $upgrades_available = 0;
678         $packages = array();
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))) {
682                 continue;
683             }
684
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))
690             {
691                 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
692                 if(file_exists($target_manifest)) {
693                         require_once($target_manifest);
694
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'];
698                         $icon = '';
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'];
706                                         }
707                 }
708
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)."]";
715                                         }
716                                 }
717
718                 if($view == 'default' && $manifest_type != 'patch') {
719                     continue;
720                 }
721
722                 if($view == 'module'
723                     && $manifest_type != 'module' && $manifest_type != 'theme' && $manifest_type != 'langpack') {
724                     continue;
725                 }
726
727                 if(empty($manifest['icon'])) {
728                     $icon = $this->getImageForType( $manifest['type'] );
729                 } else {
730                     $path_parts = pathinfo( $manifest['icon'] );
731                     $icon = "<img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
732                 }
733
734                 $upgrades_available++;
735
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));
739             }//fi
740         }//rof
741         return $packages;
742     }
743
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);
751             return $contents;
752         }else{
753             return null;
754         }
755     }
756
757     /**
758      * Run the query to obtain the list of installed types as specified by the type param
759      *
760      * @param type      an array of types you would like to search for
761      *                          type options include (theme, langpack, module, patch)
762      *
763      * @return an array of installed upgrade_history objects
764      */
765     function getInstalled($types = array('module')){
766         $uh = new UpgradeHistory();
767         $in = "";
768         for($i = 0; $i < count($types); $i++){
769                 $in .= "'".$types[$i]."'";
770                 if(($i+1) < count($types)){
771                         $in .= ",";
772                 }
773         }
774         $query = "SELECT * FROM ".$uh->table_name."      WHERE type IN (".$in.")";
775         return $uh->getList($query);
776     }
777
778     function getinstalledPackages($types = array('module', 'langpack')){
779         global $sugar_config;
780         $installeds = $this->getInstalled($types);
781         $packages = array();
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)
787                 {
788                         $populate = false;
789                         $filename = from_html($installed->filename);
790                         $date_entered = $installed->date_entered;
791                         $type = $installed->type;
792                         $version = $installed->version;
793                         $uninstallable = false;
794                         $link = "";
795                         $description = $installed->description;
796                         $name = $installed->name;
797                         $enabled = true;
798                         $enabled_string = 'ENABLED';
799                         //if the name is empty then we should try to pull from manifest and populate upgrade_history_table
800                         if(empty($name)){
801                                 $populate = true;
802                         }
803                         $upgrades_installed++;
804                         switch($type)
805                         {
806                                 case "theme":
807                                 case "langpack":
808                                 case "module":
809                                 case "patch":
810                                         if($populate){
811                                                 $manifest_file = $this->extractManifest($filename, $base_tmp_upgrade_dir);
812                                                 require_once($manifest_file);
813                                                 $GLOBALS['log']->info("Filling in upgrade_history table");
814                                                 $populate = false;
815                                                 if( isset( $manifest['name'] ) ){
816                                                 $name = $manifest['name'];
817                                                 $installed->name = $name;
818                                                 }
819                                                 if( isset( $manifest['description'] ) ){
820                                                     $description = $manifest['description'];
821                                                     $installed->description = $description;
822                                                 }
823                                                 if(isset($installdefs) && isset( $installdefs['id'] ) ){
824                                                     $id_name  = $installdefs['id'];
825                                                     $installed->id_name = $id_name;
826                                                 }
827
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));
833                                                 $installed->save();
834                                         }else{
835                                                 $serial_manifest = unserialize(base64_decode($installed->manifest));
836                                                 $manifest = $serial_manifest['manifest'];
837                                         }
838                                         if(($upgrades_installed==0 || $uh->UninstallAvailable($installeds, $installed))
839                                                 && is_file($filename) && !empty($manifest['is_uninstallable']))
840                                         {
841                                                 $uninstallable = true;
842                                         }
843                                         $enabled = $installed->enabled;
844                                         if(!$enabled)
845                                                 $enabled_string = 'DISABLED';
846                                         $file_uninstall = $filename;
847                                         if(!$uninstallable){
848                                                 $file_uninstall = 'UNINSTALLABLE';
849                                                 $enabled_string = 'UNINSTALLABLE';
850                                         } else {
851                                                 $file_uninstall = fileToHash( $file_uninstall );
852                                         }
853
854                                 $packages[] = array(
855                                     'name' => $name,
856                                     'version' => $version,
857                                     'type' => $type,
858                                     'published_date' => $date_entered,
859                                     'description' => $description,
860                                     'uninstallable' =>$uninstallable,
861                                     'file_install' =>  $file_uninstall ,
862                                     'file' =>  fileToHash($filename),
863                                     'enabled' => $enabled_string
864                                 );
865                                 break;
866                                 default:
867                                 break;
868                         }
869
870                 }//rof
871                 return $packages;
872     }
873  }
874 ?>