]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - ModuleInstall/PackageManager/PackageManager.php
Release 6.2.0
[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-2011 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
43
44
45
46 require_once('include/nusoap/nusoap.php');
47
48 require_once('include/utils/zip_utils.php');
49
50 require_once('ModuleInstall/PackageManager/PackageManagerDisplay.php');
51 require_once('ModuleInstall/ModuleInstaller.php');
52
53 require_once('include/entryPoint.php');
54 require_once('ModuleInstall/PackageManager/PackageManagerComm.php');
55
56
57  class PackageManager{
58     var $soap_client;
59
60     /**
61      * Constructor: In this method we will initialize the nusoap client to point to the hearbeat server
62      */
63     function PackageManager(){
64         $this->db = & DBManagerFactory::getInstance();
65     }
66
67     function initializeComm(){
68
69     }
70
71     /**
72      * Obtain a promotion from SugarDepot
73      * @return string   the string from the promotion
74      */
75     function getPromotion(){
76         $name_value_list = PackageManagerComm::getPromotion();
77         if(!empty($name_value_list)){
78             $name_value_list = PackageManager::fromNameValueList($name_value_list);
79             return $name_value_list['description'];
80         }else {
81            return '';
82         }
83     }
84
85     /**
86      * Obtain a list of category/packages/releases for use within the module loader
87      */
88     function getModuleLoaderCategoryPackages($category_id = ''){
89         $filter = array();
90         $filter = array('type' => "'module', 'theme', 'langpack'");
91         $filter = PackageManager::toNameValueList($filter);
92         return PackageManager::getCategoryPackages($category_id, $filter);
93     }
94
95     /**
96      * Obtain the list of category_packages from SugarDepot
97      * @return category_packages
98      */
99     function getCategoryPackages($category_id = '', $filter = array()){
100          $results = PackageManagerComm::getCategoryPackages($category_id, $filter);
101          PackageManagerComm::errorCheck();
102          $nodes = array();
103
104         $nodes[$category_id]['packages'] = array();
105         if(!empty($results['categories'])){
106                  foreach($results['categories'] as $category){
107                     $mycat = PackageManager::fromNameValueList($category);
108                     $nodes[$mycat['id']] = array('id' => $mycat['id'], 'label' => $mycat['name'], 'description' => $mycat['description'], 'type' => 'cat', 'parent' => $mycat['parent_id']);
109                     $nodes[$mycat['id']]['packages'] = array();
110                  }
111         }
112          if(!empty($results['packages'])){
113                 $uh = new UpgradeHistory();
114                  foreach($results['packages'] as $package){
115                     $mypack = PackageManager::fromNameValueList($package);
116                     $nodes[$mypack['category_id']]['packages'][$mypack['id']] = array('id' => $mypack['id'], 'label' => $mypack['name'], 'description' => $mypack['description'], 'category_id' => $mypack['category_id'], 'type' => 'package');
117                     $releases = PackageManager::getReleases($category_id, $mypack['id'], $filter);
118                     $arr_releases = array();
119                     $nodes[$mypack['category_id']]['packages'][$mypack['id']]['releases'] = array();
120                     if(!empty($releases['packages'])){
121                             foreach($releases['packages'] as $release){
122                                  $myrelease = PackageManager::fromNameValueList($release);
123                                  //check to see if we already this one installed
124                                  $result = $uh->determineIfUpgrade($myrelease['id_name'], $myrelease['version']);
125                                  $enable = false;
126                                  if($result == true || is_array($result))
127                                          $enable = true;
128                                  $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);
129                                 }
130                     }
131                     //array_push($nodes[$mypack['category_id']]['packages'], $package_arr);
132                  }
133          }
134          $GLOBALS['log']->debug("NODES". var_export($nodes, true));
135         return $nodes;
136     }
137
138     /**
139      * Get a list of categories from the SugarDepot
140      * @param category_id   the category id of parent to obtain
141      * @param filter        an array of filters to pass to limit the query
142      * @return array        an array of categories for display on the client
143      */
144     function getCategories($category_id, $filter = array()){
145         $nodes = array();
146         $results = PackageManagerComm::getCategories($category_id, $filter);
147         PackageManagerComm::errorCheck();
148         if(!empty($results['categories'])){
149                 foreach($results['categories'] as $category){
150                     $mycat = PackageManager::fromNameValueList($category);
151                     $nodes[] = array('id' => $mycat['id'], 'label' => $mycat['name'], 'description' => $mycat['description'], 'type' => 'cat', 'parent' => $mycat['parent_id']);
152                 }
153         }
154         return $nodes;
155     }
156
157     function getPackages($category_id, $filter = array()){
158         $nodes = array();
159         $results = PackageManagerComm::getPackages($category_id, $filter);
160         PackageManagerComm::errorCheck();
161         $packages = array();
162         //$xml = '';
163         //$xml .= '<packages>';
164         if(!empty($results['packages'])){
165                 foreach($results['packages'] as $package){
166                     $mypack = PackageManager::fromNameValueList($package);
167                     $packages[$mypack['id']] = array('package_id' => $mypack['id'], 'name' => $mypack['name'], 'description' => $mypack['description'], 'category_id' => $mypack['category_id']);
168                     $releases = PackageManager::getReleases($category_id, $mypack['id']);
169                     $arr_releases = array();
170                     foreach($releases['packages'] as $release){
171                          $myrelease = PackageManager::fromNameValueList($release);
172                          $arr_releases[$myrelease['id']]  = array('release_id' => $myrelease['id'], 'version' => $myrelease['version'], 'description' => $myrelease['description'], 'category_id' => $mypack['category_id'], 'package_id' => $mypack['id']);
173                     }
174                     $packages[$mypack['id']]['releases'] = $arr_releases;
175                 }
176         }
177         return $packages;
178     }
179
180     function getReleases($category_id, $package_id, $filter = array()){
181         $releases = PackageManagerComm::getReleases($category_id, $package_id, $filter);
182         PackageManagerComm::errorCheck();
183         return $releases;
184     }
185
186     /**
187      * Retrieve the package as specified by the $id from the heartbeat server
188      *
189      * @param category_id   the category_id to which the release belongs
190      * @param package_id    the package_id to which the release belongs
191      * @param release_id    the release_id to download
192      * @return filename - the path to which the zip file was saved
193      */
194     function download($category_id, $package_id, $release_id, $save_dir = ''){
195         $GLOBALS['log']->debug('RELEASE _ID: '.$release_id);
196         if(!empty($release_id)){
197             $filename = PackageManagerComm::addDownload($category_id, $package_id, $release_id);
198             if($filename){
199                     $GLOBALS['log']->debug('RESULT: '.$filename);
200                     PackageManagerComm::errorCheck();
201                         $filepath = PackageManagerComm::performDownload($filename, $save_dir);
202                         return $filepath;
203                     /*if(!empty($result) && !empty($result['filename']) && !empty($save_dir)){
204                         $GLOBALS['log']->debug('Saving Package to: '.$save_dir);
205                         $GLOBALS['log']->debug('Saving package to the local file system:'.$result['filename']);
206                         return write_encoded_file ($result, $save_dir);
207                     }else{
208                         return null;
209                     }*/
210             }
211         }else{
212             return null;
213         }
214     }
215
216     /**
217      * Given the Mambo username, password, and download key attempt to authenticate, if
218      * successful then store these credentials
219      *
220      * @param username      Mambo username
221      * @param password      Mambo password
222      * @param systemname   the user's download key
223      * @return              true if successful, false otherwise
224      */
225     function authenticate($username, $password, $systemname='', $terms_checked = true){
226         PackageManager::setCredentials($username, $password, $systemname);
227         PackageManagerComm::clearSession();
228         $result = PackageManagerComm::login($terms_checked);
229         if(is_array($result))
230                 return $result;
231         else
232                 return true;
233     }
234
235     function setCredentials($username, $password, $systemname){
236
237         $admin = new Administration();
238         $admin->retrieveSettings();
239          $admin->saveSetting(CREDENTIAL_CATEGORY, CREDENTIAL_USERNAME, $username);
240          $admin->saveSetting(CREDENTIAL_CATEGORY, CREDENTIAL_PASSWORD, $password);
241          if(!empty($systemname)){
242                 $admin->saveSetting('system', 'name', $systemname);
243          }
244     }
245
246     function getCredentials(){
247
248         $admin = new Administration();
249         $admin->retrieveSettings(CREDENTIAL_CATEGORY, true);
250         $credentials = array();
251         $credentials['username'] = '';
252         $credentials['password'] = '';
253                 $credentials['system_name'] = '';
254         if(!empty($admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_USERNAME])){
255            $credentials['username'] = $admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_USERNAME];
256         }
257         if(!empty($admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_USERNAME])){
258            $credentials['password'] = $admin->settings[CREDENTIAL_CATEGORY.'_'.CREDENTIAL_PASSWORD];
259         }
260         if(!empty($admin->settings['system_name'])){
261            $credentials['system_name'] = $admin->settings['system_name'];
262         }
263         return $credentials;
264     }
265
266     function getTermsAndConditions(){
267         return PackageManagerComm::getTermsAndConditions();
268
269     }
270
271     /**
272      * Retrieve documentation for the given release or package
273      *
274      * @param package_id        the specified package to retrieve documentation
275      * @param release_id        the specified release to retrieve documentation
276      *
277      * @return documents
278      */
279     function getDocumentation($package_id, $release_id){
280          if(!empty($release_id) || !empty($package_id)){
281             $documents = PackageManagerComm::getDocumentation($package_id, $release_id);
282             return $documents;
283         }else{
284             return null;
285         }
286     }
287
288     /**
289      * Grab the list of installed modules and send that list to the depot.
290      * The depot will then send back a list of modules that need to be updated
291      */
292     function checkForUpdates(){
293         $lists = $this->buildInstalledReleases(array('module'), true);
294                 $updates = array();
295                 if(!empty($lists)){
296                         $updates = PackageManagerComm::checkForUpdates($lists);
297                 }//fi
298                 return $updates;
299     }
300
301      ////////////////////////////////////////////////////////
302      /////////// HELPER FUNCTIONS
303     function toNameValueList($array){
304                 $list = array();
305                 foreach($array as $name=>$value){
306                         $list[] = array('name'=>$name, 'value'=>$value);
307                 }
308                 return $list;
309         }
310
311         function toNameValueLists($arrays){
312                 $lists = array();
313                 foreach($arrays as $array){
314                         $lists[] = PackageManager::toNameValueList($array);
315                 }
316                 return $lists;
317         }
318
319      function fromNameValueList($nvl){
320         $array = array();
321         foreach($nvl as $list){
322             $array[$list['name']] = $list['value'];
323         }
324         return $array;
325     }
326
327     function buildInstalledReleases($types = array('module')){
328         //1) get list of installed modules
329                 $installeds = $this->getInstalled($types);
330                 $releases = array();
331                 foreach($installeds as $installed){
332                         $releases[] = array('name' => $installed->name, 'id_name' => $installed->id_name, 'version' => $installed->version, 'filename' => $installed->filename, 'type' => $installed->type);
333                 }
334
335                 $lists = array();
336                 $name_value_list = array();
337                 if(!empty($releases)){
338                         $lists = $this->toNameValueLists($releases);
339                 }//fi
340                 return $lists;
341     }
342
343     function buildPackageXML($package, $releases = array()){
344         $xml = '<package>';
345         $xml .= '<package_id>'.$package['id'].'</package_id>';
346         $xml .= '<name>'.$package['name'].'</name>';
347         $xml .= '<description>'.$package['description'].'</description>';
348         if(!empty($releases)){
349              $xml .= '<releases>';
350              foreach($releases['packages'] as $release){
351
352                  $myrelease = PackageManager::fromNameValueList($release);
353                  $xml .= '<release>';
354                  $xml .= '<release_id>'.$myrelease['id'].'</release_id>';
355                  $xml .= '<version>'.$myrelease['version'].'</version>';
356                  $xml .= '<description>'.$myrelease['description'].'</description>';
357                  $xml .= '<package_id>'.$package['id'].'</package_id>';
358                  $xml .= '<category_id>'.$package['category_id'].'</category_id>';
359                  $xml .= '</release>';
360              }
361              $xml .= '</releases>';
362         }
363         $xml .= '</package>';
364         return $xml;
365     }
366
367     //////////////////////////////////////////////////////////////////////
368     /////////// INSTALL SECTION
369     function extractFile( $zip_file, $file_in_zip, $base_tmp_upgrade_dir){
370         $my_zip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
371         unzip_file( $zip_file, $file_in_zip, $my_zip_dir );
372         return( "$my_zip_dir/$file_in_zip" );
373     }
374
375     function extractManifest( $zip_file,$base_tmp_upgrade_dir ) {
376         global $sugar_config;
377         $base_upgrade_dir       = $sugar_config['upload_dir'] . "/upgrades";
378         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
379         return( $this->extractFile( $zip_file, "manifest.php",$base_tmp_upgrade_dir ) );
380     }
381
382     function validate_manifest( $manifest ){
383     // takes a manifest.php manifest array and validates contents
384     global $subdirs;
385     global $sugar_version;
386     global $sugar_flavor;
387     global $mod_strings;
388
389     if( !isset($manifest['type']) ){
390         die($mod_strings['ERROR_MANIFEST_TYPE']);
391     }
392     $type = $manifest['type'];
393     $GLOBALS['log']->debug("Getting InstallType");
394     if( $this->getInstallType( "/$type/" ) == "" ){
395         $GLOBALS['log']->debug("Error with InstallType".$type);
396         die($mod_strings['ERROR_PACKAGE_TYPE']. ": '" . $type . "'." );
397     }
398     $GLOBALS['log']->debug("Passed with InstallType");
399     if( isset($manifest['acceptable_sugar_versions']) ){
400             $version_ok = false;
401             $matches_empty = true;
402             if( isset($manifest['acceptable_sugar_versions']['exact_matches']) ){
403                 $matches_empty = false;
404                 foreach( $manifest['acceptable_sugar_versions']['exact_matches'] as $match ){
405                     if( $match == $sugar_version ){
406                         $version_ok = true;
407                     }
408                 }
409             }
410             if( !$version_ok && isset($manifest['acceptable_sugar_versions']['regex_matches']) ){
411                 $matches_empty = false;
412                 foreach( $manifest['acceptable_sugar_versions']['regex_matches'] as $match ){
413                     if( preg_match( "/$match/", $sugar_version ) ){
414                         $version_ok = true;
415                     }
416                 }
417             }
418
419             if( !$matches_empty && !$version_ok ){
420                 die( $mod_strings['ERROR_VERSION_INCOMPATIBLE'] . $sugar_version );
421             }
422         }
423
424      if( isset($manifest['acceptable_sugar_flavors']) && sizeof($manifest['acceptable_sugar_flavors']) > 0 ){
425             $flavor_ok = false;
426             foreach( $manifest['acceptable_sugar_flavors'] as $match ){
427                 if( $match == $sugar_flavor ){
428                     $flavor_ok = true;
429                 }
430             }
431             if( !$flavor_ok ){
432                 //die( $mod_strings['ERROR_FLAVOR_INCOMPATIBLE'] . $sugar_flavor );
433             }
434         }
435     }
436
437     function getInstallType( $type_string ){
438         // detect file type
439         global $subdirs;
440         $subdirs = array('full', 'langpack', 'module', 'patch', 'theme', 'temp');
441
442
443         foreach( $subdirs as $subdir ){
444             if( preg_match( "#/$subdir/#", $type_string ) ){
445                 return( $subdir );
446             }
447         }
448         // return empty if no match
449         return( "" );
450     }
451
452     function performSetup($tempFile, $view = 'module', $display_messages = true){
453         global $sugar_config;
454         $base_filename = urldecode($tempFile);
455         $GLOBALS['log']->debug("BaseFileName: ".$base_filename);
456         $base_upgrade_dir       = $sugar_config['upload_dir'] . "/upgrades";
457         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
458         $manifest_file = $this->extractManifest( $base_filename,$base_tmp_upgrade_dir);
459          $GLOBALS['log']->debug("Manifest: ".$manifest_file);
460         if($view == 'module')
461             $license_file = $this->extractFile($base_filename, 'LICENSE.txt', $base_tmp_upgrade_dir);
462         if(is_file($manifest_file)){
463             $GLOBALS['log']->debug("VALIDATING MANIFEST". $manifest_file);
464             require_once( $manifest_file );
465             $this->validate_manifest($manifest );
466             $upgrade_zip_type = $manifest['type'];
467             $GLOBALS['log']->debug("VALIDATED MANIFEST");
468             // exclude the bad permutations
469             if( $view == "module" ){
470                 if ($upgrade_zip_type != "module" && $upgrade_zip_type != "theme" && $upgrade_zip_type != "langpack"){
471                     $this->unlinkTempFiles();
472                     if($display_messages)
473                         die($mod_strings['ERR_UW_NOT_ACCEPTIBLE_TYPE']);
474                 }
475             }elseif( $view == "default" ){
476                 if($upgrade_zip_type != "patch" ){
477                     $this->unlinkTempFiles();
478                     if($display_messages)
479                         die($mod_strings['ERR_UW_ONLY_PATCHES']);
480                 }
481             }
482
483             $base_filename = preg_replace( "#\\\\#", "/", $base_filename );
484             $base_filename = basename( $base_filename );
485             mkdir_recursive( "$base_upgrade_dir/$upgrade_zip_type" );
486             $target_path = "$base_upgrade_dir/$upgrade_zip_type/$base_filename";
487             $target_manifest = remove_file_extension( $target_path ) . "-manifest.php";
488
489             if( isset($manifest['icon']) && $manifest['icon'] != "" ){
490                 $icon_location = $this->extractFile( $tempFile ,$manifest['icon'], $base_tmp_upgrade_dir );
491                 $path_parts = pathinfo( $icon_location );
492                 copy( $icon_location, remove_file_extension( $target_path ) . "-icon." . $path_parts['extension'] );
493             }
494
495             if( copy( $tempFile , $target_path ) ){
496                 copy( $manifest_file, $target_manifest );
497                 if($display_messages)
498                     $messages = '<script>ajaxStatus.flashStatus("' .$base_filename.$mod_strings['LBL_UW_UPLOAD_SUCCESS'] . ', 5000");</script>';
499             }else{
500                 if($display_messages)
501                         $messages = '<script>ajaxStatus.flashStatus("' .$mod_strings['ERR_UW_UPLOAD_ERROR'] . ', 5000");</script>';
502             }
503         }//fi
504         else{
505             $this->unlinkTempFiles();
506             if($display_messages)
507                 die($mod_strings['ERR_UW_NO_MANIFEST']);
508         }
509         if(isset($messages))
510             return $messages;
511     }
512
513     function unlinkTempFiles() {
514         global $sugar_config;
515         @unlink($_FILES['upgrade_zip']['tmp_name']);
516         @unlink(getcwd().'/'.$sugar_config['upload_dir'].$_FILES['upgrade_zip']['name']);
517     }
518
519     function performInstall($file, $silent=true){
520         global $sugar_config;
521         global $mod_strings;
522         global $current_language;
523         $base_upgrade_dir       = $sugar_config['upload_dir'] . "/upgrades";
524         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
525         if(!file_exists($base_tmp_upgrade_dir)){
526             mkdir_recursive($base_tmp_upgrade_dir, true);
527         }
528
529         $GLOBALS['log']->debug("INSTALLING: ".$file);
530         $mi = new ModuleInstaller();
531         $mi->silent = $silent;
532         $mod_strings = return_module_language($current_language, "Administration");
533              $GLOBALS['log']->debug("ABOUT TO INSTALL: ".$file);
534         if(preg_match("#.*\.zip\$#", $file)) {
535              $GLOBALS['log']->debug("1: ".$file);
536             // handle manifest.php
537             $target_manifest = remove_file_extension( $file ) . '-manifest.php';
538             include($target_manifest);
539             $GLOBALS['log']->debug("2: ".$file);
540             $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
541             unzip($file, $unzip_dir );
542             $GLOBALS['log']->debug("3: ".$unzip_dir);
543             $id_name = $installdefs['id'];
544                         $version = $manifest['version'];
545                         $uh = new UpgradeHistory();
546                         $previous_install = array();
547                 if(!empty($id_name) & !empty($version))
548                         $previous_install = $uh->determineIfUpgrade($id_name, $version);
549                 $previous_version = (empty($previous_install['version'])) ? '' : $previous_install['version'];
550                 $previous_id = (empty($previous_install['id'])) ? '' : $previous_install['id'];
551
552             if(!empty($previous_version)){
553                 $mi->install($unzip_dir, true, $previous_version);
554             }else{
555                 $mi->install($unzip_dir);
556             }
557             $GLOBALS['log']->debug("INSTALLED: ".$file);
558             $new_upgrade = new UpgradeHistory();
559             $new_upgrade->filename      = $file;
560             $new_upgrade->md5sum        = md5_file($file);
561             $new_upgrade->type          = $manifest['type'];
562             $new_upgrade->version       = $manifest['version'];
563             $new_upgrade->status        = "installed";
564             //$new_upgrade->author        = $manifest['author'];
565             $new_upgrade->name          = $manifest['name'];
566             $new_upgrade->description   = $manifest['description'];
567             $new_upgrade->id_name               = $id_name;
568                         $serial_manifest = array();
569                         $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
570                         $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
571                         $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
572                         $new_upgrade->manifest          = base64_encode(serialize($serial_manifest));
573             //$new_upgrade->unique_key    = (isset($manifest['unique_key'])) ? $manifest['unique_key'] : '';
574             $new_upgrade->save();
575                     //unlink($file);
576         }//fi
577     }
578
579     function performUninstall($name){
580         $uh = new UpgradeHistory();
581         $uh->name = $name;
582         $uh->id_name = $name;
583         $found = $uh->checkForExisting($uh);
584         if($found != null){
585
586                 global $sugar_config;
587                 global $mod_strings;
588                 global $current_language;
589                 $base_upgrade_dir       = $sugar_config['upload_dir'] . "/upgrades";
590                 $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
591                 if(!isset($GLOBALS['mi_remove_tables']))$GLOBALS['mi_remove_tables'] = true;
592                 $unzip_dir = mk_temp_dir( $base_tmp_upgrade_dir );
593                 unzip($found->filename, $unzip_dir );
594                 $mi = new ModuleInstaller();
595                 $mi->silent = true;
596                 $mi->uninstall( "$unzip_dir");
597                 $found->delete();
598                 unlink(remove_file_extension( $found->filename ) . '-manifest.php');
599                 unlink($found->filename);
600         }
601     }
602
603     function getUITextForType( $type ){
604         if( $type == "full" ){
605             return( "Full Upgrade" );
606         }
607         if( $type == "langpack" ){
608             return( "Language Pack" );
609         }
610         if( $type == "module" ){
611             return( "Module" );
612         }
613         if( $type == "patch" ){
614             return( "Patch" );
615         }
616         if( $type == "theme" ){
617             return( "Theme" );
618         }
619     }
620
621     function getImageForType( $type ){
622
623         $icon = "";
624         switch( $type ){
625             case "full":
626                 $icon = SugarThemeRegistry::current()->getImage("Upgrade", "" );
627                 break;
628             case "langpack":
629                 $icon = SugarThemeRegistry::current()->getImage("LanguagePacks", "" );
630                 break;
631             case "module":
632                 $icon = SugarThemeRegistry::current()->getImage("ModuleLoader", "" );
633                 break;
634             case "patch":
635                 $icon = SugarThemeRegistry::current()->getImage("PatchUpgrades", "" );
636                 break;
637             case "theme":
638                 $icon = SugarThemeRegistry::current()->getImage("Themes", "" );
639                 break;
640             default:
641                 break;
642         }
643         return( $icon );
644     }
645
646     function getPackagesInStaging($view = 'module'){
647         global $sugar_config;
648         global $current_language;
649         $uh = new UpgradeHistory();
650         $base_upgrade_dir       = $sugar_config['upload_dir'] . "/upgrades";
651         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
652         $uContent = findAllFiles( "$base_upgrade_dir", array() , false, 'zip',$base_tmp_upgrade_dir);
653          //other variations of zip file i.e. ZIP, zIp,zIP,Zip,ZIp,ZiP
654         $extns = array( 'ZIP','ZIp','ZiP','Zip','zIP','zIp','ziP');
655         foreach($extns as $extn){
656                 $uContent = array_merge($uContent,findAllFiles( "$base_upgrade_dir", array() , false, $extn,$base_tmp_upgrade_dir));
657         }
658         $upgrade_contents = array();
659         $content_values = array_values($uContent);
660         $alreadyProcessed = array();
661         foreach($content_values as $val){
662                 if(empty($alreadyProcessed[$val])){
663                         $upgrade_contents[] = $val;
664                         $alreadyProcessed["$val"] = true;
665                 }
666         }
667
668         $upgrades_available = 0;
669         $packages = array();
670         $mod_strings = return_module_language($current_language, "Administration");
671         foreach($upgrade_contents as $upgrade_content)
672         {
673             if(!preg_match("#.*\.zip\$#", strtolower($upgrade_content)) || preg_match("#.*./zips/.*#", strtolower($upgrade_content)))
674             {
675                 continue;
676             }
677
678             $upgrade_content = clean_path($upgrade_content);
679             // Bug 22285 - fix for UNC paths
680             if ( substr($upgrade_content,0,2) == '\\\\' )
681                 $upgrade_content = '\\\\'.$upgrade_content;
682             $the_base = basename($upgrade_content);
683             $the_md5 = md5_file($upgrade_content);
684             $md5_matches = $uh->findByMd5($the_md5);
685                 $file_install = $upgrade_content;
686             if(0 == sizeof($md5_matches))
687             {
688                 $target_manifest = remove_file_extension( $upgrade_content ) . '-manifest.php';
689                 require_once($target_manifest);
690
691                 $name = empty($manifest['name']) ? $upgrade_content : $manifest['name'];
692                 $version = empty($manifest['version']) ? '' : $manifest['version'];
693                 $published_date = empty($manifest['published_date']) ? '' : $manifest['published_date'];
694                 $icon = '';
695                 $description = empty($manifest['description']) ? 'None' : $manifest['description'];
696                 $uninstallable = empty($manifest['is_uninstallable']) ? 'No' : 'Yes';
697                 $type = $this->getUITextForType( $manifest['type'] );
698                 $manifest_type = $manifest['type'];
699                 $dependencies = array();
700                 if( isset( $manifest['dependencies']) ){
701                                 $dependencies    = $manifest['dependencies'];
702                                 }
703
704                                 //check dependencies first
705                                 if(!empty($dependencies)){
706
707                                         $uh = new UpgradeHistory();
708                                         $not_found = $uh->checkDependencies($dependencies);
709                                         if(!empty($not_found) && count($not_found) > 0){
710                                                         $file_install = 'errors_'.$mod_strings['ERR_UW_NO_DEPENDENCY']."[".implode(',', $not_found)."]";
711                                         }//fi
712                                 }
713
714                 if($view == 'default' && $manifest_type != 'patch')
715                 {
716                     continue;
717                 }
718
719                 if($view == 'module'
720                     && $manifest_type != 'module' && $manifest_type != 'theme' && $manifest_type != 'langpack')
721                 {
722                     continue;
723                 }
724
725                 if(empty($manifest['icon'])){
726                     $icon = $this->getImageForType( $manifest['type'] );
727                 }else{
728                     $path_parts = pathinfo( $manifest['icon'] );
729                     $icon = "<img src=\"" . remove_file_extension( $upgrade_content ) . "-icon." . $path_parts['extension'] . "\">";
730                 }
731
732                 $upgrades_available++;
733
734                                 // uploaded file in cache/upload
735                         $fileS = explode('/', $upgrade_content);
736                         $c = count($fileS);
737                         $fileName = (isset($fileS[$c-1]) && !empty($fileS[$c-1])) ? $fileS[$c-1] : $fileS[$c-2];
738                         $upload_file = $sugar_config['upload_dir'].$fileName;
739
740                 $upgrade_content = urlencode($upgrade_content);
741                 $upload_content = urlencode($upload_file);
742                 $packages[] = array('name' => $name, 'version' => $version, 'published_date' => $published_date, 'description' => $description, 'uninstallable' =>$uninstallable, 'type' => $type, 'file_install' => fileToHash($file_install), 'file' => fileToHash($upgrade_content), 'upload_file' => $upload_content);
743             }//fi
744         }//rof
745         return $packages;
746     }
747
748     function getLicenseFromFile($file){
749         global $sugar_config;
750         $base_upgrade_dir       = $sugar_config['upload_dir'] . "/upgrades";
751         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
752         $license_file = $this->extractFile($file, 'LICENSE.txt', $base_tmp_upgrade_dir);
753         if(is_file($license_file)){
754             $contents = file_get_contents($license_file);
755             return $contents;
756         }else{
757             return null;
758         }
759     }
760
761     /**
762      * Run the query to obtain the list of installed types as specified by the type param
763      *
764      * @param type      an array of types you would like to search for
765      *                          type options include (theme, langpack, module, patch)
766      *
767      * @return an array of installed upgrade_history objects
768      */
769     function getInstalled($types = array('module')){
770         $uh = new UpgradeHistory();
771         $in = "";
772         for($i = 0; $i < count($types); $i++){
773                 $in .= "'".$types[$i]."'";
774                 if(($i+1) < count($types)){
775                         $in .= ",";
776                 }
777         }
778         $query = "SELECT * FROM ".$uh->table_name."      WHERE type IN (".$in.")";
779         return $uh->getList($query);
780     }
781
782     function getinstalledPackages($types = array('module', 'langpack')){
783         global $sugar_config;
784         $installeds = $this->getInstalled($types);
785         $packages = array();
786         $upgrades_installed = 0;
787         $uh = new UpgradeHistory();
788         $base_upgrade_dir       = $sugar_config['upload_dir'] . "/upgrades";
789         $base_tmp_upgrade_dir   = "$base_upgrade_dir/temp";
790         foreach($installeds as $installed)
791                 {
792                         $populate = false;
793                         $filename = from_html($installed->filename);
794                         $date_entered = $installed->date_entered;
795                         $type = $installed->type;
796                         $version = $installed->version;
797                         $uninstallable = false;
798                         $link = "";
799                         $description = $installed->description;
800                         $name = $installed->name;
801                         $enabled = true;
802                         $enabled_string = 'ENABLED';
803                         //if the name is empty then we should try to pull from manifest and populate upgrade_history_table
804                         if(empty($name)){
805                                 $populate = true;
806                         }
807                         $upgrades_installed++;
808                         switch($type)
809                         {
810                                 case "theme":
811                                 case "langpack":
812                                 case "module":
813                                 case "patch":
814                                         if($populate){
815                                                 $manifest_file = $this->extractManifest($filename, $base_tmp_upgrade_dir);
816                                                 require_once($manifest_file);
817                                                 $GLOBALS['log']->info("Filling in upgrade_history table");
818                                                 $populate = false;
819                                                 if( isset( $manifest['name'] ) ){
820                                                 $name = $manifest['name'];
821                                                 $installed->name = $name;
822                                                 }
823                                                 if( isset( $manifest['description'] ) ){
824                                                     $description = $manifest['description'];
825                                                     $installed->description = $description;
826                                                 }
827                                                 if(isset($installdefs) && isset( $installdefs['id'] ) ){
828                                                     $id_name  = $installdefs['id'];
829                                                     $installed->id_name = $id_name;
830                                                 }
831
832                                                 $serial_manifest = array();
833                                                 $serial_manifest['manifest'] = (isset($manifest) ? $manifest : '');
834                                                 $serial_manifest['installdefs'] = (isset($installdefs) ? $installdefs : '');
835                                                 $serial_manifest['upgrade_manifest'] = (isset($upgrade_manifest) ? $upgrade_manifest : '');
836                                                 $installed->manifest = base64_encode(serialize($serial_manifest));
837                                                 $installed->save();
838                                         }else{
839                                                 $serial_manifest = unserialize(base64_decode($installed->manifest));
840                                                 $manifest = $serial_manifest['manifest'];
841                                         }
842                                         if(($upgrades_installed==0 || $uh->UninstallAvailable($installeds, $installed))
843                                                 && is_file($filename) && !empty($manifest['is_uninstallable']))
844                                         {
845                                                 $uninstallable = true;
846                                         }
847                                         $enabled = $installed->enabled;
848                                         if(!$enabled)
849                                                 $enabled_string = 'DISABLED';
850                                         $file_uninstall = $filename;
851                                         if(!$uninstallable){
852                                                 $file_uninstall = 'UNINSTALLABLE';
853                                                 $enabled_string = 'UNINSTALLABLE';
854                                         } else {
855                                                 $file_uninstall = fileToHash( $file_uninstall );
856                                         }
857
858                                 $packages[] = array(
859                                     'name' => $name,
860                                     'version' => $version,
861                                     'type' => $type,
862                                     'published_date' => $date_entered,
863                                     'description' => $description,
864                                     'uninstallable' =>$uninstallable,
865                                     'file_install' =>  $file_uninstall ,
866                                     'file' =>  fileToHash($filename),
867                                     'enabled' => $enabled_string
868                                 );
869                                 break;
870                                 default:
871                                 break;
872                         }
873
874                 }//rof
875                 return $packages;
876     }
877  }
878 ?>