MOON
Server: Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/0.9.8e-fips-rhel5 mod_bwlimited/1.4
System: Linux csr818.wilogic.com 2.6.18-419.el5xen #1 SMP Fri Feb 24 22:50:37 UTC 2017 x86_64
User: digitals (531)
PHP: 5.4.45
Disabled: NONE
Upload Files
File: //proc/self/root/proc/self/root/scripts.20110531.215904.25158/cPanelRPM.pm
package cPanelRPM;

# cpanel - cPanelRPM.pm                           Copyright(c) 2010 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

use Socket;
use strict;
use Cpanel::HttpTimer;
use Cpanel::Config     ();
use Cpanel::StringFunc ();
use Cwd 'chdir';
use IPC::Open3;

my $hassigint = 0;
$SIG{'INT'} = sub {
    $hassigint = 1;
    print "SIGINT received.  Cleaning up and halting operations.\n\n";
};

my $noperl = 1;
my $virtuozzo = -e "/proc/vz/veinfo" ? 1 : 0;

my %CPCONF = Cpanel::Config::loadcpconf();

sub rpmbinversion {
    my ($self) = @_;
    my $rpmver = `$self->{"rpmbin"} --version`;
    chomp($rpmver);
    return ($rpmver);
}

sub new {
    my ( $distro, $version, $killcache, $rpmbin );
    ( undef, $distro, $version, $killcache, $rpmbin ) = @_;
    my $self = {};
    bless($self);

    my (@UPDATES);

    $self->{'usemirrors'} = 0;

    if ( $rpmbin eq "" ) { $rpmbin = 'rpm'; }
    $self->{'rpmbin'} = $rpmbin;

    print "Using RPM Backend: " . $self->rpmbinversion() . "\n";

    if ( $distro eq "" && $version eq "" ) {
        if ( -e "/etc/fedora-release" ) {
            $distro = 'fedora';
            ($version) = getversionfromfile('/etc/fedora-release');
        }
        elsif ( -e "/etc/trustix-release" ) {
            $distro = 'trustix';
            ($version) = getversionfromfile('/etc/trustix-release');
        }
        elsif ( -e "/etc/whitebox-release" ) {
            $distro = 'whitebox';
            ($version) = getversionfromfile('/etc/whitebox-release');
        }
        elsif ( -e "/etc/caos-release" ) {
            $distro = 'caos';
            ($version) = getversionfromfile('/etc/caos-release');
        }
        elsif ( -e "/etc/SuSE-release" ) {
            $distro = 'suse';
            ($version) = getversionfromfile('/etc/SuSE-release');
        }
        elsif ( -e "/etc/mandrake-release" ) {
            $distro = 'mandrake';
            ($version) = getversionfromfile('/etc/mandrake-release');
        }
        elsif ( -e "/etc/redhat-release" ) {
            $distro = 'redhat';
            ($version) = getversionfromfile('/etc/redhat-release');
        }
        else {
            die "Your distro is NOT SUPPORTED\n";
        }
    }

    my $priarch = `rpm -q glibc --qf "%{ARCH}"`;
    my $myarch;

    $self->{"priarch"} = $priarch;

    #   print "Arch is $priarch\n";
    if ( $priarch =~ /686/ ) {
        $myarch = '686';
    }
    elsif ( $priarch =~ /586/ ) { $myarch = '586' }
    else {
        $myarch = 'x86';
    }

    $self->{"myarch"} = $myarch;

    my ( $mday, $mon, $year );
    ( undef, undef, undef, $mday, $mon, $year, undef, undef, undef ) = localtime( time() );
    $year += 1900;
    $mon++;

    my ( $ymday, $ymon, $yyear );
    ( undef, undef, undef, $ymday, $ymon, $yyear, undef, undef, undef ) = localtime( time() - 86400 );
    $yyear += 1900;
    $ymon++;

    my ( $tymday, $tymon, $tyyear );
    ( undef, undef, undef, $tymday, $tymon, $tyyear, undef, undef, undef ) = localtime( time() - ( 86400 * 2 ) );
    $tyyear += 1900;
    $tymon++;

    $self->{"mday"} = $mday;
    $self->{"mon"}  = $mon;
    $self->{"year"} = $year;

    mkdir( "/root/.cpupdates", 0700 );
    if ( !-d "/root/.cpupdates" ) {
        die "could not create /root/.cpupdates";
    }

    my $roll = 0;
    my @STFS = ( "updates", "provides", "requires" );
    foreach my $stf (@STFS) {
        if (  !-e "/root/.cpupdates/$mon-$mday-$year.${stf}"
            && -e "/root/.cpupdates/$ymon-$ymday-$yyear.${stf}" ) {
            print "cprpmdb: ${stf} rolling from $ymon-$ymday-$yyear\n";
            rename( "/root/.cpupdates/$ymon-$ymday-$yyear.${stf}", "/root/.cpupdates/$mon-$mday-$year.${stf}" );
            $roll = 1;
        }
        if (  !-e "/root/.cpupdates/$mon-$mday-$year.${stf}"
            && -e "/root/.cpupdates/$tymon-$tymday-$tyyear.${stf}" ) {
            print "cprpmdb: ${stf} rolling from $tymon-$tymday-$tyyear\n";
            rename( "/root/.cpupdates/$tymon-$tymday-$tyyear.${stf}", "/root/.cpupdates/$mon-$mday-$year.${stf}" );
            $roll = 1;
        }
    }

    opendir( CPUP, "/root/.cpupdates" );
    my @FILES = readdir(CPUP);
    closedir(CPUP);
    foreach my $file (@FILES) {
        next if ( $file eq "rpmdb-provides.mtime" );
        next if ( $file eq "rpmdb-requires.mtime" );
        next if ( $file eq "mirrors.lst" );
        next if ( $file eq "pingtimes" );
        next if ( $file eq "mirrors.speeds" );
        next if ( $file =~ /^rpmup/ );
        next if ( $file =~ /^\./ );
        if ( $file !~ /^$mon-$mday-$year\./ || $killcache ) {

            #print ("Unlinking old cache file /root/.cpupdates/$file\n");
            unlink("/root/.cpupdates/$file");
        }

    }

    my ($badf) = 1;
    if ( -e "/root/.cpupdates/$mon-$mday-$year.updates" ) {
        open( CPUP, "/root/.cpupdates/$mon-$mday-$year.updates" );
        while (<CPUP>) {
            s/\n//g;
            push( @UPDATES, $_ );
        }
        close(CPUP);
        if ( $#UPDATES > 100 ) { $badf = 0; }
    }

    if (
        $distro eq "redhat"
        && (   -e "/usr/bin/wget"
            || -e "/usr/local/bin/wget"
            || -e "/usr/bin/ncftpget"
            || -e "/usr/local/bin/ncftpget" )
      ) {
        $self->{"usemirrors"} = 1;
    }

    if ( $roll || $badf || ( ( stat("/root/.cpupdates/$mon-$mday-$year.updates") )[9] + 50000 < time() ) ) {
        $#UPDATES = 0;
        print "Fetching rpm updates list...";
        if ( $distro eq "redhat" ) {
            httpreqI( 'updates.cpanel.net', "/pub/rpminstall/$distro-$version/updates.${myarch}.v2.db.gz", "/root/.cpupdates/$mon-$mday-$year.updates.gz" );
        }
        else {
            httpreqI( 'updates.cpanel.net', "/pub/rpminstall/$distro-$version/updates.${myarch}.db.gz", "/root/.cpupdates/$mon-$mday-$year.updates.gz" );
        }
        print "Done\n";
        if ( -e "/root/.cpupdates/$mon-$mday-$year.updates.gz" ) {
            system( "gzip", "-d", "-f", "/root/.cpupdates/$mon-$mday-$year.updates.gz" );
        }
        if ( !-e "/root/.cpupdates/$mon-$mday-$year.updates" ) {
            die "Cannot fetch rpm updates list";
        }

        open( CPUP, "/root/.cpupdates/$mon-$mday-$year.updates" );
        while (<CPUP>) {
            s/\n//g;
            push( @UPDATES, $_ );
        }
        close(CPUP);
    }

    if ( $roll || ( stat("/root/.cpupdates/$mon-$mday-$year.provides") )[7] < 4096 || ( ( stat("/root/.cpupdates/$mon-$mday-$year.provides") )[9] + 50000 < time() ) ) {
        my $compressprog = 'gzip';
        print "Fetching rpm provides list...";
        if ( -e "/bin/bzip2" || -e "/usr/bin/bzip2" ) {
            httpreqI( 'updates.cpanel.net', "/pub/rpminstall/$distro-$version/provides.${myarch}.db.bz2", "/root/.cpupdates/$mon-$mday-$year.provides.bz2" );
            if ( -e "/root/.cpupdates/$mon-$mday-$year.provides.bz2" ) {
                system( "bzip2", "-d", "-f", "/root/.cpupdates/$mon-$mday-$year.provides.bz2" );
            }
        }
        else {
            httpreqI( 'updates.cpanel.net', "/pub/rpminstall/$distro-$version/provides.${myarch}.db.gz", "/root/.cpupdates/$mon-$mday-$year.provides.gz" );
            if ( -e "/root/.cpupdates/$mon-$mday-$year.provides.gz" ) {
                system( "gzip", "-d", "-f", "/root/.cpupdates/$mon-$mday-$year.provides.gz" );
            }
        }
        print "Done\n";
        if ( !-e "/root/.cpupdates/$mon-$mday-$year.provides" ) {
            die "Cannot fetch rpm provides list";
        }
        open( CPUP,  "/root/.cpupdates/$mon-$mday-$year.provides" );
        open( CPUPI, ">/root/.cpupdates/$mon-$mday-$year.provides.index" );
        my $startchar = 0;
        while (<CPUP>) {
            if ( substr( $_, 0, 2 ) ne $startchar ) {
                $startchar = substr( $_, 0, 2 );
                my $filepos = ( tell(CPUP) - length($_) );
                print CPUPI "$startchar $filepos\n";
            }
            print CPUP $_ . "\n";
        }
        close(CPUP);
        close(CPUPI);
    }

    if ( $roll || ( stat("/root/.cpupdates/$mon-$mday-$year.requires") )[7] < 4096 || ( ( stat("/root/.cpupdates/$mon-$mday-$year.requires") )[9] + 50000 < time() ) ) {
        print "Fetching rpm requires list...";
        httpreqI( 'updates.cpanel.net', "/pub/rpminstall/$distro-$version/requires.${myarch}.db.gz", "/root/.cpupdates/$mon-$mday-$year.requires.gz" );
        print "Done\n";
        if ( -e "/root/.cpupdates/$mon-$mday-$year.requires.gz" ) {
            system( "gzip", "-d", "-f", "/root/.cpupdates/$mon-$mday-$year.requires.gz" );
        }
        if ( !-e "/root/.cpupdates/$mon-$mday-$year.requires" ) {
            die "Cannot fetch rpm requires list";
        }
        open( CPUP,  "/root/.cpupdates/$mon-$mday-$year.requires" );
        open( CPUPI, ">/root/.cpupdates/$mon-$mday-$year.requires.index" );
        my $startchar = 0;
        while (<CPUP>) {
            if ( substr( $_, 0, 2 ) ne $startchar ) {
                $startchar = substr( $_, 0, 2 );
                my $filepos = ( tell(CPUP) - length($_) );
                print CPUPI "$startchar $filepos\n";
            }
            print CPUP $_ . "\n";
        }
        close(CPUP);
        close(CPUPI);
    }

    $self->getlocalprovides();
    $self->getlocalrequires();

    my (%UPS);

    foreach (@UPDATES) {
        my ( $name, $rpmdata ) = split( /=/, $_, 2 );
        $UPS{$name} = $rpmdata;
    }

    my (%DEPS);

    $self->{"updates"}       = \%UPS;
    $self->{"deps"}          = \%DEPS;
    $self->{'dirtyrequires'} = 0;

    return ($self);
}

sub install {
    my ( $self, $pkg, $force, $nodeps, $tmpdir, $distup, $nomirrors, $safe, $quiet ) = @_;
    my (%UPS) = %{ $self->{"updates"} };
    my (%INSTALLED);
    my ( @RPMA, @INSPKGS );

    if ($nomirrors) { $self->{"usemirrors"} = 0; }

    if ( $self->{"dirtyrequires"} ) {
        $self->getlocalrequires();
        $self->{"dirtyrequires"} = 0;
    }

    my (@ULLIST);
    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    open( INSTALLED, "/root/.cpupdates/$mon-$mday-$year.installed" );
    while (<INSTALLED>) {
        s/\n//g;
        my ( $ipkg, $iversion ) = split( /\%/, $_ );
        $INSTALLED{$ipkg} = $iversion;

    }
    close(INSTALLED);

    if ( $UPS{$pkg} eq "" ) {
        if ( !$safe && !$quiet ) {
            print "unknown package $pkg (ok)\n";
        }
        delete @INSTALLED{ keys %INSTALLED };
        return ();
    }
    else {
        my ( $rpmv, $file, $rpmbuilddate, $downdir ) = split( /=/, $UPS{$pkg}, 5 );
        my $rpmversion = $rpmv;
        $rpmversion = substr( $rpmversion, length($pkg) + 1 );
        my $compareopt = cPanelRPM::compareversion( $rpmversion, $INSTALLED{$pkg} );
        if ( $compareopt >= 0 && !${force} ) {
            print "$pkg: installed version $INSTALLED{$pkg} is up to date, no action needed.\n";
            return ();
        }
    }
    $self->resolvedeps( $pkg, 0, 0 );
    my (%PKGS) = %{ $self->{"deps"} };
    foreach my $pkgs ( sort keys %PKGS ) {
        if ( $UPS{$pkgs} eq "" ) {
            next();
        }

        my ( $rpmv, $file, $rpmbuilddate, $downdir, $md5sum ) = split( /=/, $UPS{$pkgs}, 6 );
        my $rpmversion = $rpmv;
        $rpmversion = substr( $rpmversion, length($pkgs) + 1 );

        if ( ( $pkgs =~ /^kernel-/ || $pkgs =~ /^httpd-/ || $pkgs =~ /^k_/ || $pkgs =~ /^cyrus-imapd/ || ( $pkgs =~ /^quota/ && $virtuozzo ) || ( $noperl && $pkgs !~ /^perl-CPAN/ && $pkgs =~ /^perl/ ) ) && $pkgs !~ /^kernel-source/ && $pkgs !~ /^kernel-pcmcia/ ) {
            print "$pkgs will be ignored.\n";
        }
        else {
            if ( $force && $pkgs eq $pkg ) {
                print "$pkgs: install will be forced to $rpmversion.\n";
            }
            else {
                if ( $INSTALLED{$pkgs} eq $rpmversion ) {
                    print "$pkgs is current ($INSTALLED{$pkgs}), no action needed.\n";
                    next;
                }
                else {
                    if ( $INSTALLED{$pkgs} eq "" ) {
                        print "$pkgs: not installed.\n";
                    }
                    else {
                        my $compareopt = cPanelRPM::compareversion( $rpmversion, $INSTALLED{$pkgs}, $distup );
                        if ( $compareopt >= 0 ) {
                            print "$pkgs: installed version $INSTALLED{$pkgs} is current ($rpmversion), no action needed.\n";
                            next;
                        }
                        else {
                            print "$pkgs: current version is $INSTALLED{$pkgs}, will be updated to $rpmversion.\n";
                        }
                    }
                }
            }
        }

        if ( ( $pkgs =~ /^kernel-/ || $pkgs =~ /^httpd-/ || $pkgs =~ /^k_/ || $pkgs =~ /^cyrus-imapd/ || ( $pkgs =~ /^quota/ && $virtuozzo ) || ( $noperl && $pkgs !~ /^perl-CPAN/ && $pkgs =~ /^perl/ ) ) && $pkgs !~ /^kernel-source/ && $pkgs !~ /^kernel-pcmcia/ ) {
            push( @RPMA, "--nodeps" );
        }
        else {
            if ( $pkgs =~ /^iptables/ ) { push( @RPMA, "--nodeps" ); }
            if ( $self->{"usemirrors"} && $md5sum ne "" ) {
                if ( $self->fetchrpm( "${downdir}/${file}", $md5sum ) ) {
                    push( @RPMA,   "/var/spool/cpupdates/${file}" );
                    push( @ULLIST, "/var/spool/cpupdates/${file}" );
                }
                else {
                    push( @RPMA, "http://updates.cpanel.net" . ${downdir} . "/" . "${file}" );
                }
            }
            else {
                push( @RPMA, "http://updates.cpanel.net" . ${downdir} . "/" . "${file}" );
            }
        }
        push( @INSPKGS, $pkgs );
    }

    if ($hassigint) { die("Terminated at users request"); }

    if ( $#RPMA > -1 ) {
        if ($force)  { push( @RPMA, "--force" ); }
        if ($nodeps) { push( @RPMA, "--nodeps" ); }
        if ( $tmpdir ne "" ) {
            push( @RPMA, "--define", "_tmppath ${tmpdir}", "--define", "tmppath ${tmpdir}" );
        }
        system( "$self->{'rpmbin'}", "-Uvh", @RPMA );
        $self->getlocalprovidesupdate(@INSPKGS);
        $self->{'dirtyrequires'} = 1;
    }

    foreach my $ul (@ULLIST) {
        if ( $ul =~ /^\/var\/spool\/cpupdates\// && $ul !~ /\.\./ ) {
            unlink($ul);
        }
    }

    delete @INSTALLED{ keys %INSTALLED };
}

sub installedlist {
    my ($self) = @_;
    my (%INSTALLED);
    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};
    open( INSTALLED, "/root/.cpupdates/$mon-$mday-$year.installed" );
    while (<INSTALLED>) {
        s/\n//g;
        my ( $ipkg, $iversion ) = split( /\%/, $_ );
        $INSTALLED{$ipkg} = $iversion;

    }
    close(INSTALLED);
    return (%INSTALLED);
}

sub resolvedeps {
    my ( $self, $pkg, $level, $passthrough ) = @_;

    if ( $passthrough eq "" ) { $passthrough = 0; }

    #	print ">>> resolvedeps ($level) ($pkg)\n";

    if ($hassigint) { die("Terminated at users request"); }

    if ( $level eq "0" ) {
        delete @{ $self->{"deps"} }{ keys %{ $self->{"deps"} } };
    }

    my (%INSTALLREQ);

    my $usedep = 1;
    if ( ( $pkg =~ /^kernel-/ || $pkg =~ /^httpd-/ || $pkg =~ /^k_/ ) && $pkg !~ /^kernel-source/ && $pkg !~ /^kernel-pcmcia/ ) { $usedep = 0; }
    if ( $pkg eq "kernel" ) { $usedep = 0; }
    if ($usedep) {
        ${ $self->{"deps"} }{$pkg} = 2;
    }

    my (@PKGPROVIDES) = $self->getprovides($pkg);

    @PKGPROVIDES = $self->stripoutsameprovides( $pkg, \@PKGPROVIDES );
    my (@REQDEPPKGS);

    if ( $#PKGPROVIDES > -1 ) {
        @REQDEPPKGS = $self->getwhatrequires(@PKGPROVIDES);
    }

    foreach my $reqbydep (@REQDEPPKGS) {
        $reqbydep =~ s/-[\w\.]+-[\w\.]+(i.86|noarch)\.rpm$//g;
        next if ( $reqbydep eq $pkg );
        next if ( Cpanel::StringFunc::ibeginmatch( "$reqbydep", "MySQL-bench" ) );
        next if ( ${ $self->{"deps"} }{$reqbydep} >= 1 );
        print "Adding InterDependency ${reqbydep} (required by $pkg)\n";
        $self->resolvedeps( $reqbydep, ( $level + 1 ), 1 );
        foreach my $ndep ( sort keys %{ $self->{"deps"} } ) {
            if ( ( $ndep =~ /^kernel-/ || $ndep =~ /^k_/ || $ndep =~ /^httpd-/ ) && $ndep !~ /^kernel-source/ && $ndep !~ /^kernel-pcmcia/ ) { next; }
            if ( $ndep eq "kernel" ) { next; }
            if ( ${ $self->{"deps"} }{$ndep} == 1 ) {
                $self->resolvedeps( $ndep, ( $level + 1 ), 0 );
            }
        }
    }

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    my $pkgidx = substr( $pkg, 0, 2 );
    my $seekpoint;
    open( REQIDX, "/root/.cpupdates/$mon-$mday-$year.requires.index" );
    while (<REQIDX>) {
        if ( substr( $_, 0, length($pkgidx) + 1 ) eq $pkgidx . " " ) {
            /\s(\d+)$/;
            close(REQIDX);
            $seekpoint = $1;
            last;
        }
    }
    close(REQIDX);
    open( REQ, "/root/.cpupdates/$mon-$mday-$year.requires" );
    seek( REQ, $seekpoint, 0 );
    while (<REQ>) {
        if ( substr( $_, 0, length($pkg) + 1 ) eq $pkg . "%" ) {
            my ($requires);
            ( undef, $requires ) = split( /\%/, $_ );
            chomp($requires);
            my (@REQLIST) = split( /\,/, $requires );
            foreach my $req (@REQLIST) {
                my ( $item, $version );
                if ( $req =~ /\>\=/ ) {
                    ( $item, $version ) = split( /\>\=/, $req );
                    $item    =~ s/^\s*|\s*$//g;
                    $version =~ s/^\s*|\s*$//g;
                    $version = $version . "|>=";
                }
                elsif ( $req =~ /\<\=/ ) {
                    ( $item, $version ) = split( /\<\=/, $req );
                    $item    =~ s/^\s*|\s*$//g;
                    $version =~ s/^\s*|\s*$//g;
                    $version = $version . "|<=";
                }
                elsif ( $req =~ /\>/ ) {
                    ( $item, $version ) = split( /\>/, $req );
                    $item    =~ s/^\s*|\s*$//g;
                    $version =~ s/^\s*|\s*$//g;
                    $version = $version . "|>";
                }
                elsif ( $req =~ /\</ ) {
                    ( $item, $version ) = split( /\</, $req );
                    $item    =~ s/^\s*|\s*$//g;
                    $version =~ s/^\s*|\s*$//g;
                    $version = $version . "|<";
                }
                else {
                    ( $item, $version ) = split( /\=/, $req );
                    $item    =~ s/^\s*|\s*$//g;
                    $version =~ s/^\s*|\s*$//g;
                    $version = $version . "|=";
                }
                next if ( $item =~ /^rpmlib/ );
                next if ( $item =~ /^netcfg$/ );
                if ( $version eq "|=" )  { $version = "-1"; }
                if ( $version eq "|<" )  { $version = "-1"; }
                if ( $version eq "|>" )  { $version = "-1"; }
                if ( $version eq "|>=" ) { $version = "-1"; }
                if ( $version eq "|<=" ) { $version = "-1"; }

                my $installver    = $version;
                my $preinstallver = $INSTALLREQ{$item};
                if ( $installver =~ /:/ ) { ( undef, $installver ) = split( /:/, $installver ); }
                if ( $installver =~ /\|/ ) { ( $installver, undef ) = split( /\|/, $installver ); }
                if ( $preinstallver =~ /:/ ) { ( undef, $preinstallver ) = split( /:/, $preinstallver ); }
                if ( $preinstallver =~ /\|/ ) { ( $preinstallver, undef ) = split( /\|/, $preinstallver ); }
                if ( $INSTALLREQ{$item} eq "" || compareversion( $installver, $preinstallver ) >= 0 ) {
                    $INSTALLREQ{$item} = $version;
                }
            }
            close(REQ);
            last;
        }
    }
    close(REQ);

    my %SEEKPOINTS;
    open( LPROIDX, "/root/.cpupdates/$mon-$mday-$year.locprovides.index" );
    while (<LPROIDX>) {
        foreach my $item ( sort keys %INSTALLREQ ) {
            my $itemidx = substr( $item, 0, 2 );
            if ( substr( $_, 0, length($itemidx) + 1 ) eq $itemidx . " " ) {
                /\s(\d+)$/;
                $SEEKPOINTS{$item} = $1;
            }
        }
    }
    close(LPROIDX);
    open( LPRO, "/root/.cpupdates/$mon-$mday-$year.locprovides" );
    foreach my $item ( sort keys %INSTALLREQ ) {
        seek( LPRO, $SEEKPOINTS{$item}, 0 );
        while (<LPRO>) {
            if ( substr( $_, 0, length($item) + 1 ) eq $item . "%" ) {
                my ( $version, $ppkg );
                ( undef, $ppkg, $version ) = split( /\%/, $_, 3 );
                $ppkg =~ s/\n//g;

                if ( ( ${ $self->{"deps"} }{$ppkg} >= 1 ) && $item eq $ppkg ) { next; }    #installed version's cannot

                #satisify deps since they
                #will be removed when they are
                #upgraded
                if ( ( ${ $self->{"deps"} }{$ppkg} >= 1 ) && $pkg eq $ppkg ) { next; }     #installed version's cannot

                #satisify deps since they
                #will be removed when they are
                #upgraded

                my $sat = 0;
                if ( $INSTALLREQ{$item} =~ /\>/ || $INSTALLREQ{$item} =~ /\</ || $INSTALLREQ{$item} =~ /\=/ ) {
                    my $pkgv = ${version};
                    if ( $pkgv =~ /:/ ) { ( undef, $pkgv ) = split( /:/, $pkgv ); }

                    $pkgv =~ s/\n//g;

                    my ( $requiredver, $requiredop ) = split( /\|/, $INSTALLREQ{$item} );
                    if ( $requiredver =~ /:/ ) { ( undef, $requiredver ) = split( /:/, $requiredver ); }

                    my $compareopt = compareversion( $requiredver, $pkgv );
                    if ( $requiredop eq "=" && $compareopt == 0 ) {
                        delete $INSTALLREQ{$item};
                        $sat = 1;
                    }
                    if ( $requiredop eq ">" && $compareopt == 1 ) {
                        delete $INSTALLREQ{$item};
                        $sat = 1;
                    }
                    if ( $requiredop eq "<" && $compareopt == -1 ) {
                        delete $INSTALLREQ{$item};
                        $sat = 1;
                    }
                    if ( $requiredop eq ">=" && ( $compareopt == 1 || $compareopt == 0 ) ) {
                        delete $INSTALLREQ{$item};
                        $sat = 1;
                    }
                    if ( $requiredop eq "<=" && ( $compareopt == -1 || $compareopt == 0 ) ) {
                        delete $INSTALLREQ{$item};
                        $sat = 1;
                    }
                }
                else {
                    delete $INSTALLREQ{$item};
                    $sat = 1;
                }
                if ( !$sat ) { next; }
            }
        }
    }
    close(LPRO);
    delete @SEEKPOINTS{ keys %SEEKPOINTS };

    my %SEEKPOINTS;
    open( PROIDX, "/root/.cpupdates/$mon-$mday-$year.provides.index" );
    while (<PROIDX>) {
        foreach my $item ( sort keys %INSTALLREQ ) {
            my $itemidx = substr( $item, 0, 2 );
            if ( $SEEKPOINTS{$itemidx} eq "" && substr( $_, 0, length($itemidx) + 1 ) eq $itemidx . " " ) {
                /\s(\d+)$/;
                $SEEKPOINTS{$itemidx} = $1;
            }
        }
    }
    close(PROIDX);
    if ( tell(PRO) == -1 ) {
        open( PRO, "/root/.cpupdates/$mon-$mday-$year.provides" );
    }
    foreach my $item ( sort keys %INSTALLREQ ) {
        my %DEPLIST;
        my $itemidx = substr( $item, 0, 2 );
        seek( PRO, $SEEKPOINTS{$itemidx}, 0 );
        while (<PRO>) {
            my $founddep = 0;
            if ( substr( $_, 0, length($item) + 1 ) eq $item . "%" ) {
                $founddep = 1;
                s/\n//g;
                my ( $version, $ppkg );
                ( undef, $ppkg, $version ) = split( /\%/, $_, 3 );
                $DEPLIST{$ppkg} = $version;
                last;    #stop searching as we found something that provides it
            }
            elsif ( $founddep == 1 ) {
                last;
            }
        }

        #the new package provides the item we are looking for
        #basiclly it includes what it requires
        if ( $DEPLIST{$pkg} ne "" ) {
            delete $INSTALLREQ{$item};
        }
        else {

            #we might have a package that provide it so lets check and resolve the
            #deps for that pacakge
            foreach my $ppkg ( keys %DEPLIST ) {
                next if ( Cpanel::StringFunc::ibeginmatch( $ppkg, "MySQL-bench" ) );
                my $version = $DEPLIST{$ppkg};
                my $sat     = 0;

                if ( $INSTALLREQ{$item} =~ /\>/ || $INSTALLREQ{$item} =~ /\</ || $INSTALLREQ{$item} =~ /\=/ ) {
                    my $pkgv = ${version};
                    if ( $pkgv =~ /:/ ) { ( undef, $pkgv ) = split( /:/, $pkgv ); }

                    $pkgv =~ s/\n//g;

                    my ( $requiredver, $requiredop ) = split( /\|/, $INSTALLREQ{$item} );
                    if ( $requiredver =~ /:/ ) { ( undef, $requiredver ) = split( /:/, $requiredver ); }

                    my $compareopt = compareversion( $requiredver, $pkgv );

                    if ( $pkgv == -1 ) {
                        delete $INSTALLREQ{$item};
                        $sat = 1;
                    }
                    else {
                        if ( $requiredop eq "=" && $compareopt == 0 ) {
                            delete $INSTALLREQ{$item};
                            $sat = 1;
                        }
                        if ( $requiredop eq ">" && $compareopt == 1 ) {
                            delete $INSTALLREQ{$item};
                            $sat = 1;
                        }
                        if ( $requiredop eq "<" && $compareopt == -1 ) {
                            delete $INSTALLREQ{$item};
                            $sat = 1;
                        }
                        if ( $requiredop eq ">=" && ( $compareopt == 1 || $compareopt == 0 ) ) {
                            delete $INSTALLREQ{$item};
                            $sat = 1;
                        }
                        if ( $requiredop eq "<=" && ( $compareopt == -1 || $compareopt == 0 ) ) {
                            delete $INSTALLREQ{$item};
                            $sat = 1;
                        }
                    }
                }
                else {
                    delete $INSTALLREQ{$item};
                    $sat = 1;
                }
                if ( !$sat ) { next; }

                if ( !( ${ $self->{"deps"} }{$ppkg} >= 1 ) ) {
                    print "Adding Dependency ${ppkg} (required by $pkg)\n";
                    $self->resolvedeps( $ppkg, ( $level + 1 ), 0 );
                    foreach my $ndep ( sort keys %{ $self->{"deps"} } ) {
                        if ( ( $ndep eq "kernel" || $ndep =~ /^kernel-/ || $ndep =~ /^k_/ || $ndep =~ /httpd-/ ) && $ndep !~ /^kernel-source/ && $ndep !~ /^kernel-pcmcia/ ) { next; }
                        if ( ${ $self->{"deps"} }{$ndep} == 1 ) {
                            $self->resolvedeps( $ndep, ( $level + 1 ), 0 );
                        }
                    }
                }
            }
        }
        delete @DEPLIST{ keys %DEPLIST };
    }

    if ( $level == 0 ) {
        close(PRO);
    }

    if ( scalar keys %INSTALLREQ > 0 ) {
        my $unresdeath = 0;
        foreach my $unresdep ( keys %INSTALLREQ ) {
            if ( ( $unresdep eq "kernel" || $unresdep =~ /^kernel-/ || $unresdep =~ /^k_/ || $unresdep =~ /^httpd-/ ) && $unresdep !~ /^kernel-source/ && $unresdep !~ /^kernel-pcmcia/ ) { next; }
            print "Could not find $unresdep ($INSTALLREQ{$unresdep}) for $pkg\n";
            $unresdeath = 1;
        }
        if ($unresdeath) {
            die "[resolvedeps ($level)]";
        }
    }
    delete @SEEKPOINTS{ keys %SEEKPOINTS };
}

sub isinarray {
    my ( $pkg, $deps ) = @_;
    my (@DEPS) = @{$deps};
    foreach (@DEPS) {
        if ( $_ eq $pkg ) { return 1; }
    }
    return 0;
}

sub getlocalprovides {
    my ( $self, $nocache ) = @_;

    open( CPUP, "/root/.cpupdates/rpmdb-provides.mtime" );
    my $rpmdbmtime = <CPUP>;
    close(CPUP);

    my $currentrpmmtime;

    if ( -e "/var/lib/rpm/Provideversion" ) {
        $currentrpmmtime = ( stat("/var/lib/rpm/Provideversion") )[9];
    }
    else {
        $currentrpmmtime = ( stat("/var/lib/rpm/fileindex.rpm") )[9];
    }

    if ( $currentrpmmtime ne $rpmdbmtime ) {
        $nocache = 1;
    }

    open( CPUP, ">/root/.cpupdates/rpmdb-provides.mtime" );
    print CPUP $currentrpmmtime;
    close(CPUP);

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    if (   ( stat("/root/.cpupdates/$mon-$mday-$year.locprovides") )[7] < 4096
        || ( stat("/root/.cpupdates/$mon-$mday-$year.installed") )[7] < 200
        || $nocache ) {
        print "Building local rpm provides list...";
        open( INSTALLED, ">/root/.cpupdates/$mon-$mday-$year.installed" );
        my (%PROL);
        my (%PROD);
        open( RPM, "rpm -qa --queryformat \"\t%{NAME}\\%%{VERSION}-%{RELEASE}\\%[%{FILENAMES},]\n\" --provides|" );
        my ($pkg);
        while (<RPM>) {
            chomp();
            if (/^\t/) {
                s/^\t//g;
                my ( $pkgversion, $provides );
                ( $pkg, $pkgversion, $provides ) = split( /\%/, $_, 3 );
                print INSTALLED "${pkg}%${pkgversion}\n";
                my (@PROLIST) = split( /\,/, $provides );
                foreach my $pro (@PROLIST) {
                    next if ( $pro eq "" );
                    my $item = $pro;
                    my $version;
                    if ( $item =~ /=/ ) {
                        ( $item, $version ) = split( /\=/, $item );
                        $item    =~ s/^\s*|\s*$//g;
                        $version =~ s/^\s*|\s*$//g;
                    }
                    else {
                        $version = "-1";
                    }
                    $PROL{$item}{$pkg} = $version;
                }
            }
            else {
                my $item = $_;
                $item =~ s/^\s*|\s*$//g;
                my $version;
                if ( $item =~ /=/ ) {
                    ( $item, $version ) = split( /\=/, $item );
                    $item    =~ s/^\s*|\s*$//g;
                    $version =~ s/^\s*|\s*$//g;
                }
                else {
                    $version = "-1";
                }
                $PROL{$item}{$pkg} = $version;
                $PROD{$pkg}{$item} = $version;
            }
        }

        open( CPUP,  ">/root/.cpupdates/$mon-$mday-$year.locprovides" );
        open( CPUPI, ">/root/.cpupdates/$mon-$mday-$year.locprovides.index" );
        my $startchar = 0;
        foreach my $item ( sort keys %PROL ) {
            foreach my $package ( sort keys %{ $PROL{$item} } ) {
                if ( substr( $item, 0, 2 ) ne $startchar ) {
                    $startchar = substr( $item, 0, 2 );
                    my $filepos = tell(CPUP);
                    print CPUPI "$startchar $filepos\n";
                }
                print CPUP ${item} . "%" . $package . "%" . $PROL{$item}{$package} . "\n";
            }
        }
        close(INSTALLED);
        close(CPUPI);
        close(CPUP);

        open( CPUP,  ">/root/.cpupdates/$mon-$mday-$year.locproviders" );
        open( CPUPI, ">/root/.cpupdates/$mon-$mday-$year.locproviders.index" );
        my $startchar = 0;
        foreach my $package ( sort keys %PROD ) {
            foreach my $item ( sort keys %{ $PROD{$package} } ) {
                if ( substr( $item, 0, 2 ) ne $startchar ) {
                    $startchar = substr( $item, 0, 2 );
                    my $filepos = tell(CPUP);
                    print CPUPI "$startchar $filepos\n";
                }
                print CPUP ${package} . "%" . ${item} . "%" . $PROD{$package}{$item} . "\n";
            }
        }
        close(CPUP);
        close(CPUPI);

        delete @PROL{ keys %PROL };
        delete @PROD{ keys %PROD };
        print "Done\n";
    }
}

sub getlocalrequires {
    my ( $self, $nocache ) = @_;

    open( CPUP, "/root/.cpupdates/rpmdb-requires.mtime" );
    my $rpmdbmtime = <CPUP>;
    close(CPUP);

    my $currentrpmmtime;

    if ( -e "/var/lib/rpm/Provideversion" ) {
        $currentrpmmtime = ( stat("/var/lib/rpm/Provideversion") )[9];
    }
    else {
        $currentrpmmtime = ( stat("/var/lib/rpm/fileindex.rpm") )[9];
    }

    if ( $currentrpmmtime ne $rpmdbmtime ) {
        $nocache = 1;
    }

    open( CPUP, ">/root/.cpupdates/rpmdb-requires.mtime" );
    print CPUP $currentrpmmtime;
    close(CPUP);

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    if ( ( stat("/root/.cpupdates/$mon-$mday-$year.locrequires") )[7] < 4096
        || $nocache ) {
        print "Building local rpm requires list...";
        my (%PROL);
        my (%PROD);
        open( RPM, "rpm -qa --queryformat \"%{NAME}\\%%{VERSION}-%{RELEASE}\\%[%{REQUIRENAME}=%{REQUIREVERSION},]\n\"|" );
        my ($pkg);
        while (<RPM>) {
            chomp();
            my ( $pkgversion, $requires );
            ( $pkg, $pkgversion, $requires ) = split( /\%/, $_, 3 );
            my (@REQLIST) = split( /\,/, $requires );
            foreach my $req (@REQLIST) {
                next if ( $req eq "" );
                my ( $item, $version ) = split( /\=/, $req );
                $PROL{$item}{$pkg} = 1;
            }
        }
        close(RPM);

        open( CPUP,  ">/root/.cpupdates/$mon-$mday-$year.locrequires" );
        open( CPUPI, ">/root/.cpupdates/$mon-$mday-$year.locrequires.index" );
        my $startchar = 0;
        foreach my $item ( sort keys %PROL ) {
            foreach my $package ( sort keys %{ $PROL{$item} } ) {
                if ( substr( $item, 0, 2 ) ne $startchar ) {
                    $startchar = substr( $item, 0, 2 );
                    my $filepos = tell(CPUP);
                    print CPUPI "$startchar $filepos\n";
                }
                print CPUP ${item} . "%" . $package . "\n";
            }
        }
        close(INSTALLED);
        close(CPUPI);
        close(CPUP);

        delete @PROL{ keys %PROL };
        print "Done\n";
    }
}

sub getlocalprovidesupdate {
    my ( $self, @NEWPKGS ) = @_;

    my ( %INSTALLED, %LOCPRO );

    my $currentrpmmtime;

    if ( -e "/var/lib/rpm/Provideversion" ) {
        $currentrpmmtime = ( stat("/var/lib/rpm/Provideversion") )[9];
    }
    else {
        $currentrpmmtime = ( stat("/var/lib/rpm/fileindex.rpm") )[9];
    }

    open( CPUP, ">/root/.cpupdates/rpmdb-provides.mtime" );
    print CPUP $currentrpmmtime;
    close(CPUP);

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    my (%PROL);
    my (%PROD);
    open( CPUP, "/root/.cpupdates/$mon-$mday-$year.locprovides" );
    while (<CPUP>) {
        s/\n//g;
        foreach my $pkg (@NEWPKGS) {
            next if ( $pkg eq "kernel" );
            next if ( ( $pkg =~ /^kernel-/ || $pkg =~ /^k_/ || $pkg =~ /^httpd-/ ) && $pkg !~ /^kernel-source/ && $pkg !~ /^kernel-pcmcia/ );
            if ( substr( $_, -1 * length("%${pkg}") ) eq "%${pkg}" ) {
                next;
            }
        }
        my ( $item, $pkg, $version ) = split( /\%/, $_, 3 );
        $PROL{$item}{$pkg} = $version;
    }
    close(CPUP);

    open( CPUP, "/root/.cpupdates/$mon-$mday-$year.locproviders" );
    while (<CPUP>) {
        s/\n//g;
        foreach my $pkg (@NEWPKGS) {
            if ( substr( $_, length("%${pkg}") ) eq "${pkg}%" ) {
                next;
            }
        }
        my ( $pkg, $item, $version ) = split( /\%/, $_, 3 );
        $PROD{$pkg}{$item} = $version;
    }
    close(CPUP);

    print "Rebuilding local rpm provides list...";
    open( INSTALLED, ">>/root/.cpupdates/$mon-$mday-$year.installed" );

    foreach my $pkg (@NEWPKGS) {
        print "..$pkg..";
        my $pkginfo = `rpm -q --queryformat \"\t%{NAME}\\%%{VERSION}-%{RELEASE}\\%[%{FILENAMES},]\n\" --provides ${pkg}`;
        if ( $pkginfo =~ /is not installed/ ) { next; }
        s/\n//g;
        my (@PKGL) = split( /\n/, $pkginfo );
        my $pkgq = shift(@PKGL);
        $pkgq =~ s/^\t//g;
        my ( $pkg, $pkgversion, $provides ) = split( /\%/, $pkgq, 3 );
        print INSTALLED "${pkg}%${pkgversion}\n";
        my (@PROLIST) = split( /\,/, $provides );

        foreach my $pro (@PROLIST) {
            next if ( $pro eq "" );
            my $item = $pro;
            $item =~ s/^\s*|\s*$//g;
            my $version;
            if ( $item =~ /=/ ) {
                ( $item, $version ) = split( /\=/, $item );
                $item    =~ s/^\s*|\s*$//g;
                $version =~ s/^\s*|\s*$//g;
            }
            else {
                $version = "-1";
            }
            $PROL{$item}{$pkg} = $version;
        }
        foreach my $pro (@PKGL) {
            next if ( $pro eq "" );
            my $item = $pro;
            $item =~ s/^\s*|\s*$//g;
            my $version;
            if ( $item =~ /=/ ) {
                ( $item, $version ) = split( /\=/, $item );
                $item    =~ s/^\s*|\s*$//g;
                $version =~ s/^\s*|\s*$//g;
            }
            else {
                $version = "-1";
            }
            $PROL{$item}{$pkg} = $version;
            $PROD{$pkg}{$item} = $version;
        }
    }
    print "Done\n";

    open( CPUP,  ">/root/.cpupdates/$mon-$mday-$year.locprovides" );
    open( CPUPI, ">/root/.cpupdates/$mon-$mday-$year.locprovides.index" );
    my $startchar = 0;
    foreach my $item ( sort keys %PROL ) {
        foreach my $package ( sort keys %{ $PROL{$item} } ) {
            if ( substr( $item, 0, 2 ) ne $startchar ) {
                $startchar = substr( $item, 0, 2 );
                my $filepos = tell(CPUP);
                print CPUPI "$startchar $filepos\n";
            }
            print CPUP ${item} . "%" . $package . "%" . $PROL{$item}{$package} . "\n";
        }
    }
    close(CPUP);
    close(CPUPI);
    close(INSTALLED);

    open( CPUP,  ">/root/.cpupdates/$mon-$mday-$year.locproviders" );
    open( CPUPI, ">/root/.cpupdates/$mon-$mday-$year.locproviders.index" );
    my $startchar = 0;
    foreach my $package ( sort keys %PROD ) {
        foreach my $item ( sort keys %{ $PROD{$package} } ) {
            if ( substr( $item, 0, 2 ) ne $startchar ) {
                $startchar = substr( $item, 0, 2 );
                my $filepos = tell(CPUP);
                print CPUPI "$startchar $filepos\n";
            }
            print CPUP ${package} . "%" . ${item} . "%" . $PROD{$package}{$item} . "\n";
        }
    }
    close(CPUP);
    close(CPUPI);

    delete @PROL{ keys %PROL };
    delete @PROD{ keys %PROD };

}

sub getversionfromfile {
    my ($file) = @_;
    my ( $line, $version );

    open( FILE, $file );
    chomp( $line = <FILE> );
    if ( $line =~ /(\d+\.\d+)/ ) {
        $version = $1;
    }
    elsif ( $line =~ /(\d+)/ ) {
        $version = $1;
    }
    close(FILE);

    if ( $version eq "" ) { die "Can't find distro version"; }
    return $version;
}

sub httpreqI {
    my ( $host, $url, $outfile ) = @_;

    my $trueoutfile = $outfile;
    $trueoutfile =~ s/\.(bz2|gz)$//g;
    my $md5sum = httpreq( $host, $url . ".md5" );
    my $localmd5sum = getmd5sum($trueoutfile);

    $md5sum      =~ s/[\n\r\s\t]*//g;
    $localmd5sum =~ s/[\n\r\s\t]*//g;

    if ( $localmd5sum eq $md5sum ) {
        system( "touch", $trueoutfile );
        return ();
    }

    print "cached ${trueoutfile} is up to date...";

    httpreq( $host, $url, $outfile );

}

sub httpreq {
    my ($page);
    my ( $host, $url, $outfile ) = @_;

    if ( $outfile ne "" ) {
        open( HTTPREQF, ">$outfile" );
    }

    eval {
        $SIG{'PIPE'} = $SIG{'ALRM'} = sub {
            print "Unable to retrieve file\n";
            die;
        };
        alarm(30);
        my $proto = getprotobyname('tcp');
        socket( Socket_Handle, AF_INET, SOCK_STREAM, $proto );
        my $iaddr = inet_aton("$host");
        my $port  = getservbyname( 'http', 'tcp' );
        my $sin   = sockaddr_in( $port, $iaddr );
        connect( Socket_Handle, $sin );
        send Socket_Handle, "GET $url HTTP/1.0\r\nHost: $host\r\n\r\n", 0;
        my $inheader = 1;

        while (<Socket_Handle>) {
            alarm(20);
            if ( !$inheader ) {
                if   ( $outfile ne "" ) { print HTTPREQF; }
                else                    { $page .= $_; }
            }
            if ( $inheader && (/^HTTP\/\d+\.\d+ (\d+)/) ) {
                if ( $1 eq "404" || $1 eq "500" || $1 eq "301" ) {
                    print "Error $1 while fetching url http://$host/$url\n";
                    print "This could indicate you have not properly configured an update source:\n";
                    print "To select an update source create a file in /var/cpanel called use[sourcename]\n";
                    print "For example:\n";
                    print "\t/var/cpanel/useurpmi - URPMI (Mandrake,Mandriva)\n";
                    print "\t/var/cpanel/useyum - Yum (CloudLinux,CentOS,Fedora)\n";
                    print "\t/var/cpanel/useup2date - U2pdate (RHEL)\n";
                    print "\t/var/cpanel/useswup - SWUP (Trustix)\n";
                    print "\t/var/cpanel/userug - Rug (SuSE)\n";
                    print "\t/var/cpanel/useapt - Apt-Get (Debian)\n";
                    print "\t/var/cpanel/useemerge - Portage (Gentoo)\n";
                    return ();
                }
            }
            if ( $inheader && ( /^\n$/ || /^\r\n$/ || /^$/ ) ) { $inheader = 0; }
        }
        alarm(0);
    };

    if ( $outfile ne "" ) {
        open(HTTPREQF);
        return ();
    }
    return ($page);
}

sub compareversion {
    my ( $wants, $has, $ignorebuild ) = @_;

    #fedora-legacy for breaking the standard
    $wants =~ s/\.legacy$//g;
    $has   =~ s/\.legacy$//g;

    #0 if match =
    #-1 if less
    #1 if greater

    if ( $wants eq $has ) { return (0); }

    my (@WANTSVERR) = split( /-/, $wants );
    my (@HASVERR)   = split( /-/, $has );
    my ( $wantsrel, $hasrel );

    if ( $#WANTSVERR == 0 ) {
        $wantsrel = 0;
    }
    else {
        $wantsrel = pop(@WANTSVERR);
    }
    if ( $#HASVERR == 0 ) {
        $hasrel = 0;
    }
    else {
        $hasrel = pop(@HASVERR);
    }

    my ($wantsver) = join( "-", @WANTSVERR );

    my ($hasver) = join( "-", @HASVERR );

    if ( $wantsrel eq "" ) { $wantsrel = 0; }
    if ( $hasrel   eq "" ) { $hasrel   = 0; }

    if ( $wantsver eq $hasver && $wantsrel eq $hasrel ) { return (0); }

    my @WANTSVERS = split( /\./, $wantsver );
    my @HASVERS   = split( /\./, $hasver );

    while ( $#WANTSVERS < $#HASVERS ) {
        push( @WANTSVERS, "0" );
    }
    while ( $#WANTSVERS > $#HASVERS ) {
        push( @HASVERS, "0" );
    }

    for ( my $i = 0; $i <= $#WANTSVERS; $i++ ) {

        next if ( $HASVERS[$i] eq "0" && $i eq "0" && $WANTSVERS[$i] eq "0" );

        if ( $HASVERS[$i] =~ /rc/ && int( $WANTSVERS[$i] ) == int( $HASVERS[$i] ) ) {
            if ( $WANTSVERS[$i] !~ /rc/ ) { return (-1); }
            if ( $WANTSVERS[$i] =~ /rc/ ) {
                $WANTSVERS[$i] =~ /(\d+)$/;
                my $rcw = $1;
                $HASVERS[$i] =~ /(\d+)$/;
                my $rch = $1;
                if ( int($rcw) > int($rch) ) {
                    return (-1);
                }
                if ( int($rcw) < int($rch) ) {
                    return (1);
                }

            }
        }

        #perl 5.8.0 is better then 5.00404
        if ( $i > 0 && $WANTSVERS[$i] =~ /^00/ ) { $WANTSVERS[$i] = 0; }
        if ( $i > 0 && $HASVERS[$i]   =~ /^00/ ) { $HASVERS[$i]   = 0; }

        if ( $WANTSVERS[$i] =~ /\D$/ && $HASVERS[$i] =~ /\D$/ && int( $WANTSVERS[$i] ) == int( $HASVERS[$i] ) ) {
            $WANTSVERS[$i] =~ /(\D)$/;
            my $whatchar = $1;
            $HASVERS[$i] =~ /(\D)$/;
            my $haschar = $1;
            if ( ord($whatchar) > ord($haschar) ) { return (-1); }
            if ( ord($whatchar) < ord($haschar) ) { return (1); }
        }

        if ( int( $WANTSVERS[$i] ) > int( $HASVERS[$i] ) ) {
            return (-1);
        }
        if ( int( $WANTSVERS[$i] ) < int( $HASVERS[$i] ) ) {
            return (1);
        }
    }

    if ($ignorebuild) { return (-1); }

    #we get here if the version are the same
    my @WANTSRELS = split( /\./, $wantsrel );
    my @HASRELS   = split( /\./, $hasrel );

    while ( $#WANTSRELS < $#HASRELS ) {
        push( @WANTSRELS, "0" );
    }
    while ( $#WANTSRELS > $#HASRELS ) {
        push( @HASRELS, "0" );
    }

    for ( my $i = 0; $i <= $#WANTSRELS; $i++ ) {
        if ( int( $WANTSRELS[$i] ) > int( $HASRELS[$i] ) ) {
            return (-1);
        }
        if ( int( $WANTSRELS[$i] ) < int( $HASRELS[$i] ) ) {
            return (1);
        }
    }

    #we get here if the releases are the same
    return (0);

}

sub whatprovides {
    my ( $self, $item ) = @_;

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    if ( tell(PRO) == -1 ) {
        open( PRO, "/root/.cpupdates/$mon-$mday-$year.provides" );
    }
    while (<PRO>) {
        my $founddep = 0;
        my ( $fitem, $ppkg, $version ) = split( /\%/, $_, 3 );
        if ( $fitem =~ /${item}$/ ) {
            close(PRO);
            return ($ppkg);
            last;
        }
    }

    close(PRO);
}

sub getprovides {
    my ( $self, $item ) = @_;
    my (@PROVIDES);
    my ($seekpoint) = 0;

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    open( LPROIDX, "/root/.cpupdates/$mon-$mday-$year.locproviders.index" );
    while (<LPROIDX>) {
        my $itemidx = substr( $item, 0, 2 );
        if ( substr( $_, 0, length($itemidx) + 1 ) eq $itemidx . " " ) {
            /\s(\d+)$/;
            $seekpoint = $1;
            last;
        }
    }
    close(LPROIDX);

    my $founditem = 0;
    open( LPRO, "/root/.cpupdates/$mon-$mday-$year.locproviders" );
    seek( LPRO, $seekpoint, 0 );
    while (<LPRO>) {
        if ( substr( $_, 0, length($item) + 1 ) eq $item . "%" ) {
            chomp();
            $founditem = 1;
            my ( $version, $item );
            ( undef, $item, $version ) = split( /\%/, $_, 3 );
            push( @PROVIDES, "${item}" );
        }
        elsif ($founditem) {
            last;
        }
    }
    close(LPRO);

    return (@PROVIDES);

}

sub stripoutsameprovides {
    my ( $self, $pkg, $locp ) = @_;
    my (@PROVIDES)  = @{$locp};
    my ($seekpoint) = 0;

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    my %LOCPROVIDES;
    foreach my $provide (@PROVIDES) {
        $LOCPROVIDES{$provide} = 1;
    }
    undef @PROVIDES;

    my %SEEKPOINTS;
    open( PROIDX, "/root/.cpupdates/$mon-$mday-$year.provides.index" );
    while (<PROIDX>) {
        foreach my $item ( keys %LOCPROVIDES ) {
            my $itemidx = substr( $item, 0, 2 );
            if ( $SEEKPOINTS{$itemidx} eq "" && substr( $_, 0, length($itemidx) + 1 ) eq $itemidx . " " ) {
                /\s(\d+)$/;
                $SEEKPOINTS{$itemidx} = $1;
            }
        }
    }
    close(PROIDX);
    if ( tell(PRO) == -1 ) {
        open( PRO, "/root/.cpupdates/$mon-$mday-$year.provides" );
    }
    foreach my $item ( keys %LOCPROVIDES ) {
        next if ( $item eq $pkg );
        my $itemidx = substr( $item, 0, 2 );
        seek( PRO, $SEEKPOINTS{$itemidx}, 0 );
        while (<PRO>) {
            if ( substr( $_, 0, length($item) + 1 ) eq $item . "%" ) {
                s/\n//g;
                my ( $version, $ppkg );
                ( undef, $ppkg, $version ) = split( /\%/, $_, 3 );
                if ( $ppkg eq $pkg ) { delete $LOCPROVIDES{$item}; }
                last;    #stop searching as we found something that provides it
            }
        }
    }
    delete @SEEKPOINTS{ keys %SEEKPOINTS };

    foreach my $provide ( keys %LOCPROVIDES ) {
        push( @PROVIDES, $provide );
    }

    delete @LOCPROVIDES{ keys %LOCPROVIDES };

    return (@PROVIDES);
}

sub getwhatrequires {
    my ( $self, @REQITEMS ) = @_;
    my (@REQDPKGS);

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    my %SEEKPOINTS;
    open( LREQIDX, "/root/.cpupdates/$mon-$mday-$year.locrequires.index" );
    while (<LREQIDX>) {
        foreach my $item ( sort @REQITEMS ) {
            my $itemidx = substr( $item, 0, 2 );
            if ( substr( $_, 0, length($itemidx) + 1 ) eq $itemidx . " " ) {
                /\s(\d+)$/;
                $SEEKPOINTS{$item} = $1;
            }
        }
    }
    close(LREQIDX);
    open( LREQ, "/root/.cpupdates/$mon-$mday-$year.locrequires" );
    foreach my $item ( sort @REQITEMS ) {
        seek( LREQ, $SEEKPOINTS{$item}, 0 );
        while (<LREQ>) {
            if ( substr( $_, 0, length($item) + 1 ) eq $item . "%" ) {
                my ($reqpkg);
                chomp();
                ( undef, $reqpkg ) = split( /\%/, $_ );
                push( @REQDPKGS, $reqpkg );
            }
        }
    }
    close(LREQ);

    return (@REQDPKGS);
}

sub fetchrpm {
    my ( $self, $file, $md5sum ) = @_;
    my ($realfile) = $file;

    my $now = time();

    my $mday = $self->{"mday"};
    my $mon  = $self->{"mon"};
    my $year = $self->{"year"};

    chdir(".");
    my ($cwd) = $ENV{'PWD'};
    chomp($cwd);

    $realfile =~ s/^\/?linux\/distros\/redhat\///g;
    $realfile =~ s/^\/?redhat\/linux\///g;
    $realfile =~ s/^\/?redhat\///g;

    my @BS       = split( /\//, $realfile );
    my $basefile = $BS[$#BS];
    my $legacy   = '';

    if (   $realfile =~ /7\.3\//
        || $realfile =~ /9\.0\//
        || $realfile =~ /\/9\// ) {
        $legacy = '.legacy';
        $realfile =~ s/\/?en\//\//g;
        $realfile =~ s/^\///g;

        if ( $realfile =~ /updates\// ) {

            #swap source and version
            my @RF = split( /\//, $realfile );
            my $p0 = $RF[1];
            my $p1 = $RF[0];
            $RF[0] = $p0;
            $RF[1] = $p1;
            $realfile = join( "/", @RF );
            $realfile =~ s/\/?os\//\//g;
        }
        elsif ( $realfile =~ /RedHat\/RPMS/ ) {
            $realfile =~ s/\/?RedHat\/RPMS\//\//g;
        }
    }

    if ( !-e "/root/.cpupdates/$mon-$mday-$year.mirrors.times" ) {
        print "Fetching rpm mirror timestamp...";
        cPanelRPM::httpreq( 'updates.cpanel.net', "/pub/rpminstall/redhat/mirrors${legacy}.times", "/root/.cpupdates/$mon-$mday-$year.mirrors.times" );
        print "Done\n";
        if ( !-e "/root/.cpupdates/$mon-$mday-$year.mirrors.times" ) {
            die "Cannot fetch mirror list";
        }
    }

    open( MT, "/root/.cpupdates/$mon-$mday-$year.mirrors.times" );
    my $mirrortime = <MT>;
    close(MT);

    chomp($mirrortime);
    if ( ( $mirrortime - 500 ) > ( stat("/root/.cpupdates/mirrors.lst") )[9] || !-e "/root/.cpupdates/mirrors.lst" ) {
        print "Fetching rpm mirror list...";
        if ( -e "/bin/bzip2" || -e "/usr/bin/bzip2" ) {
            cPanelRPM::httpreq( 'updates.cpanel.net', "/pub/rpminstall/redhat/mirrors${legacy}.lst.bz2", "/root/.cpupdates/mirrors.lst.bz2" );
            system( "bzip2", "-d", "-f", "/root/.cpupdates/mirrors.lst.bz2" );
        }
        else {
            cPanelRPM::httpreq( 'updates.cpanel.net', "/pub/rpminstall/redhat/mirrors${legacy}.lst.gz", "/root/.cpupdates/mirrors.lst.gz" );
            system( "gzip", "-d", "-f", "/root/.cpupdates/mirrors.lst.gz" );
        }
        print "Done\n";
        if ( !-e "/root/.cpupdates/mirrors.lst" ) {
            die "Cannot fetch mirror list";
        }
    }

    open( MIRRORS, "/root/.cpupdates/mirrors.lst" );
    my @MIRRORS = <MIRRORS>;
    close(MIRRORS);

    print "Testing connection speed...(this could take a while)...";
    system("/scripts/pingtest");
    print ".Done\n";

    my (%PINGTIMES);
    opendir( PT, "/root/.cpupdates/pingtimes" );
    my @PT = readdir(PT);
    closedir(PT);
    foreach my $pt (@PT) {
        next if ( $pt =~ /^\./ );
        open( PINGTIMES, "/root/.cpupdates/pingtimes/${pt}" );
        $PINGTIMES{ ${pt} } = <PINGTIMES>;
        chomp $PINGTIMES{ ${pt} };
        close(PINGTIMES);
    }
    undef @PT;

    my (%URLS);
    $URLS{'updates.cpanel.net'} = "http://updates.cpanel.net/";

    foreach my $mirror ( sort { rand($a) <=> rand($b) } @MIRRORS ) {
        chomp($mirror);

        $mirror =~ /([^\:]+):\/\/([^\/]+)(\S+)/;
        my $pro  = $1;
        my $host = $2;
        my $url  = $3;

        next if ( $mirror =~ /^[\s\r\n\t]*$/ );

        $URLS{$host} = $mirror;
    }

    if ( !-e "/var/spool/cpupdates" ) {
        mkdir( "/var/spool/cpupdates", 0700 );
    }
    chdir("/var/spool/cpupdates");

    my (%MIRRORSPEED);
    my (%MIRRORTIME);

    open( MIRRORSPEEDS, "/root/.cpupdates/mirrors.speeds" );
    while (<MIRRORSPEEDS>) {
        chomp();
        my ( $mirror, $speed, $mirrortime ) = split( /=/, $_ );

        if ( $mirrortime + ( 86400 * 15 ) > ${now} ) { next(); }

        $MIRRORSPEED{$mirror} = $speed;
        $MIRRORTIME{$mirror}  = $mirrortime;
    }
    close(MIRRORSPEEDS);

    my $dc = 0;
    foreach my $host ( sort { $PINGTIMES{$a} <=> $PINGTIMES{$b} } keys %PINGTIMES ) {
        if ( $dc >= 4 ) { print "Four usable mirrors located\n"; last; }

        if ( $MIRRORSPEED{$host} eq "" ) {
            print "Ping:$PINGTIMES{$host} ";
            $MIRRORSPEED{$host} = testmirrorspeed( $realfile, $host, $URLS{$host}, $legacy );
        }

        if ( $MIRRORSPEED{$host} > 1 ) { $dc++; }
    }

    open( MIRRORSPEEDS, ">/root/.cpupdates/mirrors.speeds" );
    foreach my $mirror ( keys %MIRRORSPEED ) {
        print MIRRORSPEEDS "${mirror}=$MIRRORSPEED{$mirror}=$MIRRORTIME{$mirror}\n";
    }
    close(MIRRORSPEEDS);

    $dc = 0;
    foreach my $host ( sort { $MIRRORSPEED{$b} <=> $MIRRORSPEED{$a} } keys %MIRRORSPEED ) {
        $dc++;

        if ( $dc >= 10 ) { last; }

        last if ( ( stat("$basefile") )[7] > 1 && getmd5sum($basefile) eq $md5sum );

        unlink("/var/spool/cpupdates/$basefile");

        if ( -e "/usr/bin/wget" || -e "/usr/local/bin/wget" ) {
            print "Trying to fetch ${basefile} from $URLS{$host} using wget...\n";
            system( "wget", "-t", "2", "--timeout", "300", "--passive-ftp", "-O", "${basefile}", $URLS{$host} . "/" . ${realfile} );
        }
        elsif ( -e "/usr/bin/curl" || -e "/usr/local/bin/curl" ) {
            print "Trying to fetch ${basefile} from $URLS{$host} using curl...\n";
            system( "curl", "-m", "1000", "-o", "${basefile}", $URLS{$host} . "/" . ${realfile} );
        }
        elsif ( $URLS{$host} =~ /^ftp/ && ( -e "/usr/bin/ncftpget" || -e "/usr/local/bin/ncftpget" ) ) {
            print "Trying to fetch ${basefile} from $URLS{$host} using ncftpget...\n";
            system( "ncftpget", "-z", "${basefile}", $URLS{$host} . "/" . ${realfile} );
        }
        else {
            die "wget/curl/ncftpget is not installed";
        }
    }

    delete @MIRRORSPEED{ keys %MIRRORSPEED };
    delete @MIRRORTIME{ keys %MIRRORTIME };

    if ( $md5sum eq getmd5sum($basefile) ) {
        chdir($cwd);
        return (1);
    }
    chdir($cwd);
    return (0);
}

sub pinghost {
    my ($host) = @_;
    my ($pingtime);
    open( PING, "-|" ) || exec( "ping", "-w", "3", "-c", "2", $host );
    while (<PING>) {
        if (/[\d\.]+\/([\d\.]+)/) {
            $pingtime = $1;
        }
    }
    close(PING);
    if ( $pingtime eq "" ) { $pingtime = 1000; }
    return ($pingtime);
}

sub getmd5sum {
    my ($file) = @_;
    my ($md5);
    open( MD5, "-|" ) || exec 'md5sum', $file;
    while (<MD5>) {
        chomp();
        ( $md5, undef ) = split( /\s+/, $_ );
        last();
    }
    close(MD5);
    return ($md5);
}

sub testmirrorspeed {
    my ( $base, $host, $url, $legacy ) = @_;

    $base =~ /([\d\.]+)\//;

    my $version = $1;

    $base = "${version}/en/os/i386";

    my $speed;

    open( WNULL, ">/dev/null" );
    open( RNULL, "</dev/null" );

    my $file = 'RELEASE-NOTES';
    if ( $legacy ne "" ) {
        $base = '';
        $url =~ s/\/?redhat\/?//g;
        $file = 'index.html';
    }
    if ( $url =~ /^http/ ) {
        print "Testing connection speed to $host using pureperl...";
        my $RES = Cpanel::HttpTimer::timedrequest( url => $url . "/" . ${base} . "/" . $file );
        $speed = $$RES{'speed'};
    }
    else {

        unlink($file);

        my $tpid;

        if ( -e "/usr/bin/wget" || -e "/usr/local/bin/wget" ) {
            print "Testing connection speed to $host using wget...";
            $tpid = open3( "<&RNULL", ">&WNULL", \*ERRFH, "wget", "--timeout", "90", "-t", "2", "--passive-ftp", "-O", $file, $url . "/" . ${base} . "/" . $file );
            while (<ERRFH>) {
                if (/\(([\d\.]+)\s+([^\)]+)/) {
                    $speed = $1;
                    if ( $2 =~ /^k/i ) { $speed = ( $speed * 1000 ); }
                    if ( $2 =~ /^m/i ) { $speed = ( $speed * 1000000 ); }
                    if ( $2 =~ /^g/i ) { $speed = ( $speed * 1000000000 ); }
                }
            }
            close(ERRFH);
        }
        elsif ( -e '/usr/bin/curl' || -e '/usr/local/bin/curl' ) {
            print "Testing connection speed to $host using curl...";

            $tpid = open3( '<&RNULL', '>&WNULL', \*ERRFH, 'curl', '-m', '100', '-o', $file, $url . "/" . ${base} . "/" . $file );
            while (<ERRFH>) {

                #  7  628k    7 46091    0     0  39876
                if (/\s*\d+\s+\S+\s+\d+\S+\s+\d+\s+\S+\s+(\d+)(\S+)/) {
                    $speed = $1;
                    if ( $2 =~ /k$/i ) { $speed = ( $speed * 1000 ); }
                    if ( $2 =~ /m$/i ) { $speed = ( $speed * 1000000 ); }
                    if ( $2 =~ /g$/i ) { $speed = ( $speed * 1000000000 ); }
                }
            }
            close(ERRFH);
        }
        elsif ( $url =~ /^ftp/ && ( -e "/usr/bin/ncftpget" || -e "/usr/local/bin/ncftpget" ) ) {
            print "Testing connection speed to $host using ncftpget...";
            open( ERRFH, "-|" ) || exec( "ncftpget", "-z", $url . "/" . ${base} . "/" . $file );
            while (<ERRFH>) {
                if (/([\d\.]+)\s+(\S+)\s*$/) {
                    $speed = $1;
                    if ( $2 =~ /^k/i ) { $speed = ( $speed * 1000 ); }
                    if ( $2 =~ /^m/i ) { $speed = ( $speed * 1000000 ); }
                    if ( $2 =~ /^g/i ) { $speed = ( $speed * 1000000000 ); }
                }
            }
            close(ERRFH);
        }

        unlink($file);

        close(RNULL);
        close(WNULL);

        waitpid( $tpid, 0 );
    }

    if ( $speed eq "" ) {
        $speed = 0;
        print "test failed...Done\n";
    }
    else {
        print "($speed bytes/s)...Done\n";
    }

    return ($speed);
}

1;