Mini Shell

Direktori : /proc/self/root/opt/sharedrads/perl/IMH/CPanel/
Upload File :
Current File : //proc/self/root/opt/sharedrads/perl/IMH/CPanel/Agent.pm

#!/usr/bin/perl
# encoding: utf-8
#
# author: Kyle Yetter
#
=pod

=head1 IMH::CPanel::Agent

IMH::CPanel::Agent - a class that is used to send and receive cPanel JSON API requests
to and from the local server.

=head1 Summary

use IMH::CPanel::Agent;

#
# pass a cPanel user name to the constructor to specify the target user of the
# API calls
#
my $agent = IMH::CPanel::Agent->new( "userna5" );

#
# Basic API calls for the functions documented at
# http://docs.cpanel.net/twiki/bin/view/SoftwareDevelopmentKit/XmlApi
#
my $result = $agent->quick_api( 'modifyacct', domain => "new-domain.com" );

#
# Version 1 Modular API calls use positional arguments. See documentation at
# http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api1/WebHome
#
my $result = $agent->modular_api_v1( "StatsBar", "stats", display => "ftpaccounts" );

#
# Version 2 Modular API calls use named parameters. See documentation at
# http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api2/WebHome
#
my $result = $agent->modular_api_v2( "StatsBar", "stats", display => "ftpaccounts" );


# All $results above are hashes with contents that vary widely depending upon
# the actual API call. Please read up on the cPanel documentation for more
# information

=cut

# since the local SSL certificate's probably self-signed, allow the query
# to skip certificate verification
$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;

package IMH::CPanel::Agent;

use strict;
use warnings;

our $VERSION = '0.01';

use LWP::UserAgent;
use URI;
use File::Basename;
use File::Slurp qw( slurp read_dir write_file );
use File::Spec::Functions;
use Term::ReadLine;
use JSON::Syck;
use Data::Dumper;
use IMH::Terminal;

our $created_access_key = 0;


# display extra debugging info if true
our $debug  = 0;

# set to 0 when a WHM api call fails
our $api_success = 1;

# the WHM access key to authenticate the calls -- read when needed
our $whm_access_key = undef;

our $console = undef;

sub tidy($) {
  my ( $str ) = @_;
  $str =~ s(\A\r?\n)();
  $str =~ s(\r?\n[ \t]*\z)();
  $str =~ s(^\s*\| ?)()mg;
  return $str;
}

sub agree($) {
  my ( $question ) = @_;
  $question = "$question [yes/no] ";
  $console ||= Term::ReadLine->new( basename( $0 ) );
  $console->newTTY( \*STDIN, \*STDERR );

  while ( defined( $_ = $console->readline( $question ) ) ) {
    if ( /^y/i ) {
      return 1;
    } elsif ( /^n/i ) {
      return 0;
    } else {
      print STDERR "Please enter `yes' or `no'\n";
    }
  }
  return 0;
}

sub load_json($) {
  my ( $source ) = @_;
  my $data;
  eval { $data = JSON::Syck::Load( $source ); };
  if ( $@ ) {
    die( $@ . "\nJSON SOURCE:\n" . $source );
  }
  return $data;
}


# this module's missing sometimes, so check if it's available.
# If not, the script will fail in a hard-to-figure-out way.
eval {
  require LWP::Protocol::https;
} or do {
  print STDERR tidy q(
  | The Perl module LWP::Protocol::https is not installed on this system.
  | It can be installed via:
  |   /scripts/perlinstaller LWP::Protocol::https\n
  );

  if ( agree( "Do you want to try and install it now?" ) ) {
    my @command = qw( /scripts/perlinstaller LWP::Protocol::https );
    my $status  = system( @command );

    die "perlinstaller failed with exit status `$status'" unless $status == 0;

    eval { require LWP::Protocol::https; } or do {
      die "the perlinstaller command didn't fail, but I still can't load the LWP::Protocol::https Perl module";
    };
  } else {
    die "cannot run without the LWP::Protocol::https Perl module";
  }
};


sub new {
  my ( $class, $user ) = @_;
  my $object = { user => $user, debug => 0 };
  bless( $object, $class || __PACKAGE__ );
  return $object;
}

sub user {
  my ( $self, @args ) = @_;
  if ( @args ) {
    $self->{user} = $args[ 0 ];
  }
  return $self->{user};
}

sub debug {
  my ( $self, @args ) = @_;
  if ( @args ) {
    $self->{debug} = $args[ 0 ];
  }
  return $self->{debug};
}

sub d {
  my $self = shift;
  if ( $self->{debug} ) {
    my ( $fmt, @params ) = @_;
    local $\ = "\n";

    my $message = c( sprintf( $fmt, @params ), 'cyan' );
    print STDERR "DEBUG: $message";
  }
}

sub quick_api {
  my ( $self, $function, %params ) = @_;

  my $uri = URI->new( "https://127.0.0.1:2087/json-api/$function" );
  $uri->query_form( %params );
  $self->d( "query URI: %s", $uri );

  my $auth    = "WHM root:" . whm_access_key();
  my $ua      = LWP::UserAgent->new;
  my $request = HTTP::Request->new( GET => "$uri" );

  $request->header( Authorization => $auth );
  my $response = $ua->request( $request );

  my $data = load_json( $response->content );
  $self->d( "json data:\n%s", Dumper( $data ) ) if $self->{debug};
  # ^-- keeps the Dumper call from executing unless totally necessary

  $self->{response} = $response;
  return $data;
}

sub modular_api_v1 {
  my ( $self, $module, $func, @args ) = @_;
  my %opts = (
    cpanel_jsonapi_user => $self->{user},
    cpanel_jsonapi_module => $module,
    cpanel_jsonapi_func => $func,
    cpanel_jsonapi_apiversion => 1
  );
  for my $i ( 0 .. $#args ) {
    $opts{ "arg-$i" } = $args[ $i ];
  }
  return $self->quick_api( 'cpanel', %opts );
}

sub modular_api_v2 {
  my ( $self, $module, $func, %params ) = @_;
  my %opts = (
    cpanel_jsonapi_user       => $self->{user},
    cpanel_jsonapi_module     => $module,
    cpanel_jsonapi_func       => $func,
    cpanel_jsonapi_apiversion => 2,
    %params
  );
  my $result = $self->quick_api( 'cpanel', %opts );
  return $result->{ cpanelresult };
}

sub whm_access_key {
  unless ( $whm_access_key ) {
    unless ( -f "/root/.accesshash" ) {
      $ENV{ REMOTE_USER } = 'root';
      `/usr/local/cpanel/bin/mkaccesshash`;
      delete $ENV{ REMOTE_USER };
      $created_access_key = 1;
    }

    $whm_access_key = slurp( "/root/.accesshash" ) or die "could not read /root/.accesshash: $!";
    $whm_access_key =~ s/\n//g;
  }
  return $whm_access_key
}

END {
  #
  # If we had to create a temporary access hash to make this work,
  # make sure it gets trashed
  #
  if ( -f '/root/.accesshash' && $created_access_key ) {
    unlink( '/root/.accesshash' ) or die( "failed to remove /root/.accesshash" );
  }
};

1;

Zerion Mini Shell 1.0