#!/usr/local/cpanel/3rdparty/bin/perl
# cpanel - scripts/installruby Copyright 2019 cPanel, L.L.C.
# All rights Reserved.
# copyright@cpanel.net http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
package scripts::installruby;
use strict;
use Cpanel::FindBin ();
use Cpanel::Logger ();
use Cpanel::Locale ();
use Cpanel::Patch ();
use Cpanel::RoR ();
use Cpanel::SafeFile ();
use Cpanel::SafeRun::Dynamic ();
use Cpanel::SysPkgs ();
use Cpanel::TempFile ();
use Cpanel::Update ();
use Cpanel::Version::Compare ();
use Cpanel::GenSysInfo ();
use Cpanel::LoadFile ();
use Cpanel::SafeRun::Simple ();
my $logger = Cpanel::Logger->new();
my %installsrc = (
'ruby' => '1.8.7',
'rubygems' => '1.3.7',
);
my %archive_types = (
'.tar.gz' => '-z',
'.tar.bz2' => '-j',
'.tgz' => '-z',
);
my $src_dir = '/usr/local/cpanel/src/3rdparty/ruby';
my $prefix = '/usr';
my $gem_bin = which_gem();
my $ruby_bin = which_ruby();
my $ruby_version_file = '/var/cpanel/version/ruby';
my $ruby_version;
exit( run(@ARGV) ) unless caller();
# update that version when new patches are available
sub cpanel_rubygemsversion { return $Cpanel::RoR::rails_version . '.cp5' }
sub run { ## no critic(ProhibitExcessComplexity)
my @args = @_;
my $msg = "This script is deprecated and will be removed in a future version. Please use the EasyApache 4 Ruby instead.";
$logger->deprecated($msg);
print STDERR "$msg\n";
sleep(5);
my $tf = Cpanel::TempFile->new();
$ENV{TMP} = $ENV{TMPDIR} = $ENV{TEMP} = $ENV{USERPROFILE} = $tf->dir() || die("Couldn't create temp dir"); # Case 67573: For 'tmpdir', which would default to /tmp if nothing better were found.
# Allow disabling of ruby
Cpanel::Update::init_UP_update('ruby');
my $force = @args && grep( /^--force$/, @args ) ? 1 : 0;
my $just_rails = @args && grep( /^--just-rails$/, @args ) ? 1 : 0;
my $patch = @args && grep( /^--patch(-gems)?$/, @args ) ? 1 : 0;
my $ruby_only = check_system_version($just_rails);
if ($patch) {
_patch_gems( force => $force );
exit;
}
my $exit_code = system '/usr/local/cpanel/scripts/checkccompiler';
if ($exit_code) {
print "C compiler appears to be broken. Ruby cannot be installed until this is resolved!\n";
exit 1;
}
system('/usr/local/cpanel/scripts/installsqlite3') == 0 or $logger->die('Failed to install sqlite3');
if ( !$just_rails ) {
_install_ruby();
}
return 0 if $ruby_only;
$gem_bin = which_gem();
# should leave when gem cannot be find
unless ($gem_bin) {
$logger->warn("Unable to find a valid gem binary.");
exit(1);
}
# Checking if a rails version >= 3.0 exists and ask confirmation before removing it.
my $rails_bin = Cpanel::FindBin::findbin('rails');
if ( -x $rails_bin ) {
my $rails_version = Cpanel::SafeRun::Simple::saferun( $rails_bin, '--version' );
chomp($rails_version);
($rails_version) = ( split( ' ', $rails_version, 2 ) )[1];
if ( Cpanel::Version::Compare::compare( $rails_version, '>=', '3.0.0' ) ) {
my $warning_msg = "\n" . 'Rails 3 has been detected on your system. Rails 3 is not supported at this time.';
if ( -t STDIN ) {
print $warning_msg . ' Would you like to remove it and install a supported version of rails? ';
my $choice;
while ( !defined $choice ) {
$choice = <STDIN>;
chomp($choice);
if ( $choice =~ /^y(?:es)?$/i ) {
$choice = 1;
}
elsif ( $choice =~ /^n(?:o)?$/ ) {
$choice = 0;
}
else {
$choice = undef;
}
}
if ($choice) {
uninstallrails3();
}
else {
exit 1;
}
}
else {
print $warning_msg . ' Uninstalling rails 3.' . "\n";
uninstallrails3();
}
}
}
my @install = ( 'mongrel', 'sqlite3' );
my @sqlite3_args = (
'--with-sqlite3-include=/usr/local/include',
'--with-sqlite3-lib=/usr/local/lib'
);
print "\nInstalling sqlite3 gem...\n\n";
_install_gem( 'sqlite3', '-v=1.3.6' );
_install_rails();
if ( _hasperlexpect() ) {
if ( my $pid = fork() ) {
waitpid( $pid, 0 );
}
else {
local $SIG{'ALRM'} = sub { die "Timeout\n"; };
alarm( 20 * 60 );
my $exp = Expect->spawn(
$gem_bin, 'install', @install, '--',
@sqlite3_args
) or die "Cannot spawn gem installer: $!";
my $expect_pid = $exp->pid();
my $mongrel_number = 0;
my $fastthread_number = 0;
while ( waitpid( $expect_pid, 1 ) != -1 ) {
$exp->expect(
300,
[
'Select which gem',
sub { return Expect::exp_continue() }
],
[
qr/^\s*\d\.\smongrel\s.*/,
sub {
if ( $exp->match =~ /\(ruby\)/ ) {
if ( !$mongrel_number ) {
($mongrel_number) = $exp->match =~ /\s*(\d+)/;
}
}
else {
return Expect::exp_continue();
}
}
],
[
qr/^\s*\d\.\sfastthread\s.*/,
sub {
if ( $exp->match =~ /\(ruby\)/ ) {
if ( !$fastthread_number ) {
($fastthread_number) = $exp->match =~ /\s*(\d+)/;
}
}
else {
return Expect::exp_continue();
}
}
],
[
'>',
sub {
my $number = 0;
if ($mongrel_number) {
$number = $mongrel_number;
$mongrel_number = 0;
}
elsif ($fastthread_number) {
$number = $fastthread_number;
$fastthread_number = 0;
}
$exp->send( $number . "\r" );
}
],
[ 'timeout', sub { $exp->send("\r"); } ],
);
}
$exp->soft_close();
exit;
}
}
else {
foreach my $app (@install) {
_install_gem($app);
}
}
if ( !-e '/etc/init.d/ror' && !-e '/usr/local/etc/rc.d/ror.sh' ) {
system('/usr/local/cpanel/bin/ror_setup');
}
# Patching gems. We have to force this because otherwise our versions don't
# get used.
_patch_gems( force => 1 );
print "Ruby - & - Rails Installed\n";
system '/usr/local/cpanel/scripts/magicloader';
system '/usr/local/cpanel/bin/build_global_cache'; # make visible
return 0;
}
sub _hasperlexpect {
my $hasperlexpect = 0;
eval {
require IO::Tty;
require Expect;
$hasperlexpect = 1;
};
return $hasperlexpect;
}
sub _install_rails {
print "\nInstalling rails...\n\n";
my $rails_version = $Cpanel::RoR::rails_version;
my @rails = ( 'rails', '-v=' . $rails_version );
Cpanel::SafeRun::Dynamic::saferunnoerrordynamic( $gem_bin, 'install', @rails );
return;
}
sub _install_ruby {
my @install = qw/ruby ruby-devel rubygems ruby-libs ruby-irb rubygem-rake/;
my %exclude_options = (
'kernel' => 1,
'ruby' => 0,
'bind-chroot' => 1,
);
my $syspkgobj = Cpanel::SysPkgs->new( exclude_options => \%exclude_options );
if ( !$syspkgobj ) { die "Could not create SysPkgs object\n"; }
$syspkgobj->check();
# Ensure Ruby is both installed and unmodified. reinstall will not install
# it if it is missing.
$syspkgobj->install( 'pkglist' => \@install );
$syspkgobj->reinstall( 'pkglist' => \@install );
# Required for cPanel to display the gem installer.
system '/usr/local/cpanel/bin/build_global_cache';
return;
}
sub check_system_version {
my ($just_rails) = @_;
if ( Cpanel::GenSysInfo::get_rpm_distro_version() != 6 ) {
my $lh = Cpanel::Locale->get_handle();
print "\n";
if ($just_rails) {
print $lh->maketext('[output,strong,Error]: This script can only install Rails on [asis,Red Hat 6], [asis,CentOS 6], and [asis,CloudLinux 6].'), "\n\n";
}
else {
print $lh->maketext('[output,strong,Note]: This script can only install Rails on [asis,Red Hat 6], [asis,CentOS 6], and [asis,CloudLinux 6].'), "\n";
print $lh->maketext('Only Ruby will be installed.');
print "\n\n";
}
exit 1 if $just_rails;
return 1;
}
return 0;
}
sub ask_question {
my ($question) = @_;
# cannot ask the question without STDIN being available
return 2 unless -t STDIN;
my $ask = $question . " Yes/No: ";
print $ask;
while (1) {
my $choice = <STDIN>;
chomp($choice);
return 1 if ( $choice =~ /^y(?:es)?$/i );
return 0 if ( $choice =~ /^n(?:o)?$/ );
$choice = undef;
print "Cannot understand your answer, you should answer by 'yes' or 'no'.\n";
print $ask;
}
# never reached
return;
}
sub which_gem {
return _which_bin('gem');
}
sub which_ruby {
return _which_bin('ruby');
}
sub _which_bin {
my $name = shift or return;
for my $d (qw{/usr/local/bin /usr/bin}) {
my $bin = $d . '/' . $name;
return $bin if -x $bin;
}
$logger->warn("Unable to locate $name binary.");
return;
}
sub gem_version {
my $bin = shift || which_gem();
return unless $bin && -x $bin;
my $version = `$bin -v`;
return unless $version;
chomp $version;
return $version;
}
sub _version_file {
return '/var/cpanel/version/cpgrubygems';
}
sub _check_patch_version {
my $current = Cpanel::LoadFile::loadfile( _version_file() ) || 0;
$current =~ s/\s+//g;
return $current ne cpanel_rubygemsversion();
}
sub _patch_gems {
my (%opts) = @_;
$opts{force} ||= 0;
my $logger = Cpanel::Logger->new();
# check that gem exists
my $gem_bin = which_gem();
unless ($gem_bin) {
$logger->warn("Cannot find gem binary.");
return;
}
my $gems_src = '/usr/local/cpanel/src/3rdparty/ruby/gems';
# cpanel_version
if ( !$opts{force} && !_check_patch_version() ) {
$logger->info("Gems are already up-to-date with latest patches.");
return;
}
my $rails_version = $Cpanel::RoR::rails_version;
my @gems_to_patch = (
{
name => 'mongrel',
version => '1.1.5',
},
{
name => 'rack',
version => '1.1.6',
uninstall => '<1.1.6',
},
);
foreach my $gem (@gems_to_patch) {
my $name = ucfirst( $gem->{name} ) . " v" . $gem->{version};
$logger->info("Gem $name");
# check if the gem is installed
unless ( system( $gem_bin, 'list', $gem->{name}, '-i', '-v', '=' . $gem->{version} ) == 0 ) {
$logger->warn( $name . " is not installed." );
next unless $gem->{uninstall};
}
# uninstall the unpatched gem and more if specified
if ( $gem->{uninstall} ) {
_uninstall_gem( $gem->{name}, '-a', '-v' => $gem->{uninstall} );
}
chdir $gems_src or $logger->die( 'Unable to chdir: ' . $! );
my $src = $gem->{name} . '-' . $gem->{version};
my $gemfile = $src . '.gem';
my $patch = $gems_src . '/../patch/gems/' . $src;
unless ( -e $gemfile && -d $patch ) {
$logger->warn( "Cannot patch " . $name . " ( gem or patch are missing )" );
next;
}
# clean previous installation
system( 'rm', '-rf', $src ) if ( -e $src );
my @cmds;
push @cmds, [ $gem_bin, 'unpack', $gemfile ];
foreach my $cmd (@cmds) {
system(@$cmd) == 0
or $logger->die( "Failed command: " . join( ' ', @$cmd ) );
}
# apply patch
if ( !Cpanel::Patch::apply_patchset( $patch, $src ) ) {
$logger->die("Failed to patch $name.");
}
# build and install gem
chdir($src) or $logger->die( 'Unable to chdir: ' . $! );
@cmds = ();
push @cmds, [ $gem_bin, 'build', "$gem->{name}.gemspec" ];
push @cmds, [ $gem_bin, 'install', $gemfile, '--local' ];
foreach my $cmd (@cmds) {
system(@$cmd) == 0
or $logger->die( "Failed command: " . join( ' ', @$cmd ) );
}
$logger->info("Successfully patched and installed $name.");
}
# update the lock file
my $lock = Cpanel::SafeFile::safeopen( \*VERSION, ">", _version_file() )
|| do {
$logger->die( "Cannot open " . _version_file() . " " . $! );
};
print VERSION cpanel_rubygemsversion();
Cpanel::SafeFile::safeclose( \*VERSION, $lock ) if $lock;
return;
}
sub _uninstall_gem {
my ( $gem, @opts ) = @_;
Cpanel::SafeRun::Dynamic::saferunnoerrordynamic( which_gem(), 'uninstall', '-I', '-x', @opts, $gem );
return;
}
sub _install_gem {
my ( $gem, @opts ) = @_;
my $gem_version = gem_version();
push @opts, '--no-ri', '--no-rdoc';
push @opts, '--include-dependencies' if ( $gem_version && Cpanel::Version::Compare::compare( $gem_version, '<', '2.0' ) );
Cpanel::SafeRun::Simple::saferun( which_gem(), 'install', $gem, @opts );
return;
}
sub uninstallrails3 {
for my $gem (qw(rails actionmailer activemodel actionpack activerecord activeresource activesupport railties)) {
_uninstall_gem( $gem, '-v' => '>=3.0.0' );
}
# remove patch version
unlink _version_file();
return;
}
Copyright 2K16 - 2K18 Indonesian Hacker Rulez