├── .gitignore ├── ignore.txt ├── .perltidyrc ├── t ├── 00-load.t ├── check-changes.t ├── cpan-changes.t ├── manifest.t ├── pod.t ├── pod-coverage.t ├── lib │ └── PubApiTest.pm ├── 05-api-query_tokens.t ├── 06-api-tokens.t ├── 04-tfa-sessions.t ├── 03-api-query.t ├── 02-construct.t └── 01-api-format.t ├── .travis.yml ├── MANIFEST ├── MANIFEST.SKIP ├── Makefile.PL ├── lib └── cPanel │ ├── PublicAPI │ ├── WHM │ │ ├── XMLAPI.pm │ │ ├── JSONAPI.pm │ │ ├── Legacy.pod │ │ ├── CachedVersion.pod │ │ ├── CachedVersion.pm │ │ ├── Legacy.pm │ │ ├── DNS.pm │ │ ├── DNS.pod │ │ ├── API.pod │ │ ├── XMLAPI.pod │ │ ├── JSONAPI.pod │ │ └── API.pm │ ├── Utils.pod │ ├── Utils.pm │ ├── WHM.pm │ └── WHM.pod │ └── PublicAPI.pod ├── Changes ├── README.mkdn └── README /.gitignore: -------------------------------------------------------------------------------- 1 | *.tdy 2 | *.bak 3 | cPanel-PublicAPI-* 4 | /Makefile 5 | /blib 6 | /pm_to_blib 7 | /MYMETA.json 8 | /MYMETA.yml 9 | /Makefile.old 10 | -------------------------------------------------------------------------------- /ignore.txt: -------------------------------------------------------------------------------- 1 | blib* 2 | Makefile 3 | Makefile.old 4 | Build 5 | Build.bat 6 | _build* 7 | pm_to_blib* 8 | *.tar.gz 9 | .lwpcookies 10 | cover_db 11 | pod2htm*.tmp 12 | cPanel-PublicAPI-* 13 | -------------------------------------------------------------------------------- /.perltidyrc: -------------------------------------------------------------------------------- 1 | -l=400 2 | -i=4 3 | -dt=4 4 | -it=4 5 | -bar 6 | -nsfs 7 | -nolq 8 | --break-at-old-comma-breakpoints 9 | --format-skipping 10 | --format-skipping-begin='#\s*tidyoff' 11 | --format-skipping-end='#\s*tidyon' 12 | -------------------------------------------------------------------------------- /t/00-load.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | 3 | use Test::More tests => 1; 4 | 5 | BEGIN { 6 | use_ok('cPanel::PublicAPI') || print "Bail out! 7 | "; 8 | } 9 | 10 | diag("Testing cPanel::PublicAPI $cPanel::PublicAPI::VERSION, Perl $], $^X"); 11 | -------------------------------------------------------------------------------- /t/check-changes.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use Test::More; 4 | plan skip_all => 'Release tests not required for installation' 5 | if not $ENV{RELEASE_TESTING}; 6 | 7 | eval { require Test::CheckChanges }; 8 | plan skip_all => 'Test::CheckChanges required for this test' if $@; 9 | Test::CheckChanges::ok_changes(); 10 | -------------------------------------------------------------------------------- /t/cpan-changes.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use Test::More; 4 | plan skip_all => 'Release tests not required for installation' 5 | if not $ENV{RELEASE_TESTING}; 6 | 7 | eval { require Test::CPAN::Changes }; 8 | plan skip_all => 'Test::CPAN::Changes required for this test' if $@; 9 | Test::CPAN::Changes::changes_ok(); 10 | -------------------------------------------------------------------------------- /t/manifest.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | unless ( $ENV{RELEASE_TESTING} ) { 8 | plan( skip_all => "Release tests not required for installation" ); 9 | } 10 | 11 | eval "use Test::CheckManifest 0.9"; 12 | plan skip_all => "Test::CheckManifest 0.9 required" if $@; 13 | ok_manifest(); 14 | -------------------------------------------------------------------------------- /t/pod.t: -------------------------------------------------------------------------------- 1 | #!perl -T 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | 7 | unless ( $ENV{RELEASE_TESTING} ) { 8 | plan( skip_all => "Release tests not required for installation" ); 9 | } 10 | 11 | # Ensure a recent version of Test::Pod 12 | my $min_tp = 1.22; 13 | eval "use Test::Pod $min_tp"; 14 | plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; 15 | 16 | all_pod_files_ok(); 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: perl 2 | notifications: 3 | slack: 4 | rooms: 5 | - cpanelllc:V6BAp4TZMPzu6ieWNznycYKK#busy-camels 6 | env: 7 | global: 8 | - PERL_USE_UNSAFE_INC=0 9 | - AUTHOR_TESTING=1 10 | - AUTOMATED_TESTING=1 11 | - RELEASE_TESTING=1 12 | perl: 13 | - "5.30" 14 | - "5.28" 15 | - "5.26" 16 | - "5.24" 17 | - "5.22" 18 | # - "5.20" 19 | # - "5.18" 20 | # - "5.16" 21 | # - "5.14" 22 | # - "5.12" 23 | # - "5.10" 24 | script: 25 | - perl Makefile.PL && make test 26 | -------------------------------------------------------------------------------- /t/pod-coverage.t: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use Test::More; 4 | 5 | unless ( $ENV{RELEASE_TESTING} ) { 6 | plan( skip_all => "Release tests not required for installation" ); 7 | } 8 | 9 | # Ensure a recent version of Test::Pod::Coverage 10 | my $min_tpc = 1.08; 11 | eval "use Test::Pod::Coverage $min_tpc"; 12 | plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage" 13 | if $@; 14 | 15 | # Test::Pod::Coverage doesn't require a minimum Pod::Coverage version, 16 | # but older versions don't recognize some common documentation styles 17 | my $min_pc = 0.18; 18 | eval "use Pod::Coverage $min_pc"; 19 | plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage" 20 | if $@; 21 | 22 | all_pod_coverage_ok(); 23 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | Changes 2 | ignore.txt 3 | lib/cPanel/PublicAPI.pm 4 | lib/cPanel/PublicAPI.pod 5 | lib/cPanel/PublicAPI/Utils.pm 6 | lib/cPanel/PublicAPI/Utils.pod 7 | lib/cPanel/PublicAPI/WHM.pm 8 | lib/cPanel/PublicAPI/WHM.pod 9 | lib/cPanel/PublicAPI/WHM/API.pm 10 | lib/cPanel/PublicAPI/WHM/API.pod 11 | lib/cPanel/PublicAPI/WHM/CachedVersion.pm 12 | lib/cPanel/PublicAPI/WHM/CachedVersion.pod 13 | lib/cPanel/PublicAPI/WHM/DNS.pm 14 | lib/cPanel/PublicAPI/WHM/DNS.pod 15 | lib/cPanel/PublicAPI/WHM/JSONAPI.pm 16 | lib/cPanel/PublicAPI/WHM/JSONAPI.pod 17 | lib/cPanel/PublicAPI/WHM/Legacy.pm 18 | lib/cPanel/PublicAPI/WHM/Legacy.pod 19 | lib/cPanel/PublicAPI/WHM/XMLAPI.pm 20 | lib/cPanel/PublicAPI/WHM/XMLAPI.pod 21 | Makefile.PL 22 | MANIFEST 23 | MANIFEST.SKIP 24 | README 25 | README.mkdn 26 | t/00-load.t 27 | t/01-api-format.t 28 | t/02-construct.t 29 | t/03-api-query.t 30 | t/04-tfa-sessions.t 31 | t/05-api-query_tokens.t 32 | t/check-changes.t 33 | t/cpan-changes.t 34 | t/lib/PubApiTest.pm 35 | t/manifest.t 36 | t/pod-coverage.t 37 | t/pod.t 38 | -------------------------------------------------------------------------------- /MANIFEST.SKIP: -------------------------------------------------------------------------------- 1 | ^\.perltidyrc 2 | ^\.travis.yml 3 | #!start included /Users/markgardner/.plenv/versions/5.26.1/lib/perl5/5.26.1/ExtUtils/MANIFEST.SKIP 4 | # Avoid version control files. 5 | \bRCS\b 6 | \bCVS\b 7 | \bSCCS\b 8 | ,v$ 9 | \B\.svn\b 10 | \B\.git\b 11 | \B\.gitignore\b 12 | \b_darcs\b 13 | \B\.cvsignore$ 14 | 15 | # Avoid VMS specific MakeMaker generated files 16 | \bDescrip.MMS$ 17 | \bDESCRIP.MMS$ 18 | \bdescrip.mms$ 19 | 20 | # Avoid Makemaker generated and utility files. 21 | \bMANIFEST\.bak 22 | \bMakefile$ 23 | \bblib/ 24 | \bMakeMaker-\d 25 | \bpm_to_blib\.ts$ 26 | \bpm_to_blib$ 27 | \bblibdirs\.ts$ # 6.18 through 6.25 generated this 28 | \b_eumm/ # 7.05_05 and above 29 | 30 | # Avoid Module::Build generated and utility files. 31 | \bBuild$ 32 | \b_build/ 33 | \bBuild.bat$ 34 | \bBuild.COM$ 35 | \bBUILD.COM$ 36 | \bbuild.com$ 37 | 38 | # and Module::Build::Tiny generated files 39 | \b_build_params$ 40 | 41 | # Avoid temp and backup files. 42 | ~$ 43 | \.old$ 44 | \#$ 45 | \b\.# 46 | \.bak$ 47 | \.tmp$ 48 | \.# 49 | \.rej$ 50 | \..*\.sw.?$ 51 | 52 | # Avoid OS-specific files/dirs 53 | # Mac OSX metadata 54 | \B\.DS_Store 55 | # Mac OSX SMB mount metadata files 56 | \B\._ 57 | 58 | # Avoid Devel::Cover and Devel::CoverX::Covered files. 59 | \bcover_db\b 60 | \bcovered\b 61 | 62 | # Avoid prove files 63 | \B\.prove$ 64 | 65 | # Avoid MYMETA files 66 | ^MYMETA\. 67 | #!end included /Users/markgardner/.plenv/versions/5.26.1/lib/perl5/5.26.1/ExtUtils/MANIFEST.SKIP 68 | 69 | -------------------------------------------------------------------------------- /Makefile.PL: -------------------------------------------------------------------------------- 1 | use strict; 2 | use warnings; 3 | use ExtUtils::MakeMaker; 4 | 5 | die "OS unsupported\n" if $^O eq 'MSWin32'; # Requires getpwuid to be implemented. 6 | 7 | WriteMakefile( 8 | NAME => 'cPanel::PublicAPI', 9 | AUTHOR => q{cPanel, Inc. }, 10 | VERSION_FROM => 'lib/cPanel/PublicAPI.pm', 11 | ABSTRACT_FROM => 'lib/cPanel/PublicAPI.pod', 12 | ( $ExtUtils::MakeMaker::VERSION >= 6.3002 13 | ? ( 'LICENSE' => 'bsd' ) 14 | : () ), 15 | PL_FILES => {}, 16 | PREREQ_PM => { 17 | 'Test::More' => 0, 18 | 'Test::Exception' => 0, 19 | 'JSON::XS' => 2.0, 20 | 'URI::Escape' => 3, 21 | 'IO::Socket::INET' => 1.31, 22 | 'IO::Socket::SSL' => 1.988, # Versions below this do not handle close calls properly 23 | 'HTTP::Tiny' => 0.042, 24 | 'HTTP::CookieJar' => 0, 25 | }, 26 | META_MERGE => { 27 | 'meta-spec' => { version => 2 }, 28 | resources => { 29 | repository => { 30 | type => 'git', 31 | url => 'git://github.com/CpanelInc/cPanel-PublicAPI.git', 32 | web => 'https://github.com/CpanelInc/cPanel-PublicAPI', 33 | }, 34 | bugtracker => { 35 | web => 'https://github.com/CpanelInc/cPanel-PublicAPI/issues', 36 | }, 37 | }, 38 | }, 39 | dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, 40 | clean => { FILES => 'cPanel-PublicAPI-*' }, 41 | ); 42 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/XMLAPI.pm: -------------------------------------------------------------------------------- 1 | package cPanel::PublicAPI::XMLAPI; 2 | 3 | # Copyright (c) 2015, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use cPanel::PublicAPI (); 33 | 34 | our $VERSION = '2.3'; 35 | 36 | package cPanel::PublicAPI; 37 | 38 | use cPanel::PublicAPI::WHM::API (); 39 | 40 | foreach my $sub ( grep ( /^api_/, keys %cPanel::PublicAPI:: ) ) { 41 | *{"xml$sub"} = *$sub; 42 | } 43 | 44 | 1; 45 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/JSONAPI.pm: -------------------------------------------------------------------------------- 1 | package cPanel::PublicAPI::JSONAPI; 2 | 3 | # Copyright (c) 2015, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use cPanel::PublicAPI (); 33 | 34 | our $VERSION = '2.3'; 35 | 36 | package cPanel::PublicAPI; 37 | 38 | use cPanel::PublicAPI::WHM::API (); 39 | 40 | foreach my $sub ( grep ( /^api_/, keys %cPanel::PublicAPI:: ) ) { 41 | *{"json$sub"} = *$sub; 42 | } 43 | 44 | 1; 45 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/Legacy.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI::WHM::Legacy - A module for handling Cpanel::Accounting backward compatibility within the cPanel::PublicAPI framework. 6 | 7 | =head1 DESCRIPTION 8 | 9 | This module should never be used, please use cPanel::PublicAPI-Ewhm_api() instead. 10 | 11 | =head1 Bugs 12 | 13 | see http://rt.cpan.org to report and view bugs 14 | 15 | =head1 License 16 | 17 | Copyright (c) 2015, cPanel, Inc. 18 | All rights reserved. 19 | http://cpanel.net 20 | 21 | Redistribution and use in source and binary forms, with or without 22 | modification, are permitted provided that the following conditions are met: 23 | * Redistributions of source code must retain the above copyright 24 | notice, this list of conditions and the following disclaimer. 25 | * Redistributions in binary form must reproduce the above copyright 26 | notice, this list of conditions and the following disclaimer in the 27 | documentation and/or other materials provided with the distribution. 28 | * Neither the name of cPanel, Inc. nor the 29 | names of its contributors may be used to endorse or promote products 30 | derived from this software without specific prior written permission. 31 | 32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 33 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 34 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 35 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 36 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 39 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | -------------------------------------------------------------------------------- /Changes: -------------------------------------------------------------------------------- 1 | Revision history for cPanel-PublicAPI 2 | 3 | 2.8 2021-01-25 4 | Don’t create symbol table entries for JSON decoders we don’t load. 5 | 6 | 2.7 2019-11-13 7 | Fix http_tiny_creator parameter handling. 8 | 9 | 2.6 2019-11-06 10 | Add http_tiny_creator parameter. 11 | Fix trivial typo in test error message. 12 | 13 | 2.5 2019-05-13 14 | Fix error details on 599 error (typo in 2.4 change). 15 | 16 | 2.4 2019-04-23 17 | Add compatibility logic for cPanel API tokens. 18 | Print HTTP::Tiny “content” when it gives a 599 error (e.g., TLS error). 19 | 20 | 2.3 2018-12-28 21 | Bump version number to be strictly greater than 2.2 22 | Switch cPanel provided encoder to be the real encoder: Cpanel::Encoder::URI 23 | Testing commits on Travis now. 24 | Update README 25 | Block install/test reports for windows since they require getpwuid to pass. 26 | 27 | 2.2.1 2017-10-09 28 | Update Changes, MANIFEST and README. 29 | 30 | 2.2 2017-04-17 31 | Implement HTTP support via HTTP::Tiny. 32 | Support two-factor authentication (2FA) workflow. 33 | Establish session when using user/pass; accesshash still uses Basic Auth. 34 | Support API tokens via new api_token constructor option. 35 | Documentation fixes. 36 | Unit test fixes. 37 | 38 | 2.0 2015-09-15 39 | Updated PublicAPI pod file to include description 40 | of new ssl_verify_mode option. 41 | Default WHM API to v1. 42 | 43 | 1.3 2015-09-14 44 | Fix hash randomization problem on newer Perls. 45 | 46 | 1.2 2015-08-26 47 | Updated from main code-base, changes include: 48 | Fixed non-numeric comparison errors. 49 | Cleaned up uninitialized variable use. 50 | Error checking after api_request in cPanel::PublicAPI::whm_api() call. 51 | Correct comments in copyright headers w/ modified bsd license 52 | Correct disclaimer in 3-clause BSD license 53 | Changes to accommodate latest version of IO::Socket::SSL 54 | Removed Frontpage references 55 | Changed to work with self-signed SSL certificates 56 | 57 | 1.0 2011-02-24 58 | First version, Implement HTTP querying. 59 | 60 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/Utils.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI::Utils - Provides some internally used utility functions for cPanel::PublicAPI, should never be used externally. 6 | 7 | =head1 Subroutines 8 | 9 | =head2 remove_trailing_newline() 10 | 11 | Removes the training newline from the provided string 12 | 13 | =head2 get_string_with_collapsed_trailing_eols 14 | 15 | Takes an array or array of arrays and puts them into a newline-seperated string. 16 | 17 | =head1 Bugs 18 | 19 | see http://rt.cpan.org to report and view bugs 20 | 21 | =head1 License 22 | 23 | Copyright (c) 2015, cPanel, Inc. 24 | All rights reserved. 25 | http://cpanel.net 26 | 27 | Redistribution and use in source and binary forms, with or without 28 | modification, are permitted provided that the following conditions are met: 29 | * Redistributions of source code must retain the above copyright 30 | notice, this list of conditions and the following disclaimer. 31 | * Redistributions in binary form must reproduce the above copyright 32 | notice, this list of conditions and the following disclaimer in the 33 | documentation and/or other materials provided with the distribution. 34 | * Neither the name of cPanel, Inc. nor the 35 | names of its contributors may be used to endorse or promote products 36 | derived from this software without specific prior written permission. 37 | 38 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 39 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 40 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 41 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 42 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 43 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 44 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 45 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 46 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 47 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/Utils.pm: -------------------------------------------------------------------------------- 1 | package cPanel::PublicAPI::Utils; 2 | 3 | # Copyright (c) 2015, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | sub remove_trailing_newline { 33 | my $string = shift; 34 | $string =~ s/\r?\n$//g; 35 | return $string; 36 | } 37 | 38 | sub get_string_with_collapsed_trailing_eols { 39 | my @copy = @_; # this addresses 'Modification of a read-only value attempted at Cpanel/Accounting.pm ...' from $line =~ below 40 | my $txt; 41 | foreach my $line (@copy) { 42 | if ( ref $line eq 'ARRAY' ) { 43 | foreach my $subline ( @{$line} ) { 44 | $subline =~ s/[\r\n]+$//g; 45 | $txt .= $subline . "\n"; 46 | } 47 | } 48 | else { 49 | $line =~ s/[\r\n]+$//g; 50 | $txt .= $line . "\n"; 51 | } 52 | } 53 | return $txt; 54 | } 55 | 56 | 1; 57 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/CachedVersion.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI::WHM::CachedVersion - Allows for lookups of remote versions of cPanel & WHM. 6 | 7 | =head1 DESCRIPTION 8 | 9 | This module allows you to lookup the version of a remote instance of cPanel & WHM based off of the contents of /var/cpanel/accounting/cache, if the server is not stored there, it will perform the version call. 10 | 11 | /var/cpanel must exist in order for this to work, /var/cpanel/accounting and /var/cpanel/accounting/cache will be created if necessary. 12 | 13 | =head1 cached_version() 14 | 15 | This module consists of a single function - cPanel::PublicAPI::WHM::CachedVersion::cached_version(). It expects an already configured publicapi instance. 16 | 17 | Syntax: 18 | 19 | my $pubapi = cPanel::PublicAPI::WHM::CachedVersion->new( 'host' => 'somehost', 'user' => 'someuser', ... ); 20 | my $version = $pubapi->cached_version(); 21 | 22 | This will return a string containing the version of the cpanel/whm server being queried. 23 | 24 | =head1 Bugs 25 | 26 | see http://rt.cpan.org to report and view bugs 27 | 28 | =head1 License 29 | 30 | Copyright (c) 2015, cPanel, Inc. 31 | All rights reserved. 32 | http://cpanel.net 33 | 34 | Redistribution and use in source and binary forms, with or without 35 | modification, are permitted provided that the following conditions are met: 36 | * Redistributions of source code must retain the above copyright 37 | notice, this list of conditions and the following disclaimer. 38 | * Redistributions in binary form must reproduce the above copyright 39 | notice, this list of conditions and the following disclaimer in the 40 | documentation and/or other materials provided with the distribution. 41 | * Neither the name of cPanel, Inc. nor the 42 | names of its contributors may be used to endorse or promote products 43 | derived from this software without specific prior written permission. 44 | 45 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 46 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 47 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 48 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 49 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 50 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 51 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 52 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 54 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 | -------------------------------------------------------------------------------- /t/lib/PubApiTest.pm: -------------------------------------------------------------------------------- 1 | package PubApiTest; 2 | 3 | use cPanel::PublicAPI; 4 | 5 | @PubApiTest::ISA = qw( cPanel::PublicAPI ); 6 | 7 | use strict; 8 | use warnings; 9 | use Test::More; 10 | 11 | # This is used to specify what a specific call be using 12 | our $test_config = {}; 13 | 14 | # Used to test the actual input to api_request 15 | sub api_request { 16 | my ( $self, $service, $uri, $method, $formdata ) = @_; 17 | 18 | undef $self->{'error'}; 19 | if ( defined $test_config->{'badcall'} ) { 20 | my $badcall_return; 21 | if ( $test_config->{'badcall'} eq 'whmapi' ) { 22 | $badcall_return = '{"error":"Unknown App Requested: asdf"}'; 23 | } 24 | elsif ( $test_config->{'badcall'} eq 'cpanelapi2' ) { 25 | $badcall_return = '{"cpanelresult":{"apiversion":2,"error":"Could not find function \'test\' in module \'Test\'","func":"test","module":"Test"}}'; 26 | } 27 | elsif ( $test_config->{'badcall'} eq 'cpanelapi1' ) { 28 | $badcall_return = '{"apiversion":"1","type":"event","module":"Test","func":"test","source":"module","data":{"result":""},"event":{"reason":"Test::test() failed: Undefined subroutine &Cpanel::Test::Test_test called at (eval 21) line 1.\n","result":0}}'; 29 | } 30 | return 0, 'failed', \$badcall_return; 31 | } 32 | 33 | is( $service, $test_config->{'service'}, 'Service is correct for ' . $test_config->{'call'} ); 34 | is( $uri, $test_config->{'uri'}, 'URI is correct for ' . $test_config->{'call'} ); 35 | is( $method, $test_config->{'method'}, 'Method is correct for ' . $test_config->{'call'} ); 36 | if ( exists $test_config->{'test_formdata'} && $test_config->{'test_formdata'} eq 'hash' ) { 37 | is_deeply( $formdata, $test_config->{'formdata'}, 'Formdata is correct for ' . $test_config->{'call'} ); 38 | } 39 | elsif ( exists $test_config->{'test_formdata'} && $test_config->{'test_formdata'} eq 'string' ) { 40 | is( $formdata, $test_config->{'formdata'}, 'Fromdata is correct for ' . $test_config->{'call'} ); 41 | } 42 | 43 | my $return_format = 'string'; 44 | if ( $uri =~ /\/json-api\// ) { 45 | $return_format = 'json'; 46 | } 47 | elsif ( $uri =~ /\/xml-api\// ) { 48 | $return_format = 'xml'; 49 | } 50 | is( $return_format, $test_config->{'return_format'}, 'Serialization format correct for ' . $test_config->{'call'} ); 51 | 52 | my $return; 53 | if ( $return_format eq 'json' ) { 54 | $return = '{"something":"somethinglese"}'; 55 | } 56 | elsif ( $return_format eq 'xml' ) { 57 | $return = 'somethingelse'; 58 | } 59 | else { 60 | $return = 'some data goes here'; 61 | } 62 | return '1', 'ok', \$return; 63 | } 64 | 65 | 1; 66 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/CachedVersion.pm: -------------------------------------------------------------------------------- 1 | package cPanel::PublicAPI::WHM::CachedVersion; 2 | 3 | # Copyright (c) 2015, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use cPanel::PublicAPI (); 33 | 34 | our $VERSION = '2.3'; 35 | 36 | package cPanel::PublicAPI; 37 | 38 | use cPanel::PublicAPI::WHM::Legacy (); 39 | 40 | our $basedir = '/var/cpanel/accounting'; 41 | our $cachedir = '/var/cpanel/accounting/cache'; 42 | our $cachettl = 3600; #one hour 43 | 44 | sub check_dirs { 45 | foreach my $dir ( $basedir, $cachedir ) { 46 | if ( !-e $dir ) { 47 | mkdir( $dir, 0700 ); 48 | } 49 | } 50 | } 51 | 52 | sub cached_version { 53 | my $self = shift; 54 | my $ttl = shift || $cachettl; 55 | my $version; 56 | 57 | $self->check_dirs(); 58 | 59 | my $file = ( $self->{'ip'} || $self->{'host'} ); 60 | 61 | if ( !$file ) { 62 | return; 63 | } 64 | 65 | $file =~ s/\///g; 66 | my $fullfile = $cachedir . '/' . $file; 67 | my $now = time(); 68 | my $mtime = ( stat($fullfile) )[9]; 69 | 70 | if ( $mtime && ( $mtime + $ttl ) > $now && $mtime < $now ) { 71 | if ( open( my $cache_fh, '<', $fullfile ) ) { 72 | my $fileversion = readline($cache_fh); 73 | if ( $fileversion =~ /^(\d+\.\d+\.\d+)/ ) { 74 | $version = $1; 75 | } 76 | close($cache_fh); 77 | } 78 | } 79 | 80 | if ($version) { return $version; } 81 | 82 | $version = $self->version(); 83 | 84 | if ($version) { 85 | if ( open( my $cache_fh, '>', $fullfile ) ) { 86 | print {$cache_fh} $version; 87 | close($cache_fh); 88 | } 89 | } 90 | 91 | return $version; 92 | } 93 | 94 | 1; 95 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/Legacy.pm: -------------------------------------------------------------------------------- 1 | package cPanel::PublicAPI::Legacy; 2 | 3 | # Copyright (c) 2015, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use cPanel::PublicAPI (); 33 | 34 | our $VERSION = '2.3'; 35 | 36 | package cPanel::PublicAPI; 37 | 38 | use cPanel::PublicAPI::WHM (); 39 | 40 | sub _modpkg { 41 | my $self = shift; 42 | my $op = shift; 43 | my $count = 0; 44 | my @OPTS = ('nohtml=1'); 45 | if ( $op eq 'edit' ) { push @OPTS, 'edit=yes'; } 46 | return $self->simple_get_whmreq( '/scripts/addpkg', \@_, [ 'name', 'hasshell', 'bwlimit', 'quota', 'ip', 'cgi', 'cpmod', 'maxftp', 'maxsql', 'maxpop', 'maxlst', 'maxsub', 'maxpark', 'maxaddon', 'featurelist', 'language' ], \@OPTS ); 47 | } 48 | 49 | sub addpkg { 50 | my $self = shift; 51 | return $self->_modpkg( 'add', @_ ); 52 | } 53 | 54 | sub editpkg { 55 | my $self = shift; 56 | return $self->_modpkg( 'edit', @_ ); 57 | } 58 | 59 | sub killpkg { 60 | my $self = shift; 61 | return $self->simple_get_whmreq( '/scripts/killpkg', \@_, ['pkg'], ['nohtml=1'] ); 62 | } 63 | 64 | sub suspend { 65 | my $self = shift; 66 | return $self->simple_get_whmreq( '/scripts/remote_suspend', \@_, ['user'] ); 67 | } 68 | 69 | sub unsuspend { 70 | my $self = shift; 71 | return $self->simple_get_whmreq( '/scripts/remote_unsuspend', \@_, ['user'] ); 72 | } 73 | 74 | sub killacct { 75 | my $self = shift; 76 | return $self->simple_get_whmreq( '/scripts/killacct', \@_, ['user'], ['nohtml=1'] ); 77 | } 78 | 79 | sub showversion { 80 | my $self = shift; 81 | return $self->simple_get_whmreq( '/scripts2/showversion', \@_ ); 82 | } 83 | 84 | sub version { 85 | my $self = shift; 86 | return $self->simple_get_whmreq( '/scripts2/showversion', \@_ ); 87 | } 88 | 89 | sub showhostname { 90 | my $self = shift; 91 | return $self->simple_get_whmreq( '/scripts2/gethostname', \@_ ); 92 | } 93 | 94 | sub createacct { 95 | my $self = shift; 96 | return $self->simple_get_whmreq( '/scripts/wwwacct', \@_, [ 'domain', 'username', 'password', 'plan', 'language' ], ['nohtml=1'] ); 97 | } 98 | 99 | sub listpkgs { 100 | my $self = shift; 101 | my $req = $self->simple_get_whmreq( '/scripts/remote_listpkg', \@_ ); 102 | my %PKGS; 103 | foreach ( split( /\n/, $req ) ) { 104 | my ( $pkg, $contents ) = split( /=/, $_ ); 105 | my @CONTENTS = split( /\,/, $contents ); 106 | $PKGS{$pkg} = \@CONTENTS; 107 | } 108 | return wantarray ? %PKGS : \%PKGS; 109 | } 110 | 111 | sub listaccts { 112 | my $self = shift; 113 | my $req = $self->simple_get_whmreq( '/scripts2/listaccts', \@_, [], ['nohtml=1&viewall=1'] ); 114 | my %ACCTS; 115 | foreach ( split( /\n/, $req ) ) { 116 | next if $_ !~ /=/; 117 | my ( $acct, $contents ) = split( /=/, $_ ); 118 | my @CONTENTS = split( /\,/, $contents ); 119 | $ACCTS{$acct} = \@CONTENTS; 120 | } 121 | return wantarray ? %ACCTS : \%ACCTS; 122 | } 123 | 1; 124 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM.pm: -------------------------------------------------------------------------------- 1 | package cPanel::PublicAPI::WHM; 2 | 3 | # Copyright (c) 2015, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use cPanel::PublicAPI (); 33 | 34 | our $VERSION = 1.0; 35 | 36 | package cPanel::PublicAPI; 37 | 38 | sub simple_get_whmreq { 39 | my ( $self, $uri, $argref, $argnameref, $opts ) = @_; 40 | 41 | $self->_init() if !exists $cPanel::PublicAPI::CFG{'init'}; 42 | 43 | $self->debug("simple_get_whmreq: ( $self, $uri, $argref, $argnameref, $opts )\n") if $self->{'debug'}; 44 | 45 | my $count = 0; 46 | if ( !$opts || !ref $opts ) { $opts = []; } 47 | if ( ref $argnameref ) { 48 | foreach my $arg ( @{$argnameref} ) { 49 | push @{$opts}, $cPanel::PublicAPI::CFG{'uri_encoder_func'}->($arg) . '=' . ( $cPanel::PublicAPI::CFG{'uri_encoder_func'}->( $argref->[$count] ) || '' ); 50 | $count++; 51 | } 52 | } 53 | my $page_ref = $self->whmreq( $uri . '?' . join( '&', @{$opts} ) ); 54 | if ( $self->{'error'} ) { return ''; } 55 | return $page_ref; 56 | } 57 | 58 | sub simple_post_whmreq { 59 | my ( $self, $uri, $argref, $argnameref, $opts ) = @_; 60 | 61 | $self->_init() if !exists $cPanel::PublicAPI::CFG{'init'}; 62 | 63 | $self->debug("simple_post_whmreq: ( $self, $uri, $argref, $argnameref, $opts )") if $self->{'debug'}; 64 | 65 | my $count = 0; 66 | if ( !$opts || !ref $opts ) { $opts = []; } 67 | if ( ref $argnameref ) { 68 | foreach my $arg ( @{$argnameref} ) { 69 | push @{$opts}, $cPanel::PublicAPI::CFG{'uri_encoder_func'}->($arg) . '=' . $cPanel::PublicAPI::CFG{'uri_encoder_func'}->( $argref->[$count] ); 70 | $count++; 71 | } 72 | } 73 | my $page_ref = $self->whmreq( $uri, 'POST', join( '&', @{$opts} ) ); 74 | if ( $self->{'error'} ) { return ''; } 75 | return $page_ref; 76 | } 77 | 78 | sub whmreq { 79 | my $self = shift; 80 | my $uri = shift; 81 | my $method = shift || 'GET'; 82 | my $formdata = shift; 83 | if ( $method eq 'GET' && $uri =~ /\?/ ) { 84 | ( $uri, $formdata ) = split( /\?/, $uri ); 85 | } 86 | 87 | $self->debug("whmreq: ( $self, $uri, $method, $formdata )\n") if $self->{'debug'}; 88 | 89 | my ( $status, $statusmsg, $data ) = $self->api_request( 'whostmgr', $uri, $method, $formdata ); 90 | return wantarray ? split( /\r?\n/, $$data ) : $$data; 91 | } 92 | 93 | sub api1 { #Cpanel::Accounting compat 94 | my $self = shift; 95 | my $user = shift; 96 | my $module = shift; 97 | my $func = shift; 98 | return $self->cpanel_api1_request( 'whostmgr', { 'user' => $user, 'module' => $module, 'func' => $func }, \@_, 'xml' ); 99 | } 100 | 101 | sub api2 { #Cpanel::Accounting compat 102 | my $self = shift; 103 | my $user = shift; 104 | my $module = shift; 105 | my $func = shift; 106 | return $self->cpanel_api2_request( 'whostmgr', { 'user' => $user, 'module' => $module, 'func' => $func }, {@_}, 'xml' ); 107 | } 108 | 109 | 1; 110 | -------------------------------------------------------------------------------- /t/05-api-query_tokens.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright 2017, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use strict; 33 | use warnings; 34 | 35 | use Test::More; # last test to print 36 | 37 | use cPanel::PublicAPI (); 38 | 39 | my @getpwuid = getpwuid($>); 40 | my $homedir = $getpwuid[7]; 41 | my $user = $getpwuid[0]; 42 | 43 | if ( !-d '/usr/local/cpanel' ) { 44 | plan skip_all => 'This test requires that cPanel and WHM are installed on a server'; 45 | } 46 | 47 | if ( !-e $homedir . '/.accesshash' ) { 48 | plan skip_all => 'This test requires that an account hash is defined (see "Setup Remote Access Keys" in WHM)'; 49 | } 50 | 51 | check_cpanel_version(63) or plan skip_all => 'This test requires cPanel version 64 or higher'; 52 | 53 | my $pubapi = cPanel::PublicAPI->new( 'ssl_verify_mode' => 0 ); 54 | if ( !-e '/var/cpanel/users/papiunit' ) { 55 | plan tests => 5; 56 | my $password = generate_password(); 57 | my $res = $pubapi->whm_api( 58 | 'createacct', 59 | { 60 | 'username' => 'papiunit', 61 | 'password' => $password, 62 | 'domain' => 'cpanel-public-api-test.acct', 63 | 'reseller' => 1, 64 | } 65 | ); 66 | like( $res->{'metadata'}->{'reason'}, qr/Account Creation Ok/, 'Test account created' ); 67 | 68 | _test_api_token_as_reseller( 'papiunit', $password ); 69 | 70 | $res = $pubapi->whm_api( 71 | 'removeacct', 72 | { 73 | 'user' => 'papiunit', 74 | } 75 | ); 76 | like( $res->{'metadata'}->{'reason'}, qr/papiunit account removed/, 'Test Account Removed' ); 77 | } 78 | else { 79 | plan skip_all => 'Unable to create test account. It already exists'; 80 | } 81 | 82 | sub _test_api_token_as_reseller { 83 | my ( $reseller, $password ) = @_; 84 | 85 | # Create the API Token 86 | my $reseller_api = cPanel::PublicAPI->new( 'user' => $reseller, 'pass' => $password, 'ssl_verify_mode' => 0 ); 87 | my $res = $reseller_api->whm_api( 'api_token_create', { 'token_name' => 'my_token' } ); 88 | ok( $res->{'metadata'}->{'result'}, 'Successfully called api_token_create API call as reseller' ); 89 | my $plaintext_token = $res->{'data'}->{'token'}; 90 | 91 | my $pub_api_with_token = cPanel::PublicAPI->new( 'user' => $reseller, 'api_token' => 'this is so wrong', 'ssl_verify_mode' => 0 ); 92 | 93 | eval { $pub_api_with_token->whm_api('loadavg') }; 94 | ok( $@, 'API call fails with wrong API token' ); 95 | 96 | $pub_api_with_token->api_token($plaintext_token); 97 | $res = $pub_api_with_token->whm_api('loadavg'); 98 | ok( defined $res->{'one'}, 'API call successfully made using the correct token' ); 99 | } 100 | 101 | sub generate_password { 102 | my @chars = ( 'A' .. 'Z', 'a' .. 'z', '0' .. '9' ); 103 | my $pass = ''; 104 | foreach ( 1 .. 32 ) { 105 | $pass .= $chars[ int rand @chars ]; 106 | } 107 | return $pass; 108 | } 109 | 110 | sub check_cpanel_version { 111 | my $min_version = shift; 112 | open( my $version_fh, '<', '/usr/local/cpanel/version' ) || return 0; 113 | my $version = do { local $/; <$version_fh> }; 114 | chomp $version; 115 | my ( $maj, $min, $rev, $sup ) = split /[\._]/, $version; 116 | return 1 if $min >= $min_version; 117 | return 0; 118 | } 119 | 120 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI::WHM - Legacy interface for querying WHM. 6 | 7 | NOTE: This module is provided for legacy purposes, L should be used instead 8 | 9 | =head1 DESCRIPTION 10 | 11 | This module provides legacy compatibility support between L and Cpanel::Accounting (distributed with cPanel). 12 | This should never be used unless there is a very good reason to use it (such as having a script that uses Cpanel::Accounting). 13 | 14 | =head1 functions 15 | 16 | =head2 C 17 | 18 | This function makes a HTTP GET query to WHM, an equivalent function within L is C. 19 | This function uses two arrays to specify arguments to be passed to a specific URI. 20 | This means that you would need to ensure that they both have the key/pair values in the same place in each array, f.ex: 21 | 22 | $argref = ['value1', 'value2', 'value3']; 23 | $argnameref = ['key1', 'key2', 'key3']; 24 | 25 | would be be specifying: 26 | 27 | key1=value1&key2=value2&key3=value3 28 | 29 | to be passed to the specified URI. 30 | 31 | Arguments 32 | 33 | =over 34 | 35 | =item * $uri - The URI you to be queried. 36 | 37 | =item * $argref - An array reference containing the values to be passed. 38 | 39 | =item * $argnameref - An array reference containing the keys to be passed. 40 | 41 | =item * $opts - An array reference containing strings like 'key1=value1' to be passed to the URI. 42 | 43 | =back 44 | 45 | This will return a scalar reference of the data returned by cpsrvd. 46 | 47 | =head2 C 48 | 49 | This function makes a HTTP POST query to WHM, an equivalent function within L is C. 50 | This function uses two arrays to specify arguments to be passed to a specific URI. 51 | This means that you would need to ensure that they both have the key/pair values in the same place in each array, f.ex: 52 | 53 | $argref = ['value1', 'value2', 'value3']; 54 | $argnameref = ['key1', 'key2', 'key3']; 55 | 56 | would be be specifying: 57 | 58 | key1=value1&key2=value2&key3=value3 59 | 60 | to be passed to the specified URI. 61 | 62 | Arguments 63 | 64 | =over 65 | 66 | =item * $uri - The URI you to be queried. 67 | 68 | =item * $argref - An array reference containing the values to be passed. 69 | 70 | =item * $argnameref - An array reference containing the keys to be passed. 71 | 72 | =item * $opts - An array reference containing strings like 'key1=value1' to be passed to the URI. 73 | 74 | =back 75 | 76 | This will return a scalar containing the data returned by cpsrvd. 77 | 78 | =head2 C 79 | 80 | This function is used to querying WHM with either GET or POST data. 81 | 82 | =over 83 | 84 | =item * $uri - The URI to be queried. 85 | 86 | =item * $method - The method of querying the URI (either GET or POST). 87 | 88 | =item * $formdata - The data to be passed to the URI formatted as formdata (e.g. 'key1=value1&key2=value2'). 89 | 90 | =back 91 | 92 | =head2 C 93 | 94 | This function is used to query cPanel's API1. This will return the XML response from the XML API's cpanel call. 95 | 96 | =over 97 | 98 | =item * $user - The user to execute an API call for. 99 | 100 | =item * $module - The module of the API call to be executed. 101 | 102 | =item * $func - The name of the API call to be executed. 103 | 104 | =item * @params - An array containing the parameters for the API call. 105 | 106 | =back 107 | 108 | =head2 C 109 | 110 | This function is used to query cPanel's API1. This will return the XML response from the XML API's cpanel call. 111 | 112 | =over 113 | 114 | =item * $user - The user to execute an API call for. 115 | 116 | =item * $module - The module of the API call to be executed. 117 | 118 | =item * $func - The name of the API call to be executed. 119 | 120 | =item * %params - An hash containing the parameters for the API call. 121 | 122 | =back 123 | 124 | =head1 Bugs 125 | 126 | see http://rt.cpan.org to report and view bugs 127 | 128 | =head1 License 129 | 130 | Copyright (c) 2015, cPanel, Inc. 131 | All rights reserved. 132 | http://cpanel.net 133 | 134 | Redistribution and use in source and binary forms, with or without 135 | modification, are permitted provided that the following conditions are met: 136 | * Redistributions of source code must retain the above copyright 137 | notice, this list of conditions and the following disclaimer. 138 | * Redistributions in binary form must reproduce the above copyright 139 | notice, this list of conditions and the following disclaimer in the 140 | documentation and/or other materials provided with the distribution. 141 | * Neither the name of cPanel, Inc. nor the 142 | names of its contributors may be used to endorse or promote products 143 | derived from this software without specific prior written permission. 144 | 145 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 146 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 147 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 148 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 149 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 150 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 151 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 152 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 153 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 154 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 155 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/DNS.pm: -------------------------------------------------------------------------------- 1 | package cPanel::PublicAPI::DNS; 2 | 3 | # Copyright (c) 2015, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use cPanel::PublicAPI (); 33 | 34 | our $VERSION = '2.3'; 35 | 36 | package cPanel::PublicAPI; 37 | 38 | use cPanel::PublicAPI::WHM (); 39 | use cPanel::PublicAPI::Utils (); 40 | 41 | sub addtocluster { 42 | my $self = shift; 43 | my $page = $self->simple_post_whmreq( '/cgi/trustclustermaster.cgi', \@_, [ 'user', 'clustermaster', 'pass', 'version' ], ['recurse=0'] ); 44 | if ( $page =~ /has been established/i ) { 45 | return 1; 46 | } 47 | return; 48 | } 49 | 50 | sub getzone_local { 51 | my $self = shift; 52 | return $self->simple_post_whmreq( '/scripts2/getzone_local', \@_, [ 'zone', 'dnsuniqid' ] ); 53 | } 54 | 55 | sub getzones_local { 56 | my $self = shift; 57 | return $self->simple_post_whmreq( '/scripts2/getzones_local', \@_, [ 'zones', 'dnsuniqid' ] ); 58 | } 59 | 60 | sub getallzones_local { 61 | my $self = shift; 62 | return $self->simple_post_whmreq( '/scripts2/getallzones_local', \@_, ['dnsuniqid'] ); 63 | } 64 | 65 | sub cleandns_local { 66 | my $self = shift; 67 | return $self->simple_get_whmreq( '/scripts2/cleandns_local', \@_, ['dnsuniqid'] ); 68 | } 69 | 70 | sub getips_local { 71 | my $self = shift; 72 | return cPanel::PublicAPI::Utils::get_string_with_collapsed_trailing_eols( split( /\n/, ( $self->simple_get_whmreq( '/scripts2/getips_local', \@_, ['dnsuniqid'] ) ) ) ); 73 | } 74 | 75 | sub getpath_local { 76 | my $self = shift; 77 | return cPanel::PublicAPI::Utils::get_string_with_collapsed_trailing_eols( split( /\n/, ( $self->simple_get_whmreq( '/scripts2/getpath_local', \@_, ['dnsuniqid'] ) ) ) ); 78 | } 79 | 80 | sub removezone_local { 81 | my $self = shift; 82 | return $self->simple_post_whmreq( '/scripts2/removezone_local', \@_, [ 'zone', 'dnsuniqid' ] ); 83 | } 84 | 85 | sub removezones_local { 86 | my $self = shift; 87 | return $self->simple_post_whmreq( '/scripts2/removezones_local', \@_, [ 'zones', 'dnsuniqid' ] ); 88 | } 89 | 90 | sub reloadzones_local { 91 | my $self = shift; 92 | return $self->simple_post_whmreq( '/scripts2/reloadzones_local', \@_, [ 'dnsuniqid', 'zone' ] ); # backcompat 93 | } 94 | 95 | sub reloadbind_local { 96 | my $self = shift; 97 | return $self->simple_post_whmreq( '/scripts2/reloadbind_local', \@_, [ 'dnsuniqid', 'zone' ] ); # backcompat 98 | } 99 | 100 | sub reconfigbind_local { 101 | my $self = shift; 102 | return $self->simple_post_whmreq( '/scripts2/reconfigbind_local', \@_, [ 'dnsuniqid', 'zone' ] ); # backcompat 103 | } 104 | 105 | sub quickzoneadd_local { 106 | my $self = shift; 107 | return $self->simple_post_whmreq( '/scripts2/quickzoneadd_local', \@_, [ 'zone', 'zonedata', 'dnsuniqid' ] ); 108 | } 109 | 110 | sub savezone_local { 111 | my $self = shift; 112 | return $self->simple_post_whmreq( '/scripts2/savezone_local', \@_, [ 'zone', 'zonedata', 'dnsuniqid' ] ); 113 | } 114 | 115 | sub synczones_local { 116 | my ( $self, $formdata, $dnsuniqid ) = @_; 117 | cPanel::PublicAPI::_init() if !exists $cPanel::PublicAPI::CFG{'init'}; 118 | $formdata =~ s/\&$//g; # formdata must come pre encoded. 119 | $formdata .= '&dnsuniqid=' . $cPanel::PublicAPI::CFG{'uri_encoder_func'}->($dnsuniqid); 120 | my $page = join( "\n", $self->whmreq( '/scripts2/synczones_local', 'POST', $formdata ) ); 121 | return if $self->{'error'}; 122 | return $page; 123 | } 124 | 125 | sub addzoneconf_local { 126 | my $self = shift; 127 | return $self->simple_get_whmreq( '/scripts2/addzoneconf_local', \@_, [ 'zone', 'dnsuniqid' ] ); 128 | } 129 | 130 | sub getzonelist_local { 131 | my $self = shift; 132 | return split( /\n/, $self->simple_get_whmreq( '/scripts2/getzonelist_local', \@_, ['dnsuniqid'] ) ); 133 | } 134 | 135 | sub zoneexists_local { 136 | my $self = shift; 137 | my $exists = cPanel::PublicAPI::Utils::remove_trailing_newline( $self->simple_post_whmreq( '/scripts2/zoneexists_local', \@_, [ 'zone', 'dnsuniqid' ] ) ); 138 | $exists =~ s/[\r\n]//g; 139 | if ( $exists eq '1' ) { 140 | return 1; 141 | } 142 | return 0; 143 | } 144 | -------------------------------------------------------------------------------- /t/06-api-tokens.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright 2017, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use strict; 33 | use warnings; 34 | 35 | use Test::More; # last test to print 36 | 37 | use cPanel::PublicAPI (); 38 | 39 | check_cpanel_version(79) or plan skip_all => 'This test requires cPanel version 80 or higher'; 40 | 41 | my ($created_token, $token_name, $created_account); 42 | 43 | my $random_username; 44 | 45 | do { 46 | $random_username = 'papi' . substr( rand, 2, 8 ) . 'test'; 47 | } while -e "/var/cpanel/users/$random_username"; 48 | 49 | END { 50 | if ($created_token) { 51 | diag "Deleting temporary root WHM API token “$token_name” …"; 52 | system('/usr/local/cpanel/bin/whmapi1', 'api_token_revoke', "token_name=$token_name"); 53 | } 54 | 55 | if ($created_account) { 56 | diag "Deleting temporary cPanel account “$random_username” …"; 57 | system('/usr/local/cpanel/scripts/removeacct', '--force', $random_username); 58 | } 59 | } 60 | 61 | my @getpwuid = getpwuid($>); 62 | my $homedir = $getpwuid[7]; 63 | my $user = $getpwuid[0]; 64 | 65 | if ( !-d '/usr/local/cpanel' ) { 66 | plan skip_all => 'This test requires that cPanel and WHM are installed on a server'; 67 | } 68 | 69 | $token_name = 'papitest' . substr( rand, 2 ); 70 | 71 | diag "Creating temporary root WHM API token “$token_name” …"; 72 | my $out = `/usr/local/cpanel/bin/whmapi1 --output=json api_token_create token_name=$token_name`; 73 | die if $?; 74 | 75 | # Avoid the need for a formal JSON parser. 76 | $out =~ m<"token":"(.+?)"> or die "No API token in output!\n$out"; 77 | 78 | $created_token = $1; 79 | 80 | my $pubapi = cPanel::PublicAPI->new( usessl => 0, user => 'root', api_token => $created_token ); 81 | 82 | plan tests => 6; 83 | 84 | my $password = generate_password(); 85 | 86 | diag "Creating temporary reseller “$random_username” …"; 87 | 88 | my $res = $pubapi->whm_api( 89 | 'createacct', 90 | { 91 | 'username' => $random_username, 92 | 'password' => $password, 93 | 'domain' => "$random_username.tld", 94 | 'reseller' => 1, 95 | } 96 | ); 97 | like( $res->{'metadata'}->{'reason'}, qr/Account Creation Ok/, 'Test account created' ); 98 | 99 | $created_account = 1; 100 | 101 | _test_api_token_as_reseller( $random_username, $password ); 102 | 103 | _test_cpanel_api_token( $random_username, $password ); 104 | 105 | diag "Deleting temporary reseller “$random_username” …"; 106 | 107 | $res = $pubapi->whm_api( 108 | 'removeacct', 109 | { 110 | 'user' => $random_username, 111 | } 112 | ); 113 | like( $res->{'metadata'}->{'reason'}, qr/\Q$random_username\E/, 'Test Account Removed' ); 114 | 115 | $created_account = 0; 116 | 117 | #---------------------------------------------------------------------- 118 | 119 | sub _test_api_token_as_reseller { 120 | my ( $reseller, $password ) = @_; 121 | 122 | # Create the API Token 123 | my $reseller_api = cPanel::PublicAPI->new( 'user' => $reseller, 'pass' => $password, 'ssl_verify_mode' => 0 ); 124 | my $res = $reseller_api->whm_api( 'api_token_create', { 'token_name' => 'my_token' } ); 125 | ok( $res->{'metadata'}->{'result'}, 'Successfully called api_token_create API call as reseller' ); 126 | my $plaintext_token = $res->{'data'}->{'token'}; 127 | 128 | my $pub_api_with_token = cPanel::PublicAPI->new( 'user' => $reseller, 'api_token' => 'this is so wrong', 'ssl_verify_mode' => 0 ); 129 | 130 | eval { $pub_api_with_token->whm_api('loadavg') }; 131 | ok( $@, 'API call fails with wrong API token' ); 132 | 133 | $pub_api_with_token->api_token($plaintext_token); 134 | $res = $pub_api_with_token->whm_api('loadavg'); 135 | ok( defined $res->{'one'}, 'API call successfully made using the correct token' ); 136 | } 137 | 138 | sub _test_cpanel_api_token { 139 | my ( $username, $password ) = @_; 140 | 141 | # Unfortunately, for now we can’t actually create the token via this module. 142 | my $out = `/usr/local/cpanel/bin/uapi --output=json --user=$username Tokens create_full_access name=fulltoken`; 143 | 144 | $out =~ m<"token":"(.+?)"> or die "No API token in response: ($out)"; 145 | my $token = $1; 146 | 147 | # Create the API Token 148 | my $api = cPanel::PublicAPI->new( 'user' => $username, api_token => $token, usessl => 0 ); 149 | my $res = $api->cpanel_api2_request( 'cpanel', { module => 'Email', func => 'listpops' } ); 150 | ok( $res->{'cpanelresult'}{'event'}{'result'}, 'Successfully called API2 Email::listpops with token' ); 151 | } 152 | 153 | sub generate_password { 154 | my @chars = ( 'A' .. 'Z', 'a' .. 'z', '0' .. '9' ); 155 | my $pass = ''; 156 | foreach ( 1 .. 32 ) { 157 | $pass .= $chars[ int rand @chars ]; 158 | } 159 | return $pass; 160 | } 161 | 162 | sub check_cpanel_version { 163 | my $min_version = shift; 164 | open( my $version_fh, '<', '/usr/local/cpanel/version' ) || return 0; 165 | my $version = do { local $/; <$version_fh> }; 166 | chomp $version; 167 | my ( $maj, $min, $rev, $sup ) = split /[\._]/, $version; 168 | return 1 if $min >= $min_version; 169 | return 0; 170 | } 171 | 172 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/DNS.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI::WHM::DNS - A module for interacting with WHM's DNS clustering system. 6 | 7 | =head1 DESCRIPTION 8 | 9 | This module is intended as a client for querying WHM's DNS clustering system. Unless you are specifically looking to write your own interaction with cPanel's DNS system, you should never need to use this module, rather the DNS functions within cPanel's XML-API should do what you are looking for: L 10 | 11 | =head1 functions 12 | 13 | The functions contained within this module share a similiar naming scheme for the variables used within, please consult the list below when figuring out what each function does. 14 | 15 | =over 16 | 17 | =item * $zone - The name of the domain to be used. 18 | 19 | =item * $dnsuniqid - A Unique string used to identify uniquely (suggested: 32 character alphanumeric) 20 | 21 | =item * $zones - A pipe seperated list of domains. 22 | 23 | =item * $zonedata - The contents of a zone file, usually used for sending changes of a zone to another system. 24 | 25 | =back 26 | 27 | =head2 C 28 | 29 | Add a machine to a DNS cluster. 30 | 31 | Call specific parameters: 32 | 33 | =over 34 | 35 | =item * $clustermaster - The IP of the machine being added to the cluster. 36 | 37 | =item * $user - The user to authenticate DNS requests as. 38 | 39 | =item * $pass - The accesshash or API token to authenticate DNS requests with 40 | 41 | =item * $version - The version of cPanel/WHM of the machine being added to the cluster 42 | 43 | =back 44 | 45 | Syntax: 46 | 47 | $pubapi->addtocluster( $user, $clustermaster, $accesshash, $version ) 48 | 49 | =head2 C 50 | 51 | Get the contents of a zone file. 52 | 53 | Syntax: 54 | 55 | $pubapi->getzone_local( $zone, $dnsuniqid ) 56 | 57 | =head2 C 58 | 59 | Get the contents of multiple zone files, this will be split up as: 60 | 61 | cpdnszone-%URI ENCODED ZONENAME%=%URI encoded version of zone file%&cpdnszone... 62 | 63 | for each zone in the response 64 | 65 | Syntax: 66 | 67 | $pubapi->getzones_local( $zones, $dnsuniqid ) 68 | 69 | =head2 C 70 | 71 | Like getzones_local, but will return all zones in a cluster. 72 | 73 | Syntax: 74 | 75 | $pubapi->getallzones_local( $dnsuniqid ) 76 | 77 | =head2 C 78 | 79 | Clean up any old or unused DNS zones from named.conf. 80 | 81 | Syntax: 82 | 83 | $pubapi->cleandns_local( $dnsuniqid ) 84 | 85 | =head2 C 86 | 87 | Get a list of extra IPs available on a system, response will be formated as: 88 | 89 | $ip:$netmask:$broadcast 90 | 91 | Syntax: 92 | 93 | $pubapi->getips_local( $dnsuniqid ) 94 | 95 | =head2 C 96 | 97 | Returns a newline separated list containing all the machines that this machine is clustered with in the following format: 98 | 99 | $hostname $remote_host 100 | 101 | Syntax: 102 | 103 | $pubapi->getpath_local( $dnsuniqid ) 104 | 105 | =head2 C 106 | 107 | Remove a DNS zone. 108 | 109 | Syntax: 110 | 111 | $pubapi->removezone_local( $zone, $dnsuniqid ) 112 | 113 | =head2 C 114 | 115 | Remove multiple DNS zones. 116 | 117 | Syntax: 118 | 119 | $pubapi->removezones_local( $zones, $dnsuniqid ) 120 | 121 | =head2 C 122 | 123 | Force bind to re-read zones files via the "rndc reload" command. 124 | 125 | Syntax: 126 | 127 | $pubapi->reloadzones_local( $dnsuniqid, $zones ) 128 | 129 | =head2 C 130 | 131 | Run the 'rndc reload' command. If no zones are specified, bind will reload everything. 132 | 133 | Syntax: 134 | 135 | $pubapi->reloadbind_local( $dnsuniqid, $zone ) 136 | 137 | =head2 C 138 | 139 | Run the 'rndc reconfig' command. 140 | 141 | Syntax: 142 | 143 | $pubapi->reconfigbind_local( $dnsuniqid, $zone ) 144 | 145 | =head2 C 146 | 147 | Add a new zone to a system. 148 | 149 | Syntax: 150 | 151 | $pubapi->quickzoneadd_local( $zone, $zonedata, $dnsuniqid ) 152 | 153 | =head2 C 154 | 155 | Update a zone file with the data specified in $zonedata. 156 | 157 | Syntax: 158 | 159 | $pubapi->savezone_local( $zone, $zonedata, $dnsuniqid ) 160 | 161 | =head2 C 162 | 163 | Send a dump of all zones and update zones when required. The zones are sent within the $formdata in the following format: 164 | 165 | cpdnszone-%URI ENCODED ZONENAME%=%URI encoded version of zone file%&cpdnszone... 166 | 167 | Syntax: 168 | 169 | $pubapi->synczones_local( $formdata, $dnsuniqid ) 170 | 171 | =head2 C 172 | 173 | Add a zone to the named.conf file. 174 | 175 | Syntax: 176 | 177 | $pubapi->addzoneconf_local( $zone, $dnsuniqid ) 178 | 179 | =head2 C 180 | 181 | Get a newline seperated list of the zones on a system. 182 | 183 | Syntax: 184 | 185 | $pubapi->getzonelist_local( $dnsuniqid ) 186 | 187 | =head2 C 188 | 189 | Return boolean value indicating whether a zone exists on a remote system or not. 190 | 191 | Syntax: 192 | 193 | $pubapi->zoneexists_local( $zone, $dnsuniqid ) 194 | 195 | =head1 Bugs 196 | 197 | see http://rt.cpan.org to report and view bugs 198 | 199 | =head1 License 200 | 201 | Copyright (c) 2015, cPanel, Inc. 202 | All rights reserved. 203 | http://cpanel.net 204 | 205 | Redistribution and use in source and binary forms, with or without 206 | modification, are permitted provided that the following conditions are met: 207 | * Redistributions of source code must retain the above copyright 208 | notice, this list of conditions and the following disclaimer. 209 | * Redistributions in binary form must reproduce the above copyright 210 | notice, this list of conditions and the following disclaimer in the 211 | documentation and/or other materials provided with the distribution. 212 | * Neither the name of cPanel, Inc. nor the 213 | names of its contributors may be used to endorse or promote products 214 | derived from this software without specific prior written permission. 215 | 216 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 217 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 218 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 219 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 220 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 221 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 222 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 223 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 224 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 225 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 226 | -------------------------------------------------------------------------------- /t/04-tfa-sessions.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright 2017, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use strict; 33 | use warnings; 34 | 35 | use Test::More; # last test to print 36 | 37 | use cPanel::PublicAPI (); 38 | 39 | my @getpwuid = getpwuid($>); 40 | my $homedir = $getpwuid[7]; 41 | my $user = $getpwuid[0]; 42 | 43 | if ( !-d '/usr/local/cpanel' ) { 44 | plan skip_all => 'This test requires that cPanel and WHM are installed on a server'; 45 | } 46 | 47 | if ( !-e $homedir . '/.accesshash' ) { 48 | plan skip_all => 'This test requires that an account hash is defined (see "Setup Remote Access Keys" in WHM)'; 49 | } 50 | 51 | check_cpanel_version() or plan skip_all => 'This test requires cPanel version 54 or higher'; 52 | 53 | eval { require MIME::Base32; require Digest::SHA; 1; } or do { 54 | plan skip_all => 'This test requires the MIME::Base32 and Digest::SHA modules'; 55 | }; 56 | unshift @INC, '/usr/local/cpanel'; 57 | require Cpanel::Security::Authn::TwoFactorAuth::Google; 58 | 59 | my $pubapi = check_api_access_and_config(); 60 | 61 | if ( !-e '/var/cpanel/users/papiunit' ) { 62 | my $password = generate_password(); 63 | my $res = $pubapi->whm_api( 64 | 'createacct', 65 | { 66 | 'username' => 'papiunit', 67 | 'password' => $password, 68 | 'domain' => 'cpanel-public-api-test.acct', 69 | 'reseller' => 1, 70 | } 71 | ); 72 | like( $res->{'metadata'}->{'reason'}, qr/Account Creation Ok/, 'Test account created' ); 73 | 74 | $res = $pubapi->whm_api( 75 | 'setacls', 76 | { 77 | 'reseller' => 'papiunit', 78 | 'acl-create-acct' => 1, 79 | } 80 | ); 81 | ok( $res->{'metadata'}->{'result'}, 'Assigned create-acct ACL successfully' ); 82 | 83 | _test_tfa_as_reseller( 'papiunit', $password ); 84 | 85 | $res = $pubapi->whm_api( 86 | 'removeacct', 87 | { 88 | 'user' => 'papiunit', 89 | } 90 | ); 91 | like( $res->{'metadata'}->{'reason'}, qr/papiunit account removed/, 'Test Account Removed' ); 92 | } 93 | else { 94 | plan skip_all => 'Unable to create test account. It already exists'; 95 | } 96 | 97 | done_testing(); 98 | 99 | sub _test_tfa_as_reseller { 100 | my ( $reseller, $password ) = @_; 101 | 102 | my $reseller_api = cPanel::PublicAPI->new( 'user' => $reseller, 'pass' => $password, 'ssl_verify_mode' => 0 ); 103 | my $res = $reseller_api->whm_api( 'twofactorauth_generate_tfa_config', {} ); 104 | ok( $res->{'metadata'}->{'result'}, 'Successfully called generate tfa config API call as reseller' ); 105 | 106 | my $tfa_secret = $res->{'data'}->{'secret'}; 107 | my $google_auth = Cpanel::Security::Authn::TwoFactorAuth::Google->new( { 'secret' => $tfa_secret, 'account_name' => '', 'issuer' => '' } ); 108 | $res = $reseller_api->whm_api( 109 | 'twofactorauth_set_tfa_config', 110 | { 111 | 'secret' => $tfa_secret, 112 | 'tfa_token' => $google_auth->generate_code(), 113 | } 114 | ); 115 | ok( $res->{'metadata'}->{'result'}, '2FA successfully configured for reseller' ); 116 | 117 | eval { $reseller_api->whm_api('loadavg') }; 118 | ok( $@, 'API calls fail without a 2FA session established' ); 119 | 120 | $reseller_api->establish_tfa_session( 'whostmgr', $google_auth->generate_code() ); 121 | $res = $reseller_api->whm_api('loadavg'); 122 | ok( defined $res->{'one'}, 'API call successfully made after establishing 2FA session' ); 123 | } 124 | 125 | sub generate_password { 126 | my @chars = ( 'A' .. 'Z', 'a' .. 'z', '0' .. '9' ); 127 | my $pass = ''; 128 | foreach ( 1 .. 32 ) { 129 | $pass .= $chars[ int rand @chars ]; 130 | } 131 | return $pass; 132 | } 133 | 134 | sub check_cpanel_version { 135 | open( my $version_fh, '<', '/usr/local/cpanel/version' ) || return 0; 136 | my $version = do { local $/; <$version_fh> }; 137 | chomp $version; 138 | my ( $maj, $min, $rev, $sup ) = split /[\._]/, $version; 139 | return 1 if $min >= 53; 140 | return 0; 141 | } 142 | 143 | sub check_api_access_and_config { 144 | 145 | open( my $config_fh, '<', '/var/cpanel/cpanel.config' ) || BAIL_OUT('Could not load /var/cpanel/cpanel.config'); 146 | my $securitypolicy_enabled = 0; 147 | my $securitypolicy_xml_api_enabled = 0; 148 | while ( my $line = readline($config_fh) ) { 149 | next if $line !~ /=/; 150 | chomp $line; 151 | my ( $key, $value ) = split( /=/, $line, 2 ); 152 | if ( $key eq 'SecurityPolicy::TwoFactorAuth' ) { 153 | $securitypolicy_enabled = 1 if $value; 154 | } 155 | elsif ( $key eq 'SecurityPolicy::xml-api' ) { 156 | $securitypolicy_xml_api_enabled = 1 if $value; 157 | } 158 | } 159 | 160 | plan skip_all => '2FA security policy is disabled on the server' if !$securitypolicy_enabled; 161 | plan skip_all => 'Security policies do not apply to API calls on the server' if !$securitypolicy_xml_api_enabled; 162 | 163 | my $pubapi = cPanel::PublicAPI->new( 'ssl_verify_mode' => 0 ); 164 | my $res = eval { $pubapi->whm_api('applist') }; 165 | if ($@) { 166 | plan skip_all => "Failed to verify API access as current user: $@"; 167 | } 168 | 169 | if ( exists $res->{'data'}->{'app'} && ref $res->{'data'}->{'app'} eq 'ARRAY' ) { 170 | return $pubapi if grep { $_ eq 'createacct' } @{ $res->{'data'}->{'app'} }; 171 | } 172 | 173 | plan skip_all => "Current user doesn't appear to have proper privileges"; 174 | } 175 | -------------------------------------------------------------------------------- /t/03-api-query.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Test::More; # last test to print 7 | 8 | use cPanel::PublicAPI (); 9 | 10 | my @getpwuid = getpwuid($>); 11 | my $homedir = $getpwuid[7]; 12 | my $user = $getpwuid[0]; 13 | 14 | if ( !-d '/usr/local/cpanel' ) { 15 | plan skip_all => 'This test requires that cPanel and WHM are installed on a server'; 16 | } 17 | 18 | if ( !-e $homedir . '/.accesshash' ) { 19 | plan skip_all => 'This test requires that an account hash is defined (see "Setup Remote Access Keys" in WHM)'; 20 | } 21 | 22 | # SSL tests 23 | my $pubapi = check_api_access(); 24 | 25 | isa_ok( $pubapi, 'cPanel::PublicAPI' ); 26 | 27 | my $res = $pubapi->api_request( 'whostmgr', '/xml-api/loadavg', 'GET', {} ); 28 | like( $$res, qr/\s*\d+\.\d+<\/one>\s*\d+\.\d+<\/five>\s*\d+\.\d+<\/fifteen>\s*<\/loadavg>*/, 'whm get no params' ); 29 | 30 | # Create the test regex for reuse 31 | my $createacct_regex = qr/.*is a reserved username.*<\/statusmsg>/; 32 | 33 | $res = $pubapi->api_request( 'whostmgr', '/xml-api/createacct', 'GET', { 'username' => 'test', 'domain' => 'test.com' } ); 34 | like( $$res, $createacct_regex, 'ssl whm get hash params' ); 35 | 36 | $res = $pubapi->api_request( 'whostmgr', '/xml-api/createacct', 'GET', 'username=test&domain=test.com' ); 37 | like( $$res, $createacct_regex, 'ssl whm get string params' ); 38 | 39 | $res = $pubapi->api_request( 'whostmgr', '/xml-api/createacct', 'POST', { 'username' => 'test', 'domain' => 'test.com' } ); 40 | like( $$res, $createacct_regex, 'ssl whm post hash params' ); 41 | 42 | $res = $pubapi->api_request( 'whostmgr', '/xml-api/createacct', 'POST', 'username=test&domain=test.com' ); 43 | like( $$res, $createacct_regex, 'ssl whm post string params' ); 44 | 45 | # Create account for cpanel & reseller testing 46 | 47 | if ( !-e '/var/cpanel/users/papiunit' ) { 48 | my $password = generate_password(); 49 | $res = $pubapi->api_request( 50 | 'whostmgr', 51 | '/xml-api/createacct', 52 | 'POST', 53 | { 54 | 'username' => 'papiunit', 55 | 'password' => $password, 56 | 'domain' => 'cpanel-public-api-test.acct', 57 | } 58 | ); 59 | 60 | like( $$res, qr/Account Creation Ok/, 'Test account created' ); 61 | 62 | # skip is not used here due to the other code contained within this block. 63 | if ( $$res =~ /Account Creation Ok/ ) { 64 | my $cp_pubapi = cPanel::PublicAPI->new( 65 | 'user' => 'papiunit', 66 | 'pass' => $password, 67 | 'ssl_verify_mode' => 0, 68 | ); 69 | isa_ok( $cp_pubapi, 'cPanel::PublicAPI' ); 70 | is( $cp_pubapi->{'operating_mode'}, 'session', 'Session operating mode is set properly when user/pass is used' ); 71 | ok( !defined $cp_pubapi->{'cookie_jars'}->{'cpanel'}, 'no cookies have been established for the cpanel service before the first query is made' ); 72 | ok( !defined $cp_pubapi->{'security_tokens'}->{'cpanel'}, 'no security_token has been set for the cpanel service before the first query is made' ); 73 | $res = $cp_pubapi->api_request( 'cpanel', '/xml-api/cpanel', 'GET', 'cpanel_xmlapi_module=StatsBar&cpanel_xmlapi_func=stat&display=diskusage' ); 74 | like( $$res, qr/StatsBar<\/module>/, 'ssl cpanel get string params' ); 75 | 76 | my $security_token = $cp_pubapi->{'security_tokens'}->{'cpanel'}; 77 | ok( $security_token, 'security token for cpanel has been set upon first request' ); 78 | $res = $cp_pubapi->api_request( 'cpanel', '/xml-api/cpanel', 'GET', { 'cpanel_xmlapi_module' => 'StatsBar', 'cpanel_xmlapi_func' => 'stat', 'display' => 'diskusage' } ); 79 | like( $$res, qr/StatsBar<\/module>/, 'ssl cpanel post hash params' ); 80 | is( $cp_pubapi->{'security_tokens'}->{'cpanel'}, $security_token, 'security_token was not changed when the second cpanel request was made' ); 81 | 82 | $res = $cp_pubapi->api_request( 'cpanel', '/xml-api/cpanel', 'POST', 'cpanel_xmlapi_module=StatsBar&cpanel_xmlapi_func=stat&display=diskusage' ); 83 | like( $$res, qr/StatsBar<\/module>/, 'ssl cpanel get string params' ); 84 | 85 | $res = $cp_pubapi->api_request( 'cpanel', '/xml-api/cpanel', 'POST', { 'cpanel_xmlapi_module' => 'StatsBar', 'cpanel_xmlapi_func' => 'stat', 'display' => 'diskusage' } ); 86 | like( $$res, qr/StatsBar<\/module>/, 'ssl cpanel post hash params' ); 87 | 88 | $res = $pubapi->api_request( 'whostmgr', '/xml-api/removeacct', 'GET', { 'user' => 'papiunit' } ); 89 | like( $$res, qr/papiunit account removed/, 'Test Account Removed' ); 90 | } 91 | } 92 | 93 | my $cp_conf = load_cpanel_config(); 94 | 95 | my $nonssl_tests = 0; 96 | if ( !$cp_conf->{'requiressl'} && !$cp_conf->{'alwaysredirecttossl'} ) { 97 | $nonssl_tests = 1; 98 | } 99 | 100 | SKIP: { 101 | skip 'nonssl querying is not supported on this server', 5, unless $nonssl_tests; 102 | 103 | my $unsecure = cPanel::PublicAPI->new( 'usessl' => 0 ) if $nonssl_tests; 104 | isa_ok( $unsecure, 'cPanel::PublicAPI' ); 105 | 106 | $res = $unsecure->api_request( 'whostmgr', '/xml-api/loadavg', 'GET' ) if $nonssl_tests; 107 | like( $$res, qr/\s*\d+\.\d+<\/one>\s*\d+\.\d+<\/five>\s*\d+\.\d+<\/fifteen>\s*<\/loadavg>*/, 'nossl whm get no params' ); 108 | 109 | $res = $unsecure->api_request( 'whostmgr', '/xml-api/createacct', 'GET', { 'username' => 'test', 'domain' => 'test.com' } ); 110 | like( $$res, $createacct_regex, 'nossl whm get hash params' ) if $nonssl_tests; 111 | 112 | $res = $unsecure->api_request( 'whostmgr', '/xml-api/createacct', 'GET', 'username=test&domain=test.com' ); 113 | like( $$res, $createacct_regex, 'nossl whm get string params' ) if $nonssl_tests; 114 | 115 | $res = $unsecure->api_request( 'whostmgr', '/xml-api/createacct', 'POST', { 'username' => 'test', 'domain' => 'test.com' } ); 116 | like( $$res, $createacct_regex, 'nossl whm post hash params' ) if $nonssl_tests; 117 | 118 | $res = $unsecure->api_request( 'whostmgr', '/xml-api/createacct', 'POST', 'username=test&domain=test.com' ); 119 | like( $$res, $createacct_regex, 'nossl whm post string params' ) if $nonssl_tests; 120 | 121 | } 122 | 123 | done_testing(); 124 | 125 | # used for generating the password of a test account 126 | sub generate_password { 127 | my @chars = ( 'A' .. 'Z', 'a' .. 'z', '0' .. '9' ); 128 | my $pass = ''; 129 | foreach ( 1 .. 32 ) { 130 | $pass .= $chars[ int rand @chars ]; 131 | } 132 | return $pass; 133 | } 134 | 135 | sub load_cpanel_config { 136 | my %cpanel_config; 137 | open( my $config_fh, '<', '/var/cpanel/cpanel.config' ) || BAIL_OUT('Could not load /var/cpanel/cpanel.config'); 138 | foreach my $line ( readline($config_fh) ) { 139 | next if $line !~ /=/; 140 | chomp $line; 141 | my ( $key, $value ) = split( /=/, $line, 2 ); 142 | $cpanel_config{$key} = $value; 143 | } 144 | return \%cpanel_config; 145 | } 146 | 147 | sub check_api_access { 148 | my $pubapi = cPanel::PublicAPI->new( 'ssl_verify_mode' => 0 ); 149 | my $res = eval { $pubapi->whm_api('applist') }; 150 | if ($@) { 151 | plan skip_all => "Failed to verify API access as current user: $@"; 152 | } 153 | 154 | if ( exists $res->{'data'}->{'app'} && ref $res->{'data'}->{'app'} eq 'ARRAY' ) { 155 | return $pubapi if grep { $_ eq 'createacct' } @{ $res->{'data'}->{'app'} }; 156 | } 157 | 158 | plan skip_all => "Current user doesn't appear to have proper privileges"; 159 | } 160 | -------------------------------------------------------------------------------- /t/02-construct.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright 2017, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use strict; 33 | use warnings; 34 | 35 | use Test::More; 36 | use Test::Exception; 37 | 38 | use cPanel::PublicAPI (); 39 | 40 | my @getpwuid = getpwuid($>); 41 | my $homedir = $getpwuid[7]; 42 | my $user = $getpwuid[0]; 43 | 44 | # test default settings 45 | if ( !-e $homedir . '/.accesshash' ) { 46 | $ENV{'REMOTE_PASSWORD'} = 'b4r!' if !defined $ENV{'REMOTE_PASSWORD'}; 47 | $ENV{'SERVER_SOFTWARE'} = 'cpsrvd fakeout'; 48 | } 49 | 50 | check_options(); 51 | check_options( 'debug' => 1, 'error_log' => '/dev/null' ); 52 | check_options( 'timeout' => 150 ); 53 | check_options( 'usessl' => 0 ); 54 | check_options( 'ip' => '4.2.2.2' ); 55 | check_options( 'host' => 'zomg.cpanel.net' ); 56 | check_options( 'error_log' => '/dev/null' ); 57 | check_options( 'user' => 'bar' ); 58 | check_options( 'pass' => 'f00!3Df@' ); 59 | my $accesshash = 'sdflkjl 60 | sdafjkl 61 | sdlfkjh'; 62 | check_options( 'accesshash' => $accesshash ); 63 | check_options( 'api_token' => 'sdfkjl' ); 64 | throws_ok { 65 | check_options( 'api_token' => 'sdfkjl', 'accesshash' => $accesshash ); 66 | } 67 | qr/You cannot specify both an accesshash and an API token/, 'Dies when specifying both an accesshash and API token'; 68 | 69 | my $http_tiny_creator_called; 70 | 71 | my $pubapi = cPanel::PublicAPI->new( 72 | 'error_log' => '/dev/null', 73 | http_tiny_creator => sub { 74 | $http_tiny_creator_called = 1; 75 | 76 | return HTTP::Tiny->new(@_); 77 | }, 78 | 79 | ); 80 | 81 | ok( $http_tiny_creator_called, 'http_tiny_creator is called' ); 82 | 83 | $pubapi->error('random string'); 84 | is( $pubapi->{'error'}, 'random string', 'Error variable is stored correctly' ); 85 | 86 | $pubapi->_init(); 87 | is( ref $cPanel::PublicAPI::CFG{'uri_encoder_func'}, 'CODE', 'URI Encoder Detected' ); 88 | 89 | $pubapi->_init_serializer(); 90 | is( ref $cPanel::PublicAPI::CFG{'api_decode_func'}, 'CODE', 'Serializer parse function detected' ); 91 | like( $cPanel::PublicAPI::CFG{'serializer_module'}, qr/^JSON/, 'Serializer Module is Named' ); 92 | is( $cPanel::PublicAPI::CFG{'serializer'}, 'json', 'Serailizer format is correct' ); 93 | 94 | my $query_result = $pubapi->format_http_query( { 'one' => 'uno', 'two' => 'dos' } ); 95 | is( $query_result, 'one=uno&two=dos', 'format_http_query' ); 96 | 97 | $pubapi->set_debug(1); 98 | is( $pubapi->{'debug'}, 1, 'set_debug accessor' ); 99 | 100 | $pubapi->user('someuser'); 101 | is( $pubapi->{'user'}, 'someuser', 'user accessor' ); 102 | 103 | $pubapi->{'accesshash'} = 'deleteme'; 104 | $pubapi->pass('somepass'); 105 | is( $pubapi->{'pass'}, 'somepass', 'pass accessor' ); 106 | ok( !exists $pubapi->{'accesshash'}, 'pass accessor deletes accesshash scalar' ); 107 | 108 | $pubapi->accesshash('onetwothreefour'); 109 | is( $pubapi->{'accesshash'}, 'onetwothreefour', 'accesshash accessor' ); 110 | ok( !exists $pubapi->{'pass'}, 'accesshash accessor deletes pass scalar' ); 111 | 112 | $pubapi->api_token('fivesixseveneight'); 113 | is( $pubapi->{'accesshash'}, 'fivesixseveneight', 'api_token accessor' ); 114 | ok( !exists $pubapi->{'pass'}, 'api_token accessor deletes pass scalar' ); 115 | 116 | my $header_string = $pubapi->format_http_headers( { 'Authorization' => 'Basic cm9vdDpsMGx1cnNtNHJ0IQ==' } ); 117 | is( $header_string, "Authorization: Basic cm9vdDpsMGx1cnNtNHJ0IQ==\r\n", 'format_http_headers is ok' ); 118 | 119 | can_ok( $pubapi, 'new', 'set_debug', 'user', 'pass', 'accesshash', 'api_token', 'whm_api', 'api_request', 'cpanel_api1_request', 'cpanel_api2_request', '_total_form_length', '_init_serializer', '_init', 'error', 'debug', 'format_http_query' ); 120 | 121 | done_testing(); 122 | 123 | # This subroutine is intended to check the options sent to a publicAPI instance. 124 | # The first parameter is the publicAPI instance, the rest should be hash key-pairs that allow you to 125 | # override default settings 126 | sub check_options { 127 | my %OPTS = @_; 128 | my $pubapi = cPanel::PublicAPI->new(%OPTS); 129 | isa_ok( $pubapi, 'cPanel::PublicAPI' ); 130 | if ( defined $OPTS{'debug'} ) { 131 | is( $pubapi->{'debug'}, $OPTS{'debug'}, 'debug constructor option' ); 132 | } 133 | else { 134 | is( $pubapi->{'debug'}, '0', 'debug default' ); 135 | } 136 | 137 | if ( defined $OPTS{'timeout'} ) { 138 | is( $pubapi->{'timeout'}, $OPTS{'timeout'}, 'timeout constructor option' ); 139 | } 140 | else { 141 | is( $pubapi->{'timeout'}, 300, 'timeout default' ); 142 | } 143 | 144 | if ( defined $OPTS{'usessl'} ) { 145 | is( $pubapi->{'usessl'}, $OPTS{'usessl'}, 'usessl constructor option' ); 146 | } 147 | else { 148 | is( $pubapi->{'usessl'}, 1, 'usessl default' ); 149 | } 150 | 151 | if ( defined $OPTS{'ip'} ) { 152 | is( $pubapi->{'ip'}, $OPTS{'ip'}, 'ip constructor option' ); 153 | } 154 | elsif ( defined $OPTS{'host'} ) { 155 | is( $pubapi->{'host'}, $OPTS{'host'}, 'host constructor option' ); 156 | } 157 | else { 158 | is( $pubapi->{'ip'}, '127.0.0.1', 'ip default' ); 159 | } 160 | 161 | if ( defined $OPTS{'error_log'} ) { 162 | ok( $pubapi->{'error_fh'} ne \*STDERR, 'error_log is not STDERR' ); 163 | } 164 | else { 165 | is( $pubapi->{'error_fh'}, \*STDERR, 'error_log is set to STDERR' ); 166 | } 167 | 168 | if ( defined $OPTS{'user'} ) { 169 | is( $pubapi->{'user'}, $OPTS{'user'}, 'user constructor option' ); 170 | } 171 | else { 172 | is( $pubapi->{'user'}, $user, 'user default' ); 173 | } 174 | 175 | if ( defined $OPTS{'pass'} ) { 176 | is( $pubapi->{'pass'}, $OPTS{'pass'}, 'pass constructor option' ); 177 | } 178 | elsif ( defined $OPTS{'api_token'} ) { 179 | is( $pubapi->{'accesshash'}, $OPTS{'api_token'}, 'api_token constructor option' ); 180 | } 181 | elsif ( defined $OPTS{'accesshash'} ) { 182 | my $accesshash = $OPTS{'accesshash'}; 183 | $accesshash =~ s/[\r\n]//g; 184 | is( $pubapi->{'accesshash'}, $accesshash, 'accesshash constructor option' ); 185 | } 186 | else { 187 | if ( -e $homedir . './accesshash' ) { 188 | my $accesshash = get_accesshash(); 189 | is( $pubapi->{'accesshash'}, $accesshash, 'accesshash default' ); 190 | } 191 | else { 192 | is( $pubapi->{'pass'}, $ENV{'REMOTE_PASSWORD'}, 'password default' ); 193 | } 194 | } 195 | } 196 | 197 | sub get_accesshash { 198 | my $accesshash; 199 | open( my $ah_fh, '<', $homedir . '/.accesshash' ); 200 | foreach my $line ( readline($ah_fh) ) { 201 | $accesshash .= $line; 202 | } 203 | $accesshash =~ s/[\r\n]//; 204 | return $accesshash; 205 | } 206 | -------------------------------------------------------------------------------- /t/01-api-format.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Test::More; # last test to print 7 | 8 | use lib 't/lib'; 9 | 10 | use PubApiTest (); 11 | 12 | my $pubapi = PubApiTest->new( 13 | 'ip' => '127.0.0.1', 14 | 'usessl' => 1, 15 | 'user' => 'someuser', 16 | 'pass' => 'somepass', 17 | 'error_log' => '/dev/null', 18 | ); 19 | 20 | # test WHM 21 | $PubApiTest::test_config = { 22 | 'service' => 'whostmgr', 23 | 'uri' => '/json-api/loadavg', 24 | 'method' => 'POST', 25 | 'call' => 'whm_api-noform', 26 | 'return_format' => 'json', 27 | }; 28 | my $res = $pubapi->whm_api('loadavg'); 29 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 30 | 31 | $PubApiTest::test_config->{'test_formdata'} = 'hash'; 32 | $PubApiTest::test_config->{'formdata'} = { 'key' => 'value', 'api.version' => 1 }; 33 | $PubApiTest::test_config->{'call'} = 'whm_api-refform'; 34 | $res = $pubapi->whm_api( 'loadavg', { 'key' => 'value' } ); 35 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 36 | 37 | $PubApiTest::test_config->{'test_formdata'} = 'hash'; 38 | $PubApiTest::test_config->{'formdata'} = { 'key' => 'value', 'api.version' => 0 }; 39 | $PubApiTest::test_config->{'call'} = 'whm_api-refapi0'; 40 | $res = $pubapi->whm_api( 'loadavg', $PubApiTest::test_config->{'formdata'} ); 41 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 42 | 43 | $PubApiTest::test_config->{'test_formdata'} = 'hash'; 44 | $PubApiTest::test_config->{'formdata'} = { 'key' => 'value', 'api.version' => 1 }; 45 | $PubApiTest::test_config->{'call'} = 'whm_api-refapi1'; 46 | $res = $pubapi->whm_api( 'loadavg', $PubApiTest::test_config->{'formdata'} ); 47 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 48 | 49 | $PubApiTest::test_config->{'test_formdata'} = 'string'; 50 | $PubApiTest::test_config->{'formdata'} = 'api.version=1&one&two'; 51 | $PubApiTest::test_config->{'call'} = 'whm_api-stringform'; 52 | $res = $pubapi->whm_api( 'loadavg', 'one&two' ); 53 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 54 | 55 | $PubApiTest::test_config->{'test_formdata'} = 'string'; 56 | $PubApiTest::test_config->{'formdata'} = 'api.version=0&one&two'; 57 | $PubApiTest::test_config->{'call'} = 'whm_api-stringapi0'; 58 | $res = $pubapi->whm_api( 'loadavg', 'api.version=0&one&two' ); 59 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 60 | 61 | delete $PubApiTest::test_config->{'formdata'}; 62 | delete $PubApiTest::test_config->{'test_formdata'}; 63 | $PubApiTest::test_config->{'return_format'} = 'json'; 64 | $res = $pubapi->whm_api( 'loadavg', undef, 'json' ); 65 | is( $res, '{"something":"somethinglese"}', 'raw JSON data returned raw correctly from whm_api' ); 66 | 67 | $PubApiTest::test_config->{'test_format'} = 'xml'; 68 | $PubApiTest::test_config->{'return_format'} = 'xml'; 69 | $PubApiTest::test_config->{'uri'} = '/xml-api/loadavg'; 70 | $res = $pubapi->whm_api( 'loadavg', undef, 'xml' ); 71 | is( $res, 'somethingelse', 'raw XML data returned raw correctly from whm_api' ); 72 | 73 | # test API1 74 | $PubApiTest::test_config = { 75 | 'service' => 'cpanel', 76 | 'uri' => '/json-api/cpanel', 77 | 'method' => 'GET', 78 | 'call' => 'api1-noargs', 79 | 'return_format' => 'json', 80 | 'test_formdata' => 'hash', 81 | 82 | }; 83 | 84 | # Without arguments 85 | $PubApiTest::test_config->{'formdata'} = { 86 | 'cpanel_jsonapi_module' => 'Test', 87 | 'cpanel_jsonapi_func' => 'test', 88 | 'cpanel_jsonapi_apiversion' => 1, 89 | }; 90 | 91 | my $call_config = { 92 | 'module' => 'Test', 93 | 'func' => 'test', 94 | }; 95 | 96 | $res = $pubapi->cpanel_api1_request( 'cpanel', $call_config ); 97 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 98 | 99 | # with arguments 100 | $PubApiTest::test_config->{'call'} = 'api1-args'; 101 | $PubApiTest::test_config->{'formdata'}->{'arg-0'} = 'one'; 102 | $PubApiTest::test_config->{'formdata'}->{'arg-1'} = 'two'; 103 | $res = $pubapi->cpanel_api1_request( 'cpanel', $call_config, [ 'one', 'two' ] ); 104 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 105 | 106 | # WHM 107 | 108 | # with arguments 109 | $PubApiTest::test_config->{'call'} = 'whm-api1-args'; 110 | $PubApiTest::test_config->{'formdata'}->{'cpanel_jsonapi_user'} = 'someuser'; 111 | $PubApiTest::test_config->{'service'} = 'whostmgr'; 112 | $call_config->{'user'} = 'someuser'; 113 | $res = $pubapi->cpanel_api1_request( 'whostmgr', $call_config, [ 'one', 'two' ] ); 114 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 115 | 116 | # without arguments 117 | $PubApiTest::test_config->{'call'} = 'whm-api1-noargs'; 118 | delete $PubApiTest::test_config->{'formdata'}->{'arg-1'}; 119 | delete $PubApiTest::test_config->{'formdata'}->{'arg-0'}; 120 | $res = $pubapi->cpanel_api1_request( 'whostmgr', $call_config ); 121 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 122 | 123 | # Test JSON 124 | $PubApiTest::test_config->{'call'} = 'whm-api1-rawjson'; 125 | $PubApiTest::test_config->{'return_format'} = 'json'; 126 | $res = $pubapi->cpanel_api1_request( 'whostmgr', $call_config, undef, 'json' ); 127 | is( $res, '{"something":"somethinglese"}', 'raw JSON data returned raw correctly from cpanel_api1_request' ); 128 | 129 | # Test XML 130 | $PubApiTest::test_config->{'call'} = 'whm-api1-rawxml'; 131 | $PubApiTest::test_config->{'test_format'} = 'xml'; 132 | $PubApiTest::test_config->{'return_format'} = 'xml'; 133 | $PubApiTest::test_config->{'uri'} = '/xml-api/cpanel'; 134 | 135 | $PubApiTest::test_config->{'formdata'} = { 136 | 'cpanel_xmlapi_user' => 'someuser', 137 | 'cpanel_xmlapi_module' => 'Test', 138 | 'cpanel_xmlapi_func' => 'test', 139 | 'cpanel_xmlapi_apiversion' => '1', 140 | }; 141 | 142 | $res = $pubapi->cpanel_api1_request( 'whostmgr', $call_config, [], 'xml' ); 143 | is( $res, 'somethingelse', 'raw XML data returned raw correctly from cpanel_api1_request' ); 144 | 145 | # API2 146 | $PubApiTest::test_config = { 147 | 'service' => 'cpanel', 148 | 'uri' => '/json-api/cpanel', 149 | 'method' => 'GET', 150 | 'call' => 'api2-noargs', 151 | 'return_format' => 'json', 152 | 'test_formdata' => 'hash', 153 | }; 154 | 155 | $PubApiTest::test_config->{'formdata'} = { 156 | 'cpanel_jsonapi_func' => 'test', 157 | 'cpanel_jsonapi_module' => 'Api2Test', 158 | 'cpanel_jsonapi_apiversion' => '2', 159 | }; 160 | 161 | $call_config = { 162 | 'module' => 'Api2Test', 163 | 'func' => 'test', 164 | }; 165 | 166 | # without args 167 | $res = $pubapi->cpanel_api2_request( 'cpanel', $call_config ); 168 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 169 | 170 | # with args 171 | $PubApiTest::test_config->{'call'} = 'whm-api2-args'; 172 | my $args = { 173 | 'testing' => 'one two three', 174 | 'earth below' => 'us', 175 | }; 176 | 177 | foreach my $key ( keys %{$args} ) { 178 | $PubApiTest::test_config->{'formdata'}->{$key} = $args->{$key}; 179 | } 180 | 181 | $res = $pubapi->cpanel_api2_request( 'cpanel', $call_config, $args ); 182 | is( ref $res, 'HASH', 'Returned format ok for ' . $PubApiTest::test_config->{'call'} ); 183 | 184 | # XML/JSON response tests 185 | delete $PubApiTest::test_config->{'formdata'}->{'testing'}; 186 | delete $PubApiTest::test_config->{'formdata'}->{'earth below'}; 187 | 188 | $PubApiTest::test_config->{'call'} = 'api2-rawjson'; 189 | $res = $pubapi->cpanel_api2_request( 'cpanel', $call_config, undef, 'json' ); 190 | is( $res, '{"something":"somethinglese"}', 'raw JSON data returned raw correctly from cpanel_api2_request' ); 191 | 192 | #xml 193 | 194 | $PubApiTest::test_config->{'call'} = 'api2-rawxml'; 195 | $PubApiTest::test_config->{'formdata'} = { 196 | 'cpanel_xmlapi_module' => 'Api2Test', 197 | 'cpanel_xmlapi_func' => 'test', 198 | 'cpanel_xmlapi_apiversion' => '2' 199 | }; 200 | $PubApiTest::test_config->{'format'} = 'xml'; 201 | $PubApiTest::test_config->{'return_format'} = 'xml'; 202 | $PubApiTest::test_config->{'uri'} = '/xml-api/cpanel'; 203 | 204 | $res = $pubapi->cpanel_api2_request( 'cpanel', $call_config, undef, 'xml' ); 205 | is( $res, 'somethingelse', 'raw XML data returned raw correctly from cpanel_api2_request' ); 206 | 207 | # test call failure situations 208 | $PubApiTest::test_config->{'badcall'} = 'whmapi'; 209 | $pubapi->whm_api('version'); 210 | like( $pubapi->{'error'}, qr/cPanel::PublicAPI::whm_api was called with the invalid API call of/, 'whm_api invalid call checking works' ); 211 | 212 | $PubApiTest::test_config->{'badcall'} = 'cpanelapi1'; 213 | $pubapi->cpanel_api1_request( 'cpanel', { 'module' => 'test', 'func' => 'test' } ); 214 | like( $pubapi->{'error'}, qr/cPanel::PublicAPI::cpanel_api1_request was called with the invalid API1 call of:/, 'cpanel_api1_request invalid call checking works' ); 215 | 216 | $PubApiTest::test_config->{'badcall'} = 'cpanelapi2'; 217 | $pubapi->cpanel_api2_request( 'cpanel', { 'module' => 'test', 'func' => 'test' } ); 218 | like( $pubapi->{'error'}, qr/cPanel::PublicAPI::cpanel_api2_request was called with the invalid API2 call of:/, 'cpanel_api1_request invalid call checking works' ); 219 | 220 | done_testing(); 221 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/API.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI::WHM::API - Legacy interface for querying the xml-api. 6 | 7 | NOTE: This module is provided for legacy purposes, L should be used instead 8 | 9 | =head1 DESCRIPTION 10 | 11 | This module provides legacy compatibility support between L and Cpanel::Accounting (distributed with cPanel). 12 | This should never be used unless there is a very good reason to use it (such as having a script that uses Cpanel::Accounting). 13 | 14 | Every method contained within this object can be queried using cPanel::publicAPI::whm_api() instead. 15 | 16 | For more information on the calls within the methods contained here and what the parameter names mean, please read the documentation at: L 17 | 18 | =head1 functions 19 | 20 | =head2 C 21 | 22 | Used to list the accounts on a server. 23 | 24 | Syntax: 25 | 26 | $pubapi->api_listaccts( $search, $searchtype ); 27 | 28 | =head2 C 29 | 30 | Create a new cPanel account. 31 | 32 | Syntax: 33 | 34 | $pubapi->api_createacct( $username, $domain, $password, $plan ); 35 | 36 | =head2 C 37 | 38 | Terminate an account. 39 | 40 | Syntax: 41 | 42 | $pubapi->api_removeacct( $user ); 43 | 44 | =head2 C 45 | 46 | Get the version of cPanel running on the server. 47 | 48 | Syntax: 49 | 50 | $pubapi->api_showversion( ); 51 | 52 | =head2 C 53 | 54 | Get the version of cPanel running on the server (as as showversion) 55 | 56 | Syntax: 57 | 58 | $pubapi->api_version( ); 59 | 60 | =head2 C 61 | 62 | List out the available xml-api calls. 63 | 64 | Syntax: 65 | 66 | $pubapi->api_applist( ); 67 | 68 | =head2 C 69 | 70 | Generate an ssl certificate. 71 | 72 | Syntax: 73 | 74 | $pubapi->api_generatessl( $host, $pass, $country, $state, $city, $co, $cod, $email, $xemail ); 75 | 76 | =head2 C 77 | 78 | Generate an SSL certificate without an email. 79 | 80 | Syntax: 81 | 82 | $pubapi->api_generatessl_noemail( $noemail=1 ); 83 | 84 | =head2 C 85 | 86 | List out the certificates that exist on the server. 87 | 88 | Syntax: 89 | 90 | $pubapi->api_listcrts( ); 91 | 92 | =head2 C 93 | 94 | Set the limits for a single reseller account. 95 | 96 | Syntax: 97 | 98 | $pubapi->api_setresellerlimits( ); 99 | 100 | =head2 C 101 | 102 | Set which packages a reseller account can use. 103 | 104 | Syntax: 105 | 106 | $pubapi->api_setresellerpackagelimit( $user, $package, $allowerd, $number, $no_limit ); 107 | 108 | =head2 C 109 | 110 | Set a reseller's main IP. 111 | 112 | Syntax: 113 | 114 | $pubapi->api_setresellermainip( $user, $ip ); 115 | 116 | =head2 C 117 | 118 | Set the IP that a reseller has available to it. 119 | 120 | Syntax: 121 | 122 | $pubapi->api_setresellerips( $user, $delegate, $ips ); 123 | 124 | =head2 C 125 | 126 | Set the nameservers that a reseller uses by default. 127 | 128 | Syntax: 129 | 130 | $pubapi->api_setresellernameservers( $user, $nameservers ); 131 | 132 | =head2 C 133 | 134 | Suspend a reseller and all of their accounts. 135 | 136 | Syntax: 137 | 138 | $pubapi->api_suspendreseller( $user, $reason, $disallow ); 139 | 140 | =head2 C 141 | 142 | Unsuspend a reseller and all of their accounts. 143 | 144 | Syntax: 145 | 146 | $pubapi->api_unsuspendreseller( $user ); 147 | 148 | =head2 C 149 | 150 | Add a record to a zone. 151 | 152 | Syntax: 153 | 154 | $pubapi->api_addzonerecord( @args ); 155 | 156 | =head2 C 157 | 158 | Edit a zone record. 159 | 160 | Syntax: 161 | 162 | $pubapi->api_editzonerecord(@args ); 163 | 164 | =head2 C 165 | 166 | Remove a line from a zone. 167 | 168 | Syntax: 169 | 170 | $pubapi->api_removezonerecord( $domain, $Line ); 171 | 172 | =head2 C 173 | 174 | Get a record from a zone. 175 | 176 | Syntax: 177 | 178 | $pubapi->api_getzonerecord( $domain, $Line ); 179 | 180 | =head2 C 181 | 182 | Get the status of various services running on a system. 183 | 184 | Syntax: 185 | 186 | $pubapi->api_servicestatus( $service ); 187 | 188 | =head2 C 189 | 190 | Enable/Disable various services. 191 | 192 | Syntax: 193 | 194 | $pubapi->api_configureservice( $service, $enabled, $monitored ); 195 | 196 | =head2 C 197 | 198 | Get the number of accounts on a system/that belong to a reseller. 199 | 200 | Syntax: 201 | 202 | $pubapi->api_acctcounts( $user ); 203 | 204 | =head2 C 205 | 206 | Get the information about a specific domain's virtualhost. 207 | 208 | Syntax: 209 | 210 | $pubapi->api_domainuserdata( $domain ); 211 | 212 | =head2 C 213 | 214 | Edit a user's quota. 215 | 216 | Syntax: 217 | 218 | $pubapi->api_editquota( $user, $quota ); 219 | 220 | =head2 C 221 | 222 | Get non-volatile data. 223 | 224 | Syntax: 225 | 226 | $pubapi->api_nvget( $key ); 227 | 228 | =head2 C 229 | 230 | Set non-volatile data. 231 | 232 | Syntax: 233 | 234 | $pubapi->api_nvset( $key, $value ); 235 | 236 | =head2 C 237 | 238 | See what privileges are available to your user. 239 | 240 | Syntax: 241 | 242 | $pubapi->api_myprivs( ); 243 | 244 | =head2 C 245 | 246 | List all the zones available to a user. 247 | 248 | Syntax: 249 | 250 | $pubapi->api_listzones( ); 251 | 252 | =head2 C 253 | 254 | Set the hostname of a system. 255 | 256 | Syntax: 257 | 258 | $pubapi->api_sethostname( $hostname ); 259 | 260 | =head2 C 261 | 262 | Set the resolvers a system uses. 263 | 264 | Syntax: 265 | 266 | $pubapi->api_setresolvers( $nameserver1, $nameserver2, $nameserver3 ); 267 | 268 | =head2 C 269 | 270 | Add a new IP to a server. 271 | 272 | Syntax: 273 | 274 | $pubapi->api_addip( $ip, $netmask ); 275 | 276 | =head2 C 277 | 278 | Remove an IP from a server. 279 | 280 | Syntax: 281 | 282 | $pubapi->api_delip( $ip, $ethernetdev, $skipifshutdown ); 283 | 284 | =head2 C 285 | 286 | List the IPs on a server. 287 | 288 | Syntax: 289 | 290 | $pubapi->api_listips( ); 291 | 292 | =head2 C 293 | 294 | Get the contents of a zone file. 295 | 296 | Syntax: 297 | 298 | $pubapi->api_dumpzone( $domain ); 299 | 300 | =head2 C 301 | 302 | List the packages available to your user. 303 | 304 | Syntax: 305 | 306 | $pubapi->api_listpkgs( ); 307 | 308 | =head2 C 309 | 310 | Limit the amount of bandwidth available to an account. 311 | 312 | Syntax: 313 | 314 | $pubapi->api_limitbw( $user, $bwlimit ); 315 | 316 | =head2 C 317 | 318 | Show the amount of BW used by an account. 319 | 320 | Syntax: 321 | 322 | $pubapi->api_showbw( $month, $year, $showres, $search, $searchtype ); 323 | 324 | =head2 C 325 | 326 | Remove a DNS zone. 327 | 328 | Syntax: 329 | 330 | $pubapi->api_killdns( $domain ); 331 | 332 | =head2 C 333 | 334 | Add a dns zone. 335 | 336 | Syntax: 337 | 338 | $pubapi->api_adddns( $domain, $ip, $trueowner ); 339 | 340 | =head2 C 341 | 342 | Change an Account's Package. 343 | 344 | Syntax: 345 | 346 | $pubapi->api_changepackage( $user, $pkg ); 347 | 348 | =head2 C 349 | 350 | Modify an Account's limits. 351 | 352 | Syntax: 353 | 354 | $pubapi->api_modifyacct( $user, $domain, $HASCGI, $CPTHEME, $LANG, $MAXPOP, $MAXFTP, $MAXLST, $MAXSUB, $MAXPARK, $MAXADDON, $MAXSQL, $shell ); 355 | 356 | =head2 C 357 | 358 | Suspend an account. 359 | 360 | Syntax: 361 | 362 | $pubapi->api_suspendacct( $user, $reason ); 363 | 364 | =head2 C 365 | 366 | Unsuspend an account. 367 | 368 | Syntax: 369 | 370 | $pubapi->api_unsuspendacct( $user ); 371 | 372 | =head2 C 373 | 374 | List the suspended accounts on a server. 375 | 376 | Syntax: 377 | 378 | $pubapi->api_listsuspended( ); 379 | 380 | =head2 C 381 | 382 | Add a new package. 383 | 384 | Syntax: 385 | 386 | $pubapi->api_addpkg( $pkgname, $quota, $ip, $cgi, $frontpage, $cpmod, $maxftp, $maxsql, $maxpop, $maxlst, $maxsub, $maxpark, $maxaddon, $featurelist, $hasshell, $bwlimit ); 387 | 388 | =head2 C 389 | 390 | Remove a package. 391 | 392 | Syntax: 393 | 394 | $pubapi->api_killpkg( $pkg ); 395 | 396 | =head2 C 397 | 398 | Edit a package. 399 | 400 | Syntax: 401 | 402 | $pubapi->api_editpkg( $pkgname, $quota, $ip, $cgi, $frontpage, $cpmod, $maxftp, $maxsql, $maxpop, $maxlst, $maxsub, $maxpark, $maxaddon, $featurelist, $hasshell, $bwlimit ); 403 | 404 | =head2 C 405 | 406 | Change features available to a reseller. 407 | 408 | Syntax: 409 | 410 | $pubapi->api_setacls( $reseller, $acllist ); 411 | 412 | =head2 C 413 | 414 | Remove a reseller. 415 | 416 | Syntax: 417 | 418 | $pubapi->api_terminatereseller( $reseller, $verify ); 419 | 420 | =head2 C 421 | 422 | Get statistics on a specific reseller. 423 | 424 | Syntax: 425 | 426 | $pubapi->api_resellerstats( $reseller ); 427 | 428 | =head2 C 429 | 430 | Make a cPanel account a Reseller account. 431 | 432 | Syntax: 433 | 434 | $pubapi->api_setupreseller( $user, $makeowner ); 435 | 436 | =head2 C 437 | 438 | Get the IP for a nameserver. 439 | 440 | Syntax: 441 | 442 | $pubapi->api_lookupnsip( $nameserver ); 443 | 444 | =head2 C 445 | 446 | List all the resellers on a system. 447 | 448 | Syntax: 449 | 450 | $pubapi->api_listresellers( ); 451 | 452 | =head2 C 453 | 454 | List all of the ACL lists available. 455 | 456 | Syntax: 457 | 458 | $pubapi->api_listacls( ); 459 | 460 | =head2 C 461 | 462 | Save a new ACL list. 463 | 464 | Syntax: 465 | 466 | $pubapi->api_saveacllist( $acllist ); 467 | 468 | =head2 C 469 | 470 | Remove reseller permissions from an account. 471 | 472 | Syntax: 473 | 474 | $pubapi->api_unsetupreseller( $user ); 475 | 476 | =head2 C 477 | 478 | Get the hostname of the server currently being queried. 479 | 480 | Syntax: 481 | 482 | $pubapi->api_gethostname( ); 483 | 484 | =head2 C 485 | 486 | Get information on a specific SSL certificate. 487 | 488 | Syntax: 489 | 490 | $pubapi->api_fetchsslinfo( $domain, $crtdata ); 491 | 492 | =head2 C 493 | 494 | Install a new SSL certificate. 495 | 496 | Syntax: 497 | 498 | $pubapi->api_installssl( $domain, $user, $cert, $key, $cab, $ip ); 499 | 500 | =head2 C 501 | 502 | Change an account's password. 503 | 504 | Syntax: 505 | 506 | $pubapi->api_passwd( $user, $pass ); 507 | 508 | =head2 C 509 | 510 | Get a list of languages available on a system. 511 | 512 | Syntax: 513 | 514 | $pubapi->api_getlanglist( ); 515 | 516 | =head2 C 517 | 518 | Reboot the server. 519 | 520 | Syntax: 521 | 522 | $pubapi->api_reboot( $force ); 523 | 524 | =head2 C 525 | 526 | Get a summary of an account. 527 | 528 | Syntax: 529 | 530 | $pubapi->api_accountsummary_user( $user ); 531 | 532 | =head2 C 533 | 534 | Get the summary of an account by specifying the domain. 535 | 536 | Syntax: 537 | 538 | $pubapi->api_accountsummary_domain( $domain ); 539 | 540 | =head2 C 541 | 542 | Get the loadavg on the system. 543 | 544 | Syntax: 545 | 546 | $pubapi->api_loadavg( ); 547 | 548 | =head2 C 549 | 550 | Restart a service. 551 | 552 | Syntax: 553 | 554 | $pubapi->api_restartservice( $service ); 555 | 556 | =head2 C 557 | 558 | Set the IP for a specific user. 559 | 560 | Syntax: 561 | 562 | $pubapi->api_setsiteip_user( $user, $ip ); 563 | 564 | =head2 C 565 | 566 | Set the IP for a specific domain. 567 | 568 | Syntax: 569 | 570 | $pubapi->api_setsiteip_domain( $domain, $ip ); 571 | 572 | =head1 Bugs 573 | 574 | see http://rt.cpan.org to report and view bugs 575 | 576 | =head1 License 577 | 578 | Copyright (c) 2015, cPanel, Inc. 579 | All rights reserved. 580 | http://cpanel.net 581 | 582 | Redistribution and use in source and binary forms, with or without 583 | modification, are permitted provided that the following conditions are met: 584 | * Redistributions of source code must retain the above copyright 585 | notice, this list of conditions and the following disclaimer. 586 | * Redistributions in binary form must reproduce the above copyright 587 | notice, this list of conditions and the following disclaimer in the 588 | documentation and/or other materials provided with the distribution. 589 | * Neither the name of cPanel, Inc. nor the 590 | names of its contributors may be used to endorse or promote products 591 | derived from this software without specific prior written permission. 592 | 593 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 594 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 595 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 596 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 597 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 598 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 599 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 600 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 601 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 602 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 603 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/XMLAPI.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI::WHM::API - Legacy interface for querying the xml-api. 6 | 7 | NOTE: This module is provided for legacy purposes, L should be used instead 8 | 9 | =head1 DESCRIPTION 10 | 11 | This module provides legacy compatibility support between L and Cpanel::Accounting (distributed with cPanel). 12 | This should never be used unless there is a very good reason to use it (such as having a script that uses Cpanel::Accounting). 13 | 14 | Every method contained within this object can be queried using cPanel::publicAPI::whm_api() instead. 15 | 16 | For more information on the calls within the methods contained here and what the parameter names mean, please read the documentation at: L 17 | 18 | =head1 functions 19 | 20 | =head2 C 21 | 22 | Used to list the accounts on a server. 23 | 24 | Syntax: 25 | 26 | $pubapi->xmlapi_listaccts( $search, $searchtype ); 27 | 28 | =head2 C 29 | 30 | Create a new cPanel account. 31 | 32 | Syntax: 33 | 34 | $pubapi->xmlapi_createacct( $username, $domain, $password, $plan ); 35 | 36 | =head2 C 37 | 38 | Terminate an account. 39 | 40 | Syntax: 41 | 42 | $pubapi->xmlapi_removeacct( $user ); 43 | 44 | =head2 C 45 | 46 | Get the version of cPanel running on the server. 47 | 48 | Syntax: 49 | 50 | $pubapi->xmlapi_showversion( ); 51 | 52 | =head2 C 53 | 54 | Get the version of cPanel running on the server (as as showversion) 55 | 56 | Syntax: 57 | 58 | $pubapi->xmlapi_version( ); 59 | 60 | =head2 C 61 | 62 | List out the available xml-api calls. 63 | 64 | Syntax: 65 | 66 | $pubapi->xmlapi_applist( ); 67 | 68 | =head2 C 69 | 70 | Generate an ssl certificate. 71 | 72 | Syntax: 73 | 74 | $pubapi->xmlapi_generatessl( $host, $pass, $country, $state, $city, $co, $cod, $email, $xemail ); 75 | 76 | =head2 C 77 | 78 | Generate an SSL certificate without an email. 79 | 80 | Syntax: 81 | 82 | $pubapi->xmlapi_generatessl_noemail( $noemail=1 ); 83 | 84 | =head2 C 85 | 86 | List out the certificates that exist on the server. 87 | 88 | Syntax: 89 | 90 | $pubapi->xmlapi_listcrts( ); 91 | 92 | =head2 C 93 | 94 | Set the limits for a single reseller account. 95 | 96 | Syntax: 97 | 98 | $pubapi->xmlapi_setresellerlimits( ); 99 | 100 | =head2 C 101 | 102 | Set which packages a reseller account can use. 103 | 104 | Syntax: 105 | 106 | $pubapi->xmlapi_setresellerpackagelimit( $user, $package, $allowerd, $number, $no_limit ); 107 | 108 | =head2 C 109 | 110 | Set a reseller's main IP. 111 | 112 | Syntax: 113 | 114 | $pubapi->xmlapi_setresellermainip( $user, $ip ); 115 | 116 | =head2 C 117 | 118 | Set the IP that a reseller has available to it. 119 | 120 | Syntax: 121 | 122 | $pubapi->xmlapi_setresellerips( $user, $delegate, $ips ); 123 | 124 | =head2 C 125 | 126 | Set the nameservers that a reseller uses by default. 127 | 128 | Syntax: 129 | 130 | $pubapi->xmlapi_setresellernameservers( $user, $nameservers ); 131 | 132 | =head2 C 133 | 134 | Suspend a reseller and all of their accounts. 135 | 136 | Syntax: 137 | 138 | $pubapi->xmlapi_suspendreseller( $user, $reason, $disallow ); 139 | 140 | =head2 C 141 | 142 | Unsuspend a reseller and all of their accounts. 143 | 144 | Syntax: 145 | 146 | $pubapi->xmlapi_unsuspendreseller( $user ); 147 | 148 | =head2 C 149 | 150 | Add a record to a zone. 151 | 152 | Syntax: 153 | 154 | $pubapi->xmlapi_addzonerecord( @args ); 155 | 156 | =head2 C 157 | 158 | Edit a zone record. 159 | 160 | Syntax: 161 | 162 | $pubapi->xmlapi_editzonerecord(@args ); 163 | 164 | =head2 C 165 | 166 | Remove a line from a zone. 167 | 168 | Syntax: 169 | 170 | $pubapi->xmlapi_removezonerecord( $domain, $Line ); 171 | 172 | =head2 C 173 | 174 | Get a record from a zone. 175 | 176 | Syntax: 177 | 178 | $pubapi->xmlapi_getzonerecord( $domain, $Line ); 179 | 180 | =head2 C 181 | 182 | Get the status of various services running on a system. 183 | 184 | Syntax: 185 | 186 | $pubapi->xmlapi_servicestatus( $service ); 187 | 188 | =head2 C 189 | 190 | Enable/Disable various services. 191 | 192 | Syntax: 193 | 194 | $pubapi->xmlapi_configureservice( $service, $enabled, $monitored ); 195 | 196 | =head2 C 197 | 198 | Get the number of accounts on a system/that belong to a reseller. 199 | 200 | Syntax: 201 | 202 | $pubapi->xmlapi_acctcounts( $user ); 203 | 204 | =head2 C 205 | 206 | Get the information about a specific domain's virtualhost. 207 | 208 | Syntax: 209 | 210 | $pubapi->xmlapi_domainuserdata( $domain ); 211 | 212 | =head2 C 213 | 214 | Edit a user's quota. 215 | 216 | Syntax: 217 | 218 | $pubapi->xmlapi_editquota( $user, $quota ); 219 | 220 | =head2 C 221 | 222 | Get non-volatile data. 223 | 224 | Syntax: 225 | 226 | $pubapi->xmlapi_nvget( $key ); 227 | 228 | =head2 C 229 | 230 | Set non-volatile data. 231 | 232 | Syntax: 233 | 234 | $pubapi->xmlapi_nvset( $key, $value ); 235 | 236 | =head2 C 237 | 238 | See what privileges are available to your user. 239 | 240 | Syntax: 241 | 242 | $pubapi->xmlapi_myprivs( ); 243 | 244 | =head2 C 245 | 246 | List all the zones available to a user. 247 | 248 | Syntax: 249 | 250 | $pubapi->xmlapi_listzones( ); 251 | 252 | =head2 C 253 | 254 | Set the hostname of a system. 255 | 256 | Syntax: 257 | 258 | $pubapi->xmlapi_sethostname( $hostname ); 259 | 260 | =head2 C 261 | 262 | Set the resolvers a system uses. 263 | 264 | Syntax: 265 | 266 | $pubapi->xmlapi_setresolvers( $nameserver1, $nameserver2, $nameserver3 ); 267 | 268 | =head2 C 269 | 270 | Add a new IP to a server. 271 | 272 | Syntax: 273 | 274 | $pubapi->xmlapi_addip( $ip, $netmask ); 275 | 276 | =head2 C 277 | 278 | Remove an IP from a server. 279 | 280 | Syntax: 281 | 282 | $pubapi->xmlapi_delip( $ip, $ethernetdev, $skipifshutdown ); 283 | 284 | =head2 C 285 | 286 | List the IPs on a server. 287 | 288 | Syntax: 289 | 290 | $pubapi->xmlapi_listips( ); 291 | 292 | =head2 C 293 | 294 | Get the contents of a zone file. 295 | 296 | Syntax: 297 | 298 | $pubapi->xmlapi_dumpzone( $domain ); 299 | 300 | =head2 C 301 | 302 | List the packages available to your user. 303 | 304 | Syntax: 305 | 306 | $pubapi->xmlapi_listpkgs( ); 307 | 308 | =head2 C 309 | 310 | Limit the amount of bandwidth available to an account. 311 | 312 | Syntax: 313 | 314 | $pubapi->xmlapi_limitbw( $user, $bwlimit ); 315 | 316 | =head2 C 317 | 318 | Show the amount of BW used by an account. 319 | 320 | Syntax: 321 | 322 | $pubapi->xmlapi_showbw( $month, $year, $showres, $search, $searchtype ); 323 | 324 | =head2 C 325 | 326 | Remove a DNS zone. 327 | 328 | Syntax: 329 | 330 | $pubapi->xmlapi_killdns( $domain ); 331 | 332 | =head2 C 333 | 334 | Add a dns zone. 335 | 336 | Syntax: 337 | 338 | $pubapi->xmlapi_adddns( $domain, $ip, $trueowner ); 339 | 340 | =head2 C 341 | 342 | Change an Account's Package. 343 | 344 | Syntax: 345 | 346 | $pubapi->xmlapi_changepackage( $user, $pkg ); 347 | 348 | =head2 C 349 | 350 | Modify an Account's limits. 351 | 352 | Syntax: 353 | 354 | $pubapi->xmlapi_modifyacct( $user, $domain, $HASCGI, $CPTHEME, $LANG, $MAXPOP, $MAXFTP, $MAXLST, $MAXSUB, $MAXPARK, $MAXADDON, $MAXSQL, $shell ); 355 | 356 | =head2 C 357 | 358 | Suspend an account. 359 | 360 | Syntax: 361 | 362 | $pubapi->xmlapi_suspendacct( $user, $reason ); 363 | 364 | =head2 C 365 | 366 | Unsuspend an account. 367 | 368 | Syntax: 369 | 370 | $pubapi->xmlapi_unsuspendacct( $user ); 371 | 372 | =head2 C 373 | 374 | List the suspended accounts on a server. 375 | 376 | Syntax: 377 | 378 | $pubapi->xmlapi_listsuspended( ); 379 | 380 | =head2 C 381 | 382 | Add a new package. 383 | 384 | Syntax: 385 | 386 | $pubapi->xmlapi_addpkg( $pkgname, $quota, $ip, $cgi, $frontpage, $cpmod, $maxftp, $maxsql, $maxpop, $maxlst, $maxsub, $maxpark, $maxaddon, $featurelist, $hasshell, $bwlimit ); 387 | 388 | =head2 C 389 | 390 | Remove a package. 391 | 392 | Syntax: 393 | 394 | $pubapi->xmlapi_killpkg( $pkg ); 395 | 396 | =head2 C 397 | 398 | Edit a package. 399 | 400 | Syntax: 401 | 402 | $pubapi->xmlapi_editpkg( $pkgname, $quota, $ip, $cgi, $frontpage, $cpmod, $maxftp, $maxsql, $maxpop, $maxlst, $maxsub, $maxpark, $maxaddon, $featurelist, $hasshell, $bwlimit ); 403 | 404 | =head2 C 405 | 406 | Change features available to a reseller. 407 | 408 | Syntax: 409 | 410 | $pubapi->xmlapi_setacls( $reseller, $acllist ); 411 | 412 | =head2 C 413 | 414 | Remove a reseller. 415 | 416 | Syntax: 417 | 418 | $pubapi->xmlapi_terminatereseller( $reseller, $verify ); 419 | 420 | =head2 C 421 | 422 | Get statistics on a specific reseller. 423 | 424 | Syntax: 425 | 426 | $pubapi->xmlapi_resellerstats( $reseller ); 427 | 428 | =head2 C 429 | 430 | Make a cPanel account a Reseller account. 431 | 432 | Syntax: 433 | 434 | $pubapi->xmlapi_setupreseller( $user, $makeowner ); 435 | 436 | =head2 C 437 | 438 | Get the IP for a nameserver. 439 | 440 | Syntax: 441 | 442 | $pubapi->xmlapi_lookupnsip( $nameserver ); 443 | 444 | =head2 C 445 | 446 | List all the resellers on a system. 447 | 448 | Syntax: 449 | 450 | $pubapi->xmlapi_listresellers( ); 451 | 452 | =head2 C 453 | 454 | List all of the ACL lists available. 455 | 456 | Syntax: 457 | 458 | $pubapi->xmlapi_listacls( ); 459 | 460 | =head2 C 461 | 462 | Save a new ACL list. 463 | 464 | Syntax: 465 | 466 | $pubapi->xmlapi_saveacllist( $acllist ); 467 | 468 | =head2 C 469 | 470 | Remove reseller permissions from an account. 471 | 472 | Syntax: 473 | 474 | $pubapi->xmlapi_unsetupreseller( $user ); 475 | 476 | =head2 C 477 | 478 | Get the hostname of the server currently being queried. 479 | 480 | Syntax: 481 | 482 | $pubapi->xmlapi_gethostname( ); 483 | 484 | =head2 C 485 | 486 | Get information on a specific SSL certificate. 487 | 488 | Syntax: 489 | 490 | $pubapi->xmlapi_fetchsslinfo( $domain, $crtdata ); 491 | 492 | =head2 C 493 | 494 | Install a new SSL certificate. 495 | 496 | Syntax: 497 | 498 | $pubapi->xmlapi_installssl( $domain, $user, $cert, $key, $cab, $ip ); 499 | 500 | =head2 C 501 | 502 | Change an account's password. 503 | 504 | Syntax: 505 | 506 | $pubapi->xmlapi_passwd( $user, $pass ); 507 | 508 | =head2 C 509 | 510 | Get a list of languages available on a system. 511 | 512 | Syntax: 513 | 514 | $pubapi->xmlapi_getlanglist( ); 515 | 516 | =head2 C 517 | 518 | Reboot the server. 519 | 520 | Syntax: 521 | 522 | $pubapi->xmlapi_reboot( $force ); 523 | 524 | =head2 C 525 | 526 | Get a summary of an account. 527 | 528 | Syntax: 529 | 530 | $pubapi->xmlapi_accountsummary_user( $user ); 531 | 532 | =head2 C 533 | 534 | Get the summary of an account by specifying the domain. 535 | 536 | Syntax: 537 | 538 | $pubapi->xmlapi_accountsummary_domain( $domain ); 539 | 540 | =head2 C 541 | 542 | Get the loadavg on the system. 543 | 544 | Syntax: 545 | 546 | $pubapi->xmlapi_loadavg( ); 547 | 548 | =head2 C 549 | 550 | Restart a service. 551 | 552 | Syntax: 553 | 554 | $pubapi->xmlapi_restartservice( $service ); 555 | 556 | =head2 C 557 | 558 | Set the IP for a specific user. 559 | 560 | Syntax: 561 | 562 | $pubapi->xmlapi_setsiteip_user( $user, $ip ); 563 | 564 | =head2 C 565 | 566 | Set the IP for a specific domain. 567 | 568 | Syntax: 569 | 570 | $pubapi->xmlapi_setsiteip_domain( $domain, $ip ); 571 | 572 | =head1 Bugs 573 | 574 | see http://rt.cpan.org to report and view bugs 575 | 576 | =head1 License 577 | 578 | Copyright (c) 2015, cPanel, Inc. 579 | All rights reserved. 580 | http://cpanel.net 581 | 582 | Redistribution and use in source and binary forms, with or without 583 | modification, are permitted provided that the following conditions are met: 584 | * Redistributions of source code must retain the above copyright 585 | notice, this list of conditions and the following disclaimer. 586 | * Redistributions in binary form must reproduce the above copyright 587 | notice, this list of conditions and the following disclaimer in the 588 | documentation and/or other materials provided with the distribution. 589 | * Neither the name of cPanel, Inc. nor the 590 | names of its contributors may be used to endorse or promote products 591 | derived from this software without specific prior written permission. 592 | 593 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 594 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 595 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 596 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 597 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 598 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 599 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 600 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 601 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 602 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 603 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/JSONAPI.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI::WHM::API - Legacy interface for querying the xml-api. 6 | 7 | NOTE: This module is provided for legacy purposes, L should be used instead 8 | 9 | =head1 DESCRIPTION 10 | 11 | This module provides legacy compatibility support between L and Cpanel::Accounting (distributed with cPanel). 12 | This should never be used unless there is a very good reason to use it (such as having a script that uses Cpanel::Accounting). 13 | 14 | Every method contained within this object can be queried using cPanel::publicAPI::whm_api() instead. 15 | 16 | For more information on the calls within the methods contained here and what the parameter names mean, please read the documentation at: L 17 | 18 | =head1 functions 19 | 20 | =head2 C 21 | 22 | Used to list the accounts on a server. 23 | 24 | Syntax: 25 | 26 | $pubapi->jsonapi_listaccts( $search, $searchtype ); 27 | 28 | =head2 C 29 | 30 | Create a new cPanel account. 31 | 32 | Syntax: 33 | 34 | $pubapi->jsonapi_createacct( $username, $domain, $password, $plan ); 35 | 36 | =head2 C 37 | 38 | Terminate an account. 39 | 40 | Syntax: 41 | 42 | $pubapi->jsonapi_removeacct( $user ); 43 | 44 | =head2 C 45 | 46 | Get the version of cPanel running on the server. 47 | 48 | Syntax: 49 | 50 | $pubapi->jsonapi_showversion( ); 51 | 52 | =head2 C 53 | 54 | Get the version of cPanel running on the server (as as showversion) 55 | 56 | Syntax: 57 | 58 | $pubapi->jsonapi_version( ); 59 | 60 | =head2 C 61 | 62 | List out the available xml-api calls. 63 | 64 | Syntax: 65 | 66 | $pubapi->jsonapi_applist( ); 67 | 68 | =head2 C 69 | 70 | Generate an ssl certificate. 71 | 72 | Syntax: 73 | 74 | $pubapi->jsonapi_generatessl( $host, $pass, $country, $state, $city, $co, $cod, $email, $xemail ); 75 | 76 | =head2 C 77 | 78 | Generate an SSL certificate without an email. 79 | 80 | Syntax: 81 | 82 | $pubapi->jsonapi_generatessl_noemail( $noemail=1 ); 83 | 84 | =head2 C 85 | 86 | List out the certificates that exist on the server. 87 | 88 | Syntax: 89 | 90 | $pubapi->jsonapi_listcrts( ); 91 | 92 | =head2 C 93 | 94 | Set the limits for a single reseller account. 95 | 96 | Syntax: 97 | 98 | $pubapi->jsonapi_setresellerlimits( ); 99 | 100 | =head2 C 101 | 102 | Set which packages a reseller account can use. 103 | 104 | Syntax: 105 | 106 | $pubapi->jsonapi_setresellerpackagelimit( $user, $package, $allowerd, $number, $no_limit ); 107 | 108 | =head2 C 109 | 110 | Set a reseller's main IP. 111 | 112 | Syntax: 113 | 114 | $pubapi->jsonapi_setresellermainip( $user, $ip ); 115 | 116 | =head2 C 117 | 118 | Set the IP that a reseller has available to it. 119 | 120 | Syntax: 121 | 122 | $pubapi->jsonapi_setresellerips( $user, $delegate, $ips ); 123 | 124 | =head2 C 125 | 126 | Set the nameservers that a reseller uses by default. 127 | 128 | Syntax: 129 | 130 | $pubapi->jsonapi_setresellernameservers( $user, $nameservers ); 131 | 132 | =head2 C 133 | 134 | Suspend a reseller and all of their accounts. 135 | 136 | Syntax: 137 | 138 | $pubapi->jsonapi_suspendreseller( $user, $reason, $disallow ); 139 | 140 | =head2 C 141 | 142 | Unsuspend a reseller and all of their accounts. 143 | 144 | Syntax: 145 | 146 | $pubapi->jsonapi_unsuspendreseller( $user ); 147 | 148 | =head2 C 149 | 150 | Add a record to a zone. 151 | 152 | Syntax: 153 | 154 | $pubapi->jsonapi_addzonerecord( @args ); 155 | 156 | =head2 C 157 | 158 | Edit a zone record. 159 | 160 | Syntax: 161 | 162 | $pubapi->jsonapi_editzonerecord(@args ); 163 | 164 | =head2 C 165 | 166 | Remove a line from a zone. 167 | 168 | Syntax: 169 | 170 | $pubapi->jsonapi_removezonerecord( $domain, $Line ); 171 | 172 | =head2 C 173 | 174 | Get a record from a zone. 175 | 176 | Syntax: 177 | 178 | $pubapi->jsonapi_getzonerecord( $domain, $Line ); 179 | 180 | =head2 C 181 | 182 | Get the status of various services running on a system. 183 | 184 | Syntax: 185 | 186 | $pubapi->jsonapi_servicestatus( $service ); 187 | 188 | =head2 C 189 | 190 | Enable/Disable various services. 191 | 192 | Syntax: 193 | 194 | $pubapi->jsonapi_configureservice( $service, $enabled, $monitored ); 195 | 196 | =head2 C 197 | 198 | Get the number of accounts on a system/that belong to a reseller. 199 | 200 | Syntax: 201 | 202 | $pubapi->jsonapi_acctcounts( $user ); 203 | 204 | =head2 C 205 | 206 | Get the information about a specific domain's virtualhost. 207 | 208 | Syntax: 209 | 210 | $pubapi->jsonapi_domainuserdata( $domain ); 211 | 212 | =head2 C 213 | 214 | Edit a user's quota. 215 | 216 | Syntax: 217 | 218 | $pubapi->jsonapi_editquota( $user, $quota ); 219 | 220 | =head2 C 221 | 222 | Get non-volatile data. 223 | 224 | Syntax: 225 | 226 | $pubapi->jsonapi_nvget( $key ); 227 | 228 | =head2 C 229 | 230 | Set non-volatile data. 231 | 232 | Syntax: 233 | 234 | $pubapi->jsonapi_nvset( $key, $value ); 235 | 236 | =head2 C 237 | 238 | See what privileges are available to your user. 239 | 240 | Syntax: 241 | 242 | $pubapi->jsonapi_myprivs( ); 243 | 244 | =head2 C 245 | 246 | List all the zones available to a user. 247 | 248 | Syntax: 249 | 250 | $pubapi->jsonapi_listzones( ); 251 | 252 | =head2 C 253 | 254 | Set the hostname of a system. 255 | 256 | Syntax: 257 | 258 | $pubapi->jsonapi_sethostname( $hostname ); 259 | 260 | =head2 C 261 | 262 | Set the resolvers a system uses. 263 | 264 | Syntax: 265 | 266 | $pubapi->jsonapi_setresolvers( $nameserver1, $nameserver2, $nameserver3 ); 267 | 268 | =head2 C 269 | 270 | Add a new IP to a server. 271 | 272 | Syntax: 273 | 274 | $pubapi->jsonapi_addip( $ip, $netmask ); 275 | 276 | =head2 C 277 | 278 | Remove an IP from a server. 279 | 280 | Syntax: 281 | 282 | $pubapi->jsonapi_delip( $ip, $ethernetdev, $skipifshutdown ); 283 | 284 | =head2 C 285 | 286 | List the IPs on a server. 287 | 288 | Syntax: 289 | 290 | $pubapi->jsonapi_listips( ); 291 | 292 | =head2 C 293 | 294 | Get the contents of a zone file. 295 | 296 | Syntax: 297 | 298 | $pubapi->jsonapi_dumpzone( $domain ); 299 | 300 | =head2 C 301 | 302 | List the packages available to your user. 303 | 304 | Syntax: 305 | 306 | $pubapi->jsonapi_listpkgs( ); 307 | 308 | =head2 C 309 | 310 | Limit the amount of bandwidth available to an account. 311 | 312 | Syntax: 313 | 314 | $pubapi->jsonapi_limitbw( $user, $bwlimit ); 315 | 316 | =head2 C 317 | 318 | Show the amount of BW used by an account. 319 | 320 | Syntax: 321 | 322 | $pubapi->jsonapi_showbw( $month, $year, $showres, $search, $searchtype ); 323 | 324 | =head2 C 325 | 326 | Remove a DNS zone. 327 | 328 | Syntax: 329 | 330 | $pubapi->jsonapi_killdns( $domain ); 331 | 332 | =head2 C 333 | 334 | Add a dns zone. 335 | 336 | Syntax: 337 | 338 | $pubapi->jsonapi_adddns( $domain, $ip, $trueowner ); 339 | 340 | =head2 C 341 | 342 | Change an Account's Package. 343 | 344 | Syntax: 345 | 346 | $pubapi->jsonapi_changepackage( $user, $pkg ); 347 | 348 | =head2 C 349 | 350 | Modify an Account's limits. 351 | 352 | Syntax: 353 | 354 | $pubapi->jsonapi_modifyacct( $user, $domain, $HASCGI, $CPTHEME, $LANG, $MAXPOP, $MAXFTP, $MAXLST, $MAXSUB, $MAXPARK, $MAXADDON, $MAXSQL, $shell ); 355 | 356 | =head2 C 357 | 358 | Suspend an account. 359 | 360 | Syntax: 361 | 362 | $pubapi->jsonapi_suspendacct( $user, $reason ); 363 | 364 | =head2 C 365 | 366 | Unsuspend an account. 367 | 368 | Syntax: 369 | 370 | $pubapi->jsonapi_unsuspendacct( $user ); 371 | 372 | =head2 C 373 | 374 | List the suspended accounts on a server. 375 | 376 | Syntax: 377 | 378 | $pubapi->jsonapi_listsuspended( ); 379 | 380 | =head2 C 381 | 382 | Add a new package. 383 | 384 | Syntax: 385 | 386 | $pubapi->jsonapi_addpkg( $pkgname, $quota, $ip, $cgi, $frontpage, $cpmod, $maxftp, $maxsql, $maxpop, $maxlst, $maxsub, $maxpark, $maxaddon, $featurelist, $hasshell, $bwlimit ); 387 | 388 | =head2 C 389 | 390 | Remove a package. 391 | 392 | Syntax: 393 | 394 | $pubapi->jsonapi_killpkg( $pkg ); 395 | 396 | =head2 C 397 | 398 | Edit a package. 399 | 400 | Syntax: 401 | 402 | $pubapi->jsonapi_editpkg( $pkgname, $quota, $ip, $cgi, $frontpage, $cpmod, $maxftp, $maxsql, $maxpop, $maxlst, $maxsub, $maxpark, $maxaddon, $featurelist, $hasshell, $bwlimit ); 403 | 404 | =head2 C 405 | 406 | Change features available to a reseller. 407 | 408 | Syntax: 409 | 410 | $pubapi->jsonapi_setacls( $reseller, $acllist ); 411 | 412 | =head2 C 413 | 414 | Remove a reseller. 415 | 416 | Syntax: 417 | 418 | $pubapi->jsonapi_terminatereseller( $reseller, $verify ); 419 | 420 | =head2 C 421 | 422 | Get statistics on a specific reseller. 423 | 424 | Syntax: 425 | 426 | $pubapi->jsonapi_resellerstats( $reseller ); 427 | 428 | =head2 C 429 | 430 | Make a cPanel account a Reseller account. 431 | 432 | Syntax: 433 | 434 | $pubapi->jsonapi_setupreseller( $user, $makeowner ); 435 | 436 | =head2 C 437 | 438 | Get the IP for a nameserver. 439 | 440 | Syntax: 441 | 442 | $pubapi->jsonapi_lookupnsip( $nameserver ); 443 | 444 | =head2 C 445 | 446 | List all the resellers on a system. 447 | 448 | Syntax: 449 | 450 | $pubapi->jsonapi_listresellers( ); 451 | 452 | =head2 C 453 | 454 | List all of the ACL lists available. 455 | 456 | Syntax: 457 | 458 | $pubapi->jsonapi_listacls( ); 459 | 460 | =head2 C 461 | 462 | Save a new ACL list. 463 | 464 | Syntax: 465 | 466 | $pubapi->jsonapi_saveacllist( $acllist ); 467 | 468 | =head2 C 469 | 470 | Remove reseller permissions from an account. 471 | 472 | Syntax: 473 | 474 | $pubapi->jsonapi_unsetupreseller( $user ); 475 | 476 | =head2 C 477 | 478 | Get the hostname of the server currently being queried. 479 | 480 | Syntax: 481 | 482 | $pubapi->jsonapi_gethostname( ); 483 | 484 | =head2 C 485 | 486 | Get information on a specific SSL certificate. 487 | 488 | Syntax: 489 | 490 | $pubapi->jsonapi_fetchsslinfo( $domain, $crtdata ); 491 | 492 | =head2 C 493 | 494 | Install a new SSL certificate. 495 | 496 | Syntax: 497 | 498 | $pubapi->jsonapi_installssl( $domain, $user, $cert, $key, $cab, $ip ); 499 | 500 | =head2 C 501 | 502 | Change an account's password. 503 | 504 | Syntax: 505 | 506 | $pubapi->jsonapi_passwd( $user, $pass ); 507 | 508 | =head2 C 509 | 510 | Get a list of languages available on a system. 511 | 512 | Syntax: 513 | 514 | $pubapi->jsonapi_getlanglist( ); 515 | 516 | =head2 C 517 | 518 | Reboot the server. 519 | 520 | Syntax: 521 | 522 | $pubapi->jsonapi_reboot( $force ); 523 | 524 | =head2 C 525 | 526 | Get a summary of an account. 527 | 528 | Syntax: 529 | 530 | $pubapi->jsonapi_accountsummary_user( $user ); 531 | 532 | =head2 C 533 | 534 | Get the summary of an account by specifying the domain. 535 | 536 | Syntax: 537 | 538 | $pubapi->jsonapi_accountsummary_domain( $domain ); 539 | 540 | =head2 C 541 | 542 | Get the loadavg on the system. 543 | 544 | Syntax: 545 | 546 | $pubapi->jsonapi_loadavg( ); 547 | 548 | =head2 C 549 | 550 | Restart a service. 551 | 552 | Syntax: 553 | 554 | $pubapi->jsonapi_restartservice( $service ); 555 | 556 | =head2 C 557 | 558 | Set the IP for a specific user. 559 | 560 | Syntax: 561 | 562 | $pubapi->jsonapi_setsiteip_user( $user, $ip ); 563 | 564 | =head2 C 565 | 566 | Set the IP for a specific domain. 567 | 568 | Syntax: 569 | 570 | $pubapi->jsonapi_setsiteip_domain( $domain, $ip ); 571 | 572 | =head1 Bugs 573 | 574 | see http://rt.cpan.org to report and view bugs 575 | 576 | =head1 License 577 | 578 | Copyright (c) 2015, cPanel, Inc. 579 | All rights reserved. 580 | http://cpanel.net 581 | 582 | Redistribution and use in source and binary forms, with or without 583 | modification, are permitted provided that the following conditions are met: 584 | * Redistributions of source code must retain the above copyright 585 | notice, this list of conditions and the following disclaimer. 586 | * Redistributions in binary form must reproduce the above copyright 587 | notice, this list of conditions and the following disclaimer in the 588 | documentation and/or other materials provided with the distribution. 589 | * Neither the name of cPanel, Inc. nor the 590 | names of its contributors may be used to endorse or promote products 591 | derived from this software without specific prior written permission. 592 | 593 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 594 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 595 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 596 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 597 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 598 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 599 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 600 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 601 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 602 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 603 | -------------------------------------------------------------------------------- /README.mkdn: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/CpanelInc/cPanel-PublicAPI.svg?branch=master)](https://travis-ci.org/CpanelInc/cPanel-PublicAPI) 2 | 3 | # NAME 4 | 5 | cPanel::PublicAPI - A perl interface for interacting with cPanel 6 | 7 | # SYNOPSIS 8 | 9 | use cPanel::PublicAPI; 10 | 11 | # Auto detect authentication information 12 | my $cp = cPanel::PublicAPI->new(); 13 | # or specify a user/password 14 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'pass' => 'somepass' ); 15 | # or specify an accesshash 16 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'accesshash' => $accesshash ); 17 | # or specify an API token 18 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'api_token' => $api_token ); 19 | 20 | # Perform an xml-api query 21 | $cp->whm_api('listaccts'); 22 | # Pass parameters to the xml-api 23 | $cp->whm_api('createacct', {'username' => 'someuser', 'password' => 's0m3P4$$w()Rd' } ); 24 | # Return JSON from xml-api (rather than a hash reference) 25 | $cp->whm_api('version', undef, 'json'); 26 | 27 | # Perform an API2 query 28 | $cp->cpanel_api2_request('whostmgr', 29 | { 30 | 'module' => 'Email', 31 | 'func' => 'listpopswithdisk', 32 | 'user' => 'someuser', 33 | } 34 | ); 35 | # Perform an API2 query when authenticated as a user 36 | $cp->cpanel_api2_request('cpanel', 37 | { 38 | 'module' => 'Email', 39 | 'func' => 'listpopswithdisk', 40 | } 41 | ); 42 | # Pass parameters to an API2 call 43 | $cp->cpanel_api2_request('cpanel' 44 | { 45 | 'module' => 'Email', 46 | 'func' => 'addpop', 47 | }, 48 | { 49 | 'domain' => 'domain.com', 50 | 'email' => 'username', 51 | 'password' => 'SojmASDM(#(Jinasifodanosd', 52 | 'quota' => 200 53 | }, 54 | ); 55 | 56 | # Perform an API1 query 57 | $cp->cpanel_api1_request('whostmgr', 58 | { 59 | 'module' => 'LastLogin', 60 | 'func' => 'lastlogin', 61 | 'user' => 'someuser' 62 | } 63 | ); 64 | # Pass parameters to an API1 query 65 | $cp->cpanel_api1_request('cpanel', 66 | { 67 | 'module' => 'Mysql', 68 | 'func' => 'adduserdb', 69 | }, 70 | [ 'somedb', 'somedbuser', 'ALL' ] 71 | ); 72 | 73 | # perform an HTTP GET request against a URL 74 | $cp->api_request('whostmgr', '/xml-api/loadavg', 'GET'); 75 | 76 | # perform an HTTP GET request with parameters 77 | $cp->api_request('whostmgr', '/xml-api/createacct', 'GET', {'username' => 'someuser', domain => 'domain.com'} ); 78 | 79 | # perform an HTTP POST request (with parameters) 80 | $cp->api_request('whostmgr', '/xml-api/createacct', 'POST', {'username' => 'someuser', domain => 'domain.com'} ); 81 | 82 | # DESCRIPTION 83 | 84 | cPanel::PublicAPI is a supported interface for interacting with cPanel's APIs over HTTP. 85 | This allows you to query either WHM or cPanel accounts from a perl interface. The purpose 86 | of this module is to provide an easy-to-use interface into cPanel's various APIs without 87 | requiring much knowledge of how they work. 88 | 89 | ## Object Construction 90 | 91 | a cPanel::PublicAPI object is constructed with the new() method. 92 | 93 | my $publicapi = cPanel::PublicAPI->new(); 94 | 95 | When passed no parameters, this will create the object using the accesshash in ~/.accesshash. If no .accesshash file exists, it will attempt to use the REMOTE\_PASS environment variable. If the REMOTE\_PASS variable is not defined, object creation will error out. 96 | 97 | ### new() parameters 98 | 99 | options for new() are specified as a hash reference, the following parameters are supported: 100 | 101 | - user - The username to authenticate as. 102 | - pass - The password to use for authentication. 103 | - accesshash - The accesshash to use for authentication. 104 | - api\_token - The API token to use for authentication. 105 | - timeout - The length of time (in seconds) before an http request should time out. Default to 300. 106 | - ip - The IP to be queried. defaults to 127.0.0.1, if host is defined it will take precedence over the 'ip' parameter. 107 | - host - The hostname to be queried. This will take precedence over the 'ip' parameter. 108 | - usessl - 1 or 0, Indicates whether communication should be performed over SSL or not (default to 1). 109 | - ssl\_verify\_mode - 1 or 0, Indicates whether to verify SSL certificates or not. (default to 1). 110 | - error\_log - Path to where you want debug and error logging information to be written to. If this is not defined or the module is unable to open the path in question, it will default to STDERR. 111 | - debug - Enables debug logging, which will place considerably more information into the error\_log. 112 | 113 | ### Notes about authentication 114 | 115 | There are three sets of credentials that can be used to authenticate to WHM. 116 | 117 | First we have the basic user/password combinations: 118 | 119 | use cPanel::PublicAPI; 120 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'pass' => 'bar' ); 121 | 122 | Next is API token authentication. To create an API token, visit "Manage API Tokens" in WHM and click Generate Token. Fill out 123 | the form and click Generate. Your token will appear in a special notice. Make certain that you save your API token in a safe location 124 | on your workstation. You cannot access the token after you navigate away from the interface or refresh the API Tokens table. 125 | 126 | To use an API token with this module, do the following: 127 | 128 | use cPanel::PublicAPI; 129 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'api_token' => $string_containing_api_token ); 130 | 131 | Last is accesshash authentication. To configure accesshashes, visit “Setup remote access key” 132 | in WHM which will generate an accesshash for your server if one does not already exist. It will store the generated accesshash 133 | in ~/.accesshash. 134 | 135 | To use an accesshash with this module, do the following: 136 | 137 | use cPanel::PublicAPI; 138 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'accesshash' => $string_containing_access_hash ); 139 | 140 | It should be noted that the accesshash can contain newlines in it. Newlines will be stripped by the object when 141 | it attempts to perform a query. 142 | 143 | **NOTE:** Accesshash authentication is deprecated in cPanel & WHM version 64. 144 | 145 | ### Dependencies 146 | 147 | This module will fall back on different modules if one fails to load. This allows for compatibility with cPanel & WHM's internal perl parser and maintain compatibility with a standard perl implementation. The order that it will fall back on serialization modules is: 148 | 149 | - JSON::Syck 150 | - JSON 151 | - JSON::XS 152 | - JSON::PP 153 | 154 | If you installed this module via CPAN, this should never be an issue. If you are wishing to use this 155 | module on a system where you do not have access to compiled modules, JSON::PP is the recommended serializer. 156 | 157 | # Two-Factor Authentication (2FA) 158 | 159 | cPanel version 54 and above allows users to configure 2FA on their accounts - this security policy requires that the API queries 160 | are performed after authenticating and establishing a session. The workflow to accomodate 2FA will be as so: 161 | 162 | use cPanel::PublicAPI; 163 | 164 | use lib '/usr/local/cpanel'; 165 | use Cpanel::Security::Authn::TwoFactorAuth::Google (); # only available in 11.54+ 166 | 167 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'pass' => 'bar' ); 168 | my $google_auth = Cpanel::Security::Authn::TwoFactorAuth::Google->new( 169 | { 170 | 'account_name' => 'foo', 171 | 'secret' => $user_2fa_secret, 172 | 'issuer' => '' 173 | } 174 | ); 175 | $pubapi->establish_tfa_session('whostmgr', $google_auth->generate_code()); 176 | $pubapi->whm_api('applist'); 177 | 178 | Anytime you change services (e.g. from 'whostmgr' to 'cpanel'), you must establish the 2FA session for the new service. 179 | 180 | eval { 181 | $pubapi->cpanel_api2_request('cpanel', { 'user' => 'foo', 'module' => 'MysqlFE', 'func' => 'listdbs' }, {} ); 182 | }; 183 | print "failed cause 2fa session wasn't established\n" if $@; 184 | 185 | $pubapi->establish_tfa_session('cpanel', $google_auth->generate_code()); 186 | eval { 187 | $pubapi->cpanel_api2_request('cpanel', { 'user' => 'foo', 'module' => 'MysqlFE', 'func' => 'listdbs' }, {} ); 188 | }; 189 | print "success\n" if not $@; 190 | 191 | **NOTE**: Additionally, since accesshash authentication is not allowed to establish sessions, you must use the 'user'/'pass' 192 | authentication in order to make API requests as a user with 2FA configured. 193 | 194 | # Important Methods 195 | 196 | ## Querying the xml-api - whm\_api() 197 | 198 | The XML-API is WHM's API used for administrative functions is handled via the whm\_api() method. 199 | 200 | The syntax for whmapi is: 201 | 202 | $cp->whm_api($call [, \%formdata, $format ] ); 203 | 204 | The meaning of these parameters is: 205 | 206 | - $call - The XML-API call you wish to query 207 | - $formdata - The parameters for the XML-API call in question, f.ex. for suspendacct, here you would pass in a hashref containing “user” and “reason”. If there are no parameters, this can be undef or a blank hash. 208 | - $format - The requested response format. The valid values here are “xml”, “json” or “ref” (perl hash reference). This will default to returning a perl hash reference when the value is undef. 209 | 210 | By default, WHM API v1 is used. If, for legacy reasons, you need to use v0, 211 | please set the `api.version` key to 0 in the formdata parameter. 212 | 213 | For more information on what calls are available and how they can be referenced, please see the xml-api documentation at [http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/XmlApi](http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/XmlApi). 214 | 215 | ## Querying cPanel's APIs 216 | 217 | cPanel supports two APIs, designated "API1" and "API2". 218 | 219 | cPanel API calls are seperate into Modules, these module names relate to modules within the Cpanel namespace on a cPanel server. Each module defines a set of functions that are from either API1 or API2 (or both). 220 | 221 | There are two distinct differences between API1 and API2: 222 | 223 | - API1 Takes in ordered parameters and returns strings 224 | - API2 uses named parameters and returns hashes or arrays of hashes 225 | 226 | Within the context of the public api, calling a function from API1 or API2 will always return a hash, but the specific data returned from the API call will be contained within the 'data' key of the response. 227 | 228 | For more information on the differences between API1 and API2 please see the documentation: [http://docs.cpanel.net/twiki/bin/view/DeveloperResources/ApiBasics/WebHome](http://docs.cpanel.net/twiki/bin/view/DeveloperResources/ApiBasics/WebHome) 229 | 230 | For information on calling API1 and API2 direct via HTTP, please see: [http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/CallingAPIFunctions](http://docs.cpanel.net/twiki/bin/view/AllDocumentation/AutomationIntegration/CallingAPIFunctions) 231 | 232 | ### cpanel\_api1\_request() 233 | 234 | `cpanel_api1_request()` is used to query cPanel's API1, the function used for querying API1 has the following syntax: 235 | 236 | $cp->cpanel_api1_request($service, \%cfg [, \@params, $format ] ); 237 | 238 | - $service - The service that you wish to query. This can be 'cpanel' 'whostmgr', or 'webmail'. It is important to note that what services you are able to query depends on the user you are authenticated as. Only a user with reseller or root access can use the whostmgr service. If you are authenticated as root, you will not be able to query the 'cpanel' service. When the service is set to 'whostmgr' a 'user' must be set in the $cfg hash. 239 | - $cfg - A hash reference describing the call you wish to make. Required parameters are 'module' and 'func', which correspond to the module and function of the API call you wish to query. If you are querying the "whostmgr" service, you will need to specify 'user' as well. 240 | - $params - An array reference containing the parameters you wish to pass to the API call. 241 | - $format - The format for the xml-api to respond in. The valid values here are “xml”, “json” or “ref” (perl hash reference). This will default to returning a perl hash reference. 242 | 243 | To see what modules and functions are available for making API1 calls, please see: [http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api1/WebHome](http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api1/WebHome) 244 | 245 | ### cpanel\_api2\_request() 246 | 247 | `cpanel_api2_request()` is used to query cPanel's API2, the function use for querying API2 has the following syntax: 248 | 249 | $cp->cpanel_api2_request( $service, \%cfg [, \%params, $format ] ); 250 | 251 | - $service - The service that you wish to query. This can be 'cpanel' 'whostmgr', or 'webmail'. It is important to note that what services you are able to query depends on the user you are authenticated as. A user that does not have reseller or root access will not be able to use the whostmgr service. If you are authenticated as root, you will not be able to query the 'cpanel' service. When the service is set to 'whostmgr' a 'user' must be set in the $cfg hash. 252 | - $cfg - A hash reference describing the call you wish to make. required parameters here are 'module' and 'func', which correspond to the module and function of the API call you wish to query. If you are querying the "whostmgr" service, you will need to specify 'user' as well. 253 | - $params - An hash reference containing the parameters you wish to pass to the API call. 254 | - $format - The format for the xml-api to respond in. The valid values here are “xml”, “json” or “ref” (perl hash reference). This will default to returning a perl hash reference when the value is undef. 255 | 256 | To see what modules and functions are available for making API2 calls, please see: [http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api2/WebHome](http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api2/WebHome) 257 | 258 | ## api\_request() - Making direct URL requests to cPanel & WHM. 259 | 260 | There are some situations where you will need to query cPanel and WHM URLs directly. This should ONLY be done when there is not an API call available for the function you wish to query. 261 | 262 | The function used for querying URLs directly is api\_request(). It will always return a string rather than converting the response into a hash reference. It uses the following syntax: 263 | 264 | $cp->api_request( $service, $uri, $method, \%formdata, $headers) 265 | 266 | - $service - The service that you wish to query. This can be 'cpanel' 'whostmgr', or 'webmail', when passed an numerical value, PublicAPI will query that port directly. 267 | - $uri - The URL you wish to query, e.g. '/xml-api/cpanel' 268 | - $method - 'GET' or 'POST' 269 | - $formdata - The data you wish to pass to the URL 270 | - $headers - Any additional headers are to be passed with the request. These can be either a flat string or as a hashref like {'headertitle' => 'headerdata'} 271 | 272 | # Other Features 273 | 274 | - `establish_tfa_session()` 275 | 276 | See ["Two-Factor Authentication (2FA)"](#two-factor-authentication-2fa) above. 277 | 278 | - `set_debug()` 279 | 280 | This function allows you to enable/disable debug mode by passing a value that evaluates to 'true' or 'false'. 281 | 282 | - `user()` 283 | 284 | Allows you to change the user that your PublicAPI object is authenticating with. 285 | 286 | - `pass()` 287 | 288 | Allows you to change the password that your PublicAPI object is authenticating with, this will remove the stored accesshash from the object. 289 | 290 | - `accesshash()` 291 | 292 | Allows you to change the accesshash that your PublicAPI object is authenticating with, this will remove the stored password from the object. 293 | 294 | - `api_token()` 295 | 296 | Allows you to change the API token that your PublicAPI object is authenticating with, this will remove the stored password from the object. 297 | 298 | - `format_http_query()` 299 | 300 | Allows you to construct formdata for an http query from a hash. For Example: 301 | 302 | $pubapi->format_http_query( { 'one' => '1', 'two' => 2 } ); 303 | 304 | would return: 305 | 306 | 'one=1&two=2' 307 | 308 | - `format_http_headers()` 309 | 310 | Allows you to construct headers for an http query from a hash. For Example: 311 | 312 | $pubapi->format_http_headers( { 'Authorization' => 'Basic cm9vdDpsMGx1cnNtNHJ0IQ=='} ); 313 | 314 | would return: 315 | 316 | 'Authorization: Basic cm9vdDpsMGx1cnNtNHJ0IQ==\r\n' 317 | 318 | - `$pubapi->{'error'}` 319 | 320 | Errors encountered within the class are stored here before being written out to the error\_fh filehandle. This can be used for checking the existance of query errors. 321 | 322 | # Bugs 323 | 324 | see http://rt.cpan.org to report and view bugs 325 | 326 | # License 327 | 328 | Copyright (c) 2015, cPanel, Inc. 329 | All rights reserved. 330 | http://cpanel.net 331 | 332 | Redistribution and use in source and binary forms, with or without 333 | modification, are permitted provided that the following conditions are met: 334 | \* Redistributions of source code must retain the above copyright 335 | notice, this list of conditions and the following disclaimer. 336 | \* Redistributions in binary form must reproduce the above copyright 337 | notice, this list of conditions and the following disclaimer in the 338 | documentation and/or other materials provided with the distribution. 339 | \* Neither the name of cPanel, Inc. nor the 340 | names of its contributors may be used to endorse or promote products 341 | derived from this software without specific prior written permission. 342 | 343 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 344 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 345 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 346 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 347 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 348 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 349 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 350 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 351 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 352 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 353 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI/WHM/API.pm: -------------------------------------------------------------------------------- 1 | package cPanel::PublicAPI::API; 2 | 3 | # Copyright (c) 2015, cPanel, Inc. 4 | # All rights reserved. 5 | # http://cpanel.net 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # 1. Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # 13 | # 2. Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # 3. Neither the name of the owner nor the names of its contributors may be 18 | # used to endorse or promote products derived from this software without 19 | # specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | use cPanel::PublicAPI (); 33 | our $VERSION = '2.3'; 34 | 35 | package cPanel::PublicAPI; 36 | 37 | use cPanel::PublicAPI::WHM (); 38 | 39 | cPanel::PublicAPI::_init_serializer() if !exists $cPanel::PublicAPI::CFG{'serializer'}; 40 | 41 | sub api_listaccts { 42 | my $self = shift; 43 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/listaccts', \@_, [ 'search', 'searchtype' ] ) ); 44 | } 45 | 46 | sub api_createacct { 47 | my $self = shift; 48 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/createacct', \@_, [ 'username', 'domain', 'password', 'plan' ] ) ); 49 | } 50 | 51 | sub api_removeacct { 52 | my $self = shift; 53 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/removeacct', \@_, ['user'] ) ); 54 | } 55 | 56 | sub api_showversion { 57 | my $self = shift; 58 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/version', \@_ ) ); 59 | } 60 | 61 | sub api_version { 62 | goto &xmlapi_showversion; 63 | } 64 | 65 | sub api_applist { 66 | my $self = shift; 67 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/applist', \@_ ) ); 68 | } 69 | 70 | sub api_generatessl { 71 | my $self = shift; 72 | return $self->serialize( $self->simple_post_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/generatessl', \@_, [ 'host', 'pass', 'country', 'state', 'city', 'co', 'cod', 'email', 'xemail' ] ) ); 73 | } 74 | 75 | sub api_generatessl_noemail { 76 | my $self = shift; 77 | return $self->serialize( $self->simple_post_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/generatessl', \@_, [ 'host', 'pass', 'country', 'state', 'city', 'co', 'cod', 'email' ], ['noemail=1'] ) ); 78 | } 79 | 80 | sub api_listcrts { 81 | my $self = shift; 82 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/listcrts', \@_ ) ); 83 | } 84 | 85 | # Variable arguments 86 | sub api_setresellerlimits { 87 | my $self = shift; 88 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setresellerlimits', \@_ ) ); 89 | } 90 | 91 | sub api_setresellerpackagelimit { 92 | my $self = shift; 93 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setresellerpackagelimit', \@_, [ 'user', 'package', 'allowerd', 'number', 'no_limit' ] ) ); 94 | } 95 | 96 | sub api_setresellermainip { 97 | my $self = shift; 98 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setresellermainip', \@_, [ 'user', 'ip' ] ) ); 99 | } 100 | 101 | sub api_setresellerips { 102 | my $self = shift; 103 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setresellerips', \@_, [ 'user', 'delegate', 'ips' ] ) ); 104 | } 105 | 106 | sub api_setresellernameservers { 107 | my $self = shift; 108 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setresellernameservers', \@_, [ 'user', 'nameservers' ] ) ); 109 | } 110 | 111 | sub api_suspendreseller { 112 | my $self = shift; 113 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/suspendreseller', \@_, [ 'user', 'reason', 'disallow' ] ) ); 114 | } 115 | 116 | sub api_unsuspendreseller { 117 | my $self = shift; 118 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/unsuspendreseller', \@_, ['user'] ) ); 119 | } 120 | 121 | # Variable arguments 122 | sub api_addzonerecord { 123 | my $self = shift; 124 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/addzonerecord', \@_ ) ); 125 | } 126 | 127 | # Variable arguments 128 | sub api_editzonerecord { 129 | my $self = shift; 130 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/editzonerecord', \@_ ) ); 131 | } 132 | 133 | sub api_removezonerecord { 134 | my $self = shift; 135 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/removezonerecord', \@_, [ 'domain', 'Line' ] ) ); 136 | } 137 | 138 | sub api_getzonerecord { 139 | my $self = shift; 140 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/getzonerecord', \@_, [ 'domain', 'Line' ] ) ); 141 | } 142 | 143 | sub api_servicestatus { 144 | my $self = shift; 145 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/servicestatus', \@_, ['service'] ) ); 146 | } 147 | 148 | sub api_configureservice { 149 | my $self = shift; 150 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/configureservice', \@_, [ 'service', 'enabled', 'monitored' ] ) ); 151 | } 152 | 153 | sub api_acctcounts { 154 | my $self = shift; 155 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/acctcounts', \@_, ['user'] ) ); 156 | } 157 | 158 | sub api_domainuserdata { 159 | my $self = shift; 160 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/domainuserdata', \@_, ['domain'] ) ); 161 | } 162 | 163 | sub api_editquota { 164 | my $self = shift; 165 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/editquota', \@_, [ 'user', 'quota' ] ) ); 166 | } 167 | 168 | sub api_nvget { 169 | my $self = shift; 170 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/nvget', \@_, ['key'] ) ); 171 | } 172 | 173 | # The underlying XMLAPI call allows setting multiple nvvars at once by appending 174 | # labels to the end of the variable names... i.e. key1, value1 175 | sub api_nvset { 176 | my $self = shift; 177 | return $self->serialize( $self->simple_post_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/nvset', \@_, [ 'key', 'value' ] ) ); 178 | } 179 | 180 | sub api_myprivs { 181 | my $self = shift; 182 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/myprivs', \@_ ) ); 183 | } 184 | 185 | sub api_listzones { 186 | my $self = shift; 187 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/listzones', \@_ ) ); 188 | } 189 | 190 | sub api_sethostname { 191 | my $self = shift; 192 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/sethostname', \@_, ['hostname'] ) ); 193 | } 194 | 195 | sub api_setresolvers { 196 | my $self = shift; 197 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setresolvers', \@_, [ 'nameserver1', 'nameserver2', 'nameserver3' ] ) ); 198 | } 199 | 200 | sub api_addip { 201 | my $self = shift; 202 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/addip', \@_, [ 'ip', 'netmask' ] ) ); 203 | } 204 | 205 | sub api_delip { 206 | my $self = shift; 207 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/delip', \@_, [ 'ip', 'ethernetdev', 'skipifshutdown' ] ) ); 208 | } 209 | 210 | sub api_listips { 211 | my $self = shift; 212 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/listips', \@_ ) ); 213 | } 214 | 215 | sub api_dumpzone { 216 | my $self = shift; 217 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/dumpzone', \@_, ['domain'] ) ); 218 | } 219 | 220 | sub api_listpkgs { 221 | my $self = shift; 222 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/listpkgs', \@_ ) ); 223 | } 224 | 225 | sub api_limitbw { 226 | my $self = shift; 227 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/limitbw', \@_, [ 'user', 'bwlimit' ] ) ); 228 | } 229 | 230 | sub api_showbw { 231 | my $self = shift; 232 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/showbw', \@_, [ 'month', 'year', 'showres', 'search', 'searchtype' ] ) ); 233 | } 234 | 235 | sub api_killdns { 236 | my $self = shift; 237 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/killdns', \@_, ['domain'] ) ); 238 | } 239 | 240 | sub api_adddns { 241 | my $self = shift; 242 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/adddns', \@_, [ 'domain', 'ip', 'trueowner' ] ) ); 243 | } 244 | 245 | sub api_changepackage { 246 | my $self = shift; 247 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/changepackage', \@_, [ 'user', 'pkg' ] ) ); 248 | } 249 | 250 | sub api_modifyacct { 251 | my $self = shift; 252 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/modifyacct', \@_, [ 'user', 'domain', 'HASCGI', 'CPTHEME', 'LANG', 'MAXPOP', 'MAXFTP', 'MAXLST', 'MAXSUB', 'MAXPARK', 'MAXADDON', 'MAXSQL', 'shell' ] ) ); 253 | } 254 | 255 | sub api_suspendacct { 256 | my $self = shift; 257 | return $self->serialize( $self->simple_post_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/suspendacct', \@_, [ 'user', 'reason' ] ) ); 258 | } 259 | 260 | sub api_unsuspendacct { 261 | my $self = shift; 262 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/unsuspendacct', \@_, ['user'] ) ); 263 | } 264 | 265 | sub api_listsuspended { 266 | my $self = shift; 267 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/listsuspended', \@_ ) ); 268 | } 269 | 270 | sub api_addpkg { 271 | my $self = shift; 272 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/addpkg', \@_, [ 'pkgname', 'quota', 'ip', 'cgi', 'cpmod', 'maxftp', 'maxsql', 'maxpop', 'maxlst', 'maxsub', 'maxpark', 'maxaddon', 'featurelist', 'hasshell', 'bwlimit' ] ) ); 273 | } 274 | 275 | sub api_killpkg { 276 | my $self = shift; 277 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/killpkg', \@_, ['pkg'] ) ); 278 | } 279 | 280 | sub api_editpkg { 281 | my $self = shift; 282 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/editpkg', \@_, [ 'pkgname', 'quota', 'ip', 'cgi', 'cpmod', 'maxftp', 'maxsql', 'maxpop', 'maxlst', 'maxsub', 'maxpark', 'maxaddon', 'featurelist', 'hasshell', 'bwlimit' ] ) ); 283 | } 284 | 285 | sub api_setacls { 286 | my $self = shift; 287 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setacls', \@_, [ 'reseller', 'acllist' ] ) ); 288 | } 289 | 290 | sub api_terminatereseller { 291 | my $self = shift; 292 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/terminatereseller', \@_, [ 'reseller', 'verify' ] ) ); 293 | } 294 | 295 | sub api_resellerstats { 296 | my $self = shift; 297 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/resellerstats', \@_, ['reseller'] ) ); 298 | } 299 | 300 | sub api_setupreseller { 301 | my $self = shift; 302 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setupreseller', \@_, [ 'user', 'makeowner' ] ) ); 303 | } 304 | 305 | sub api_lookupnsip { 306 | my $self = shift; 307 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/lookupnsip', \@_, ['nameserver'] ) ); 308 | } 309 | 310 | sub api_listresellers { 311 | my $self = shift; 312 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/listresellers', \@_ ) ); 313 | } 314 | 315 | sub api_listacls { 316 | my $self = shift; 317 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/listacls', \@_ ) ); 318 | } 319 | 320 | sub api_saveacllist { 321 | my $self = shift; 322 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/saveacllist', \@_, ['acllist'] ) ); 323 | } 324 | 325 | sub api_unsetupreseller { 326 | my $self = shift; 327 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/unsetupreseller', \@_, ['user'] ) ); 328 | } 329 | 330 | sub api_gethostname { 331 | my $self = shift; 332 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/gethostname', \@_ ) ); 333 | } 334 | 335 | sub api_fetchsslinfo { 336 | my $self = shift; 337 | return $self->serialize( $self->simple_post_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/fetchsslinfo', \@_, [ 'domain', 'crtdata' ] ) ); 338 | } 339 | 340 | sub api_installssl { 341 | my $self = shift; 342 | return $self->serialize( $self->simple_post_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/installssl', \@_, [ 'domain', 'user', 'cert', 'key', 'cab', 'ip' ] ) ); 343 | } 344 | 345 | sub api_passwd { 346 | my $self = shift; 347 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/passwd', \@_, [ 'user', 'pass' ] ) ); 348 | } 349 | 350 | sub api_getlanglist { 351 | my $self = shift; 352 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/getlanglist', \@_ ) ); 353 | } 354 | 355 | sub api_reboot { 356 | my $self = shift; 357 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/reboot', \@_, ['force'] ) ); 358 | } 359 | 360 | sub api_accountsummary_user { 361 | my $self = shift; 362 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/accountsummary', \@_, ['user'] ) ); 363 | } 364 | 365 | sub api_accountsummary_domain { 366 | my $self = shift; 367 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/accountsummary', \@_, ['domain'] ) ); 368 | } 369 | 370 | sub api_loadavg { 371 | my $self = shift; 372 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/loadavg', \@_ ) ); 373 | } 374 | 375 | sub api_restartservice { 376 | my $self = shift; 377 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/restartservice', \@_, ['service'] ) ); 378 | } 379 | 380 | sub api_setsiteip_user { 381 | my $self = shift; 382 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setsiteip', \@_, [ 'user', 'ip' ] ) ); 383 | } 384 | 385 | sub api_setsiteip_domain { 386 | my $self = shift; 387 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/setsiteip', \@_, [ 'domain', 'ip' ] ) ); 388 | } 389 | 390 | sub api_initializemsgcenter { 391 | my $self = shift; 392 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/initializemsgcenter', \@_, [ 'title', 'id' ] ) ); 393 | } 394 | 395 | sub api_createmsg { 396 | my $self = shift; 397 | 398 | # Need to perform magic to deal with the optional parameters. 399 | my @parm_names = ( 'title', 'updated', 'published', 'content', 'author.name', 'author.email', 'author.uri', 'contributor.name', 'contributor.email', 'contributor.uri', 'summary' ); 400 | 401 | my $extra_count = scalar(@_) - scalar(@parm_names); 402 | my $cat_count = int( $extra_count / 3 + ( ( $extra_count % 3 ) && 1 ) ); 403 | foreach my $i ( 1 .. $cat_count ) { 404 | push @parm_names, "category.$i.term", "category.$i.label", "category.$i.scheme"; 405 | } 406 | 407 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/createmsg', \@_, \@parm_names ) ); 408 | } 409 | 410 | sub api_deletemsg { 411 | my $self = shift; 412 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/deletemsg', \@_, ['atom_id'] ) ); 413 | } 414 | 415 | sub api_getmsgfeed { 416 | my $self = shift; 417 | return $self->serialize( $self->simple_get_whmreq( '/' . $cPanel::PublicAPI::CFG{'serializer'} . '-api/getmsgfeed', \@_, ['which'] ) ); 418 | } 419 | 420 | sub serialize { 421 | my $self = shift; 422 | return $cPanel::PublicAPI::CFG{'api_decode_func'}->(@_); 423 | } 424 | 425 | 1; 426 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | NAME 2 | cPanel::PublicAPI - A perl interface for interacting with cPanel 3 | 4 | SYNOPSIS 5 | use cPanel::PublicAPI; 6 | 7 | # Auto detect authentication information 8 | my $cp = cPanel::PublicAPI->new(); 9 | # or specify a user/password 10 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'pass' => 'somepass' ); 11 | # or specify an accesshash 12 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'accesshash' => $accesshash ); 13 | # or specify an API token 14 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'api_token' => $api_token ); 15 | 16 | # Perform an xml-api query 17 | $cp->whm_api('listaccts'); 18 | # Pass parameters to the xml-api 19 | $cp->whm_api('createacct', {'username' => 'someuser', 'password' => 's0m3P4$$w()Rd' } ); 20 | # Return JSON from xml-api (rather than a hash reference) 21 | $cp->whm_api('version', undef, 'json'); 22 | 23 | # Perform an API2 query 24 | $cp->cpanel_api2_request('whostmgr', 25 | { 26 | 'module' => 'Email', 27 | 'func' => 'listpopswithdisk', 28 | 'user' => 'someuser', 29 | } 30 | ); 31 | # Perform an API2 query when authenticated as a user 32 | $cp->cpanel_api2_request('cpanel', 33 | { 34 | 'module' => 'Email', 35 | 'func' => 'listpopswithdisk', 36 | } 37 | ); 38 | # Pass parameters to an API2 call 39 | $cp->cpanel_api2_request('cpanel' 40 | { 41 | 'module' => 'Email', 42 | 'func' => 'addpop', 43 | }, 44 | { 45 | 'domain' => 'domain.com', 46 | 'email' => 'username', 47 | 'password' => 'SojmASDM(#(Jinasifodanosd', 48 | 'quota' => 200 49 | }, 50 | ); 51 | 52 | # Perform an API1 query 53 | $cp->cpanel_api1_request('whostmgr', 54 | { 55 | 'module' => 'LastLogin', 56 | 'func' => 'lastlogin', 57 | 'user' => 'someuser' 58 | } 59 | ); 60 | # Pass parameters to an API1 query 61 | $cp->cpanel_api1_request('cpanel', 62 | { 63 | 'module' => 'Mysql', 64 | 'func' => 'adduserdb', 65 | }, 66 | [ 'somedb', 'somedbuser', 'ALL' ] 67 | ); 68 | 69 | # perform an HTTP GET request against a URL 70 | $cp->api_request('whostmgr', '/xml-api/loadavg', 'GET'); 71 | 72 | # perform an HTTP GET request with parameters 73 | $cp->api_request('whostmgr', '/xml-api/createacct', 'GET', {'username' => 'someuser', domain => 'domain.com'} ); 74 | 75 | # perform an HTTP POST request (with parameters) 76 | $cp->api_request('whostmgr', '/xml-api/createacct', 'POST', {'username' => 'someuser', domain => 'domain.com'} ); 77 | 78 | DESCRIPTION 79 | cPanel::PublicAPI is a supported interface for interacting with cPanel's 80 | APIs over HTTP. This allows you to query either WHM or cPanel accounts 81 | from a perl interface. The purpose of this module is to provide an 82 | easy-to-use interface into cPanel's various APIs without requiring much 83 | knowledge of how they work. 84 | 85 | Object Construction 86 | a cPanel::PublicAPI object is constructed with the new() method. 87 | 88 | my $publicapi = cPanel::PublicAPI->new(); 89 | 90 | When passed no parameters, this will create the object using the 91 | accesshash in ~/.accesshash. If no .accesshash file exists, it will 92 | attempt to use the REMOTE_PASS environment variable. If the REMOTE_PASS 93 | variable is not defined, object creation will error out. 94 | 95 | new() parameters 96 | options for new() are specified as a hash reference, the following 97 | parameters are supported: 98 | 99 | * user - The username to authenticate as. 100 | 101 | * pass - The password to use for authentication. 102 | 103 | * accesshash - The accesshash to use for authentication. 104 | 105 | * api_token - The API token to use for authentication. 106 | 107 | * timeout - The length of time (in seconds) before an http request 108 | should time out. Default to 300. 109 | 110 | * ip - The IP to be queried. defaults to 127.0.0.1, if host is defined 111 | it will take precedence over the 'ip' parameter. 112 | 113 | * host - The hostname to be queried. This will take precedence over 114 | the 'ip' parameter. 115 | 116 | * usessl - 1 or 0, Indicates whether communication should be performed 117 | over SSL or not (default to 1). 118 | 119 | * ssl_verify_mode - 1 or 0, Indicates whether to verify SSL 120 | certificates or not. (default to 1). 121 | 122 | * error_log - Path to where you want debug and error logging 123 | information to be written to. If this is not defined or the module 124 | is unable to open the path in question, it will default to STDERR. 125 | 126 | * debug - Enables debug logging, which will place considerably more 127 | information into the error_log. 128 | 129 | Notes about authentication 130 | There are three sets of credentials that can be used to authenticate to 131 | WHM. 132 | 133 | First we have the basic user/password combinations: 134 | 135 | use cPanel::PublicAPI; 136 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'pass' => 'bar' ); 137 | 138 | Next is API token authentication. To create an API token, visit "Manage 139 | API Tokens" in WHM and click Generate Token. Fill out the form and click 140 | Generate. Your token will appear in a special notice. Make certain that 141 | you save your API token in a safe location on your workstation. You 142 | cannot access the token after you navigate away from the interface or 143 | refresh the API Tokens table. 144 | 145 | To use an API token with this module, do the following: 146 | 147 | use cPanel::PublicAPI; 148 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'api_token' => $string_containing_api_token ); 149 | 150 | Last is accesshash authentication. To configure accesshashes, visit 151 | “Setup remote access key” in WHM which will generate an accesshash for 152 | your server if one does not already exist. It will store the generated 153 | accesshash in ~/.accesshash. 154 | 155 | To use an accesshash with this module, do the following: 156 | 157 | use cPanel::PublicAPI; 158 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'accesshash' => $string_containing_access_hash ); 159 | 160 | It should be noted that the accesshash can contain newlines in it. 161 | Newlines will be stripped by the object when it attempts to perform a 162 | query. 163 | 164 | NOTE: Accesshash authentication is deprecated in cPanel & WHM version 165 | 64. 166 | 167 | Dependencies 168 | This module will fall back on different modules if one fails to load. 169 | This allows for compatibility with cPanel & WHM's internal perl parser 170 | and maintain compatibility with a standard perl implementation. The 171 | order that it will fall back on serialization modules is: 172 | 173 | * JSON::Syck 174 | 175 | * JSON 176 | 177 | * JSON::XS 178 | 179 | * JSON::PP 180 | 181 | If you installed this module via CPAN, this should never be an issue. If 182 | you are wishing to use this module on a system where you do not have 183 | access to compiled modules, JSON::PP is the recommended serializer. 184 | 185 | Two-Factor Authentication (2FA) 186 | cPanel version 54 and above allows users to configure 2FA on their 187 | accounts - this security policy requires that the API queries are 188 | performed after authenticating and establishing a session. The workflow 189 | to accomodate 2FA will be as so: 190 | 191 | use cPanel::PublicAPI; 192 | 193 | use lib '/usr/local/cpanel'; 194 | use Cpanel::Security::Authn::TwoFactorAuth::Google (); # only available in 11.54+ 195 | 196 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'pass' => 'bar' ); 197 | my $google_auth = Cpanel::Security::Authn::TwoFactorAuth::Google->new( 198 | { 199 | 'account_name' => 'foo', 200 | 'secret' => $user_2fa_secret, 201 | 'issuer' => '' 202 | } 203 | ); 204 | $pubapi->establish_tfa_session('whostmgr', $google_auth->generate_code()); 205 | $pubapi->whm_api('applist'); 206 | 207 | Anytime you change services (e.g. from 'whostmgr' to 'cpanel'), you must 208 | establish the 2FA session for the new service. 209 | 210 | eval { 211 | $pubapi->cpanel_api2_request('cpanel', { 'user' => 'foo', 'module' => 'MysqlFE', 'func' => 'listdbs' }, {} ); 212 | }; 213 | print "failed cause 2fa session wasn't established\n" if $@; 214 | 215 | $pubapi->establish_tfa_session('cpanel', $google_auth->generate_code()); 216 | eval { 217 | $pubapi->cpanel_api2_request('cpanel', { 'user' => 'foo', 'module' => 'MysqlFE', 'func' => 'listdbs' }, {} ); 218 | }; 219 | print "success\n" if not $@; 220 | 221 | NOTE: Additionally, since accesshash authentication is not allowed to 222 | establish sessions, you must use the 'user'/'pass' authentication in 223 | order to make API requests as a user with 2FA configured. 224 | 225 | Important Methods 226 | Querying the xml-api - whm_api() 227 | The XML-API is WHM's API used for administrative functions is handled 228 | via the whm_api() method. 229 | 230 | The syntax for whmapi is: 231 | 232 | $cp->whm_api($call [, \%formdata, $format ] ); 233 | 234 | The meaning of these parameters is: 235 | 236 | * $call - The XML-API call you wish to query 237 | 238 | * $formdata - The parameters for the XML-API call in question, f.ex. 239 | for suspendacct, here you would pass in a hashref containing “user” 240 | and “reason”. If there are no parameters, this can be undef or a 241 | blank hash. 242 | 243 | * $format - The requested response format. The valid values here are 244 | “xml”, “json” or “ref” (perl hash reference). This will default to 245 | returning a perl hash reference when the value is undef. 246 | 247 | By default, WHM API v1 is used. If, for legacy reasons, you need to use 248 | v0, please set the "api.version" key to 0 in the formdata parameter. 249 | 250 | For more information on what calls are available and how they can be 251 | referenced, please see the xml-api documentation at 252 | . 254 | 255 | Querying cPanel's APIs 256 | cPanel supports two APIs, designated "API1" and "API2". 257 | 258 | cPanel API calls are seperate into Modules, these module names relate to 259 | modules within the Cpanel namespace on a cPanel server. Each module 260 | defines a set of functions that are from either API1 or API2 (or both). 261 | 262 | There are two distinct differences between API1 and API2: 263 | 264 | * API1 Takes in ordered parameters and returns strings 265 | 266 | * API2 uses named parameters and returns hashes or arrays of hashes 267 | 268 | Within the context of the public api, calling a function from API1 or 269 | API2 will always return a hash, but the specific data returned from the 270 | API call will be contained within the 'data' key of the response. 271 | 272 | For more information on the differences between API1 and API2 please see 273 | the documentation: 274 | 276 | 277 | For information on calling API1 and API2 direct via HTTP, please see: 278 | 280 | 281 | cpanel_api1_request() 282 | "cpanel_api1_request()" is used to query cPanel's API1, the function 283 | used for querying API1 has the following syntax: 284 | 285 | $cp->cpanel_api1_request($service, \%cfg [, \@params, $format ] ); 286 | 287 | * $service - The service that you wish to query. This can be 'cpanel' 288 | 'whostmgr', or 'webmail'. It is important to note that what services 289 | you are able to query depends on the user you are authenticated as. 290 | Only a user with reseller or root access can use the whostmgr 291 | service. If you are authenticated as root, you will not be able to 292 | query the 'cpanel' service. When the service is set to 'whostmgr' a 293 | 'user' must be set in the $cfg hash. 294 | 295 | * $cfg - A hash reference describing the call you wish to make. 296 | Required parameters are 'module' and 'func', which correspond to the 297 | module and function of the API call you wish to query. If you are 298 | querying the "whostmgr" service, you will need to specify 'user' as 299 | well. 300 | 301 | * $params - An array reference containing the parameters you wish to 302 | pass to the API call. 303 | 304 | * $format - The format for the xml-api to respond in. The valid values 305 | here are “xml”, “json” or “ref” (perl hash reference). This will 306 | default to returning a perl hash reference. 307 | 308 | To see what modules and functions are available for making API1 calls, 309 | please see: 310 | 311 | cpanel_api2_request() 312 | "cpanel_api2_request()" is used to query cPanel's API2, the function use 313 | for querying API2 has the following syntax: 314 | 315 | $cp->cpanel_api2_request( $service, \%cfg [, \%params, $format ] ); 316 | 317 | * $service - The service that you wish to query. This can be 'cpanel' 318 | 'whostmgr', or 'webmail'. It is important to note that what services 319 | you are able to query depends on the user you are authenticated as. 320 | A user that does not have reseller or root access will not be able 321 | to use the whostmgr service. If you are authenticated as root, you 322 | will not be able to query the 'cpanel' service. When the service is 323 | set to 'whostmgr' a 'user' must be set in the $cfg hash. 324 | 325 | * $cfg - A hash reference describing the call you wish to make. 326 | required parameters here are 'module' and 'func', which correspond 327 | to the module and function of the API call you wish to query. If you 328 | are querying the "whostmgr" service, you will need to specify 'user' 329 | as well. 330 | 331 | * $params - An hash reference containing the parameters you wish to 332 | pass to the API call. 333 | 334 | * $format - The format for the xml-api to respond in. The valid values 335 | here are “xml”, “json” or “ref” (perl hash reference). This will 336 | default to returning a perl hash reference when the value is undef. 337 | 338 | To see what modules and functions are available for making API2 calls, 339 | please see: 340 | 341 | api_request() - Making direct URL requests to cPanel & WHM. 342 | There are some situations where you will need to query cPanel and WHM 343 | URLs directly. This should ONLY be done when there is not an API call 344 | available for the function you wish to query. 345 | 346 | The function used for querying URLs directly is api_request(). It will 347 | always return a string rather than converting the response into a hash 348 | reference. It uses the following syntax: 349 | 350 | $cp->api_request( $service, $uri, $method, \%formdata, $headers) 351 | 352 | * $service - The service that you wish to query. This can be 'cpanel' 353 | 'whostmgr', or 'webmail', when passed an numerical value, PublicAPI 354 | will query that port directly. 355 | 356 | * $uri - The URL you wish to query, e.g. '/xml-api/cpanel' 357 | 358 | * $method - 'GET' or 'POST' 359 | 360 | * $formdata - The data you wish to pass to the URL 361 | 362 | * $headers - Any additional headers are to be passed with the request. 363 | These can be either a flat string or as a hashref like 364 | {'headertitle' => 'headerdata'} 365 | 366 | Other Features 367 | "establish_tfa_session()" 368 | 369 | See "Two-Factor Authentication (2FA)" above. 370 | 371 | "set_debug()" 372 | 373 | This function allows you to enable/disable debug mode by passing a value 374 | that evaluates to 'true' or 'false'. 375 | 376 | "user()" 377 | 378 | Allows you to change the user that your PublicAPI object is 379 | authenticating with. 380 | 381 | "pass()" 382 | 383 | Allows you to change the password that your PublicAPI object is 384 | authenticating with, this will remove the stored accesshash from the 385 | object. 386 | 387 | "accesshash()" 388 | 389 | Allows you to change the accesshash that your PublicAPI object is 390 | authenticating with, this will remove the stored password from the 391 | object. 392 | 393 | "api_token()" 394 | 395 | Allows you to change the API token that your PublicAPI object is 396 | authenticating with, this will remove the stored password from the 397 | object. 398 | 399 | "format_http_query()" 400 | 401 | Allows you to construct formdata for an http query from a hash. For 402 | Example: 403 | 404 | $pubapi->format_http_query( { 'one' => '1', 'two' => 2 } ); 405 | 406 | would return: 407 | 408 | 'one=1&two=2' 409 | 410 | "format_http_headers()" 411 | 412 | Allows you to construct headers for an http query from a hash. For 413 | Example: 414 | 415 | $pubapi->format_http_headers( { 'Authorization' => 'Basic cm9vdDpsMGx1cnNtNHJ0IQ=='} ); 416 | 417 | would return: 418 | 419 | 'Authorization: Basic cm9vdDpsMGx1cnNtNHJ0IQ==\r\n' 420 | 421 | "$pubapi->{'error'}" 422 | 423 | Errors encountered within the class are stored here before being written 424 | out to the error_fh filehandle. This can be used for checking the 425 | existance of query errors. 426 | 427 | Bugs 428 | see http://rt.cpan.org to report and view bugs 429 | 430 | License 431 | Copyright (c) 2015, cPanel, Inc. All rights reserved. http://cpanel.net 432 | 433 | Redistribution and use in source and binary forms, with or without 434 | modification, are permitted provided that the following conditions are 435 | met: * Redistributions of source code must retain the above copyright 436 | notice, this list of conditions and the following disclaimer. * 437 | Redistributions in binary form must reproduce the above copyright 438 | notice, this list of conditions and the following disclaimer in the 439 | documentation and/or other materials provided with the distribution. * 440 | Neither the name of cPanel, Inc. nor the names of its contributors may 441 | be used to endorse or promote products derived from this software 442 | without specific prior written permission. 443 | 444 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 445 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 446 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 447 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 448 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 449 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 450 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 451 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 452 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 453 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 454 | POSSIBILITY OF SUCH DAMAGE. 455 | 456 | -------------------------------------------------------------------------------- /lib/cPanel/PublicAPI.pod: -------------------------------------------------------------------------------- 1 | =encoding UTF-8 2 | 3 | =head1 NAME 4 | 5 | cPanel::PublicAPI - A perl interface for interacting with cPanel 6 | 7 | =head1 SYNOPSIS 8 | 9 | use cPanel::PublicAPI; 10 | 11 | # Auto detect authentication information 12 | my $cp = cPanel::PublicAPI->new(); 13 | # or specify a user/password 14 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'pass' => 'somepass' ); 15 | # or specify an accesshash 16 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'accesshash' => $accesshash ); 17 | # or specify an API token 18 | my $cp = cPanel::PublicAPI->new( 'user' => 'someuser', 'api_token' => $api_token ); 19 | 20 | # Perform an xml-api query 21 | $cp->whm_api('listaccts'); 22 | # Pass parameters to the xml-api 23 | $cp->whm_api('createacct', {'username' => 'someuser', 'password' => 's0m3P4$$w()Rd' } ); 24 | # Return JSON from xml-api (rather than a hash reference) 25 | $cp->whm_api('version', undef, 'json'); 26 | 27 | # Perform an API2 query 28 | $cp->cpanel_api2_request('whostmgr', 29 | { 30 | 'module' => 'Email', 31 | 'func' => 'listpopswithdisk', 32 | 'user' => 'someuser', 33 | } 34 | ); 35 | # Perform an API2 query when authenticated as a user 36 | $cp->cpanel_api2_request('cpanel', 37 | { 38 | 'module' => 'Email', 39 | 'func' => 'listpopswithdisk', 40 | } 41 | ); 42 | # Pass parameters to an API2 call 43 | $cp->cpanel_api2_request('cpanel' 44 | { 45 | 'module' => 'Email', 46 | 'func' => 'addpop', 47 | }, 48 | { 49 | 'domain' => 'domain.com', 50 | 'email' => 'username', 51 | 'password' => 'SojmASDM(#(Jinasifodanosd', 52 | 'quota' => 200 53 | }, 54 | ); 55 | 56 | # Perform an API1 query 57 | $cp->cpanel_api1_request('whostmgr', 58 | { 59 | 'module' => 'LastLogin', 60 | 'func' => 'lastlogin', 61 | 'user' => 'someuser' 62 | } 63 | ); 64 | # Pass parameters to an API1 query 65 | $cp->cpanel_api1_request('cpanel', 66 | { 67 | 'module' => 'Mysql', 68 | 'func' => 'adduserdb', 69 | }, 70 | [ 'somedb', 'somedbuser', 'ALL' ] 71 | ); 72 | 73 | # perform an HTTP GET request against a URL 74 | $cp->api_request('whostmgr', '/xml-api/loadavg', 'GET'); 75 | 76 | # perform an HTTP GET request with parameters 77 | $cp->api_request('whostmgr', '/xml-api/createacct', 'GET', {'username' => 'someuser', domain => 'domain.com'} ); 78 | 79 | # perform an HTTP POST request (with parameters) 80 | $cp->api_request('whostmgr', '/xml-api/createacct', 'POST', {'username' => 'someuser', domain => 'domain.com'} ); 81 | 82 | =head1 DESCRIPTION 83 | 84 | cPanel::PublicAPI is a supported interface for interacting with cPanel's APIs over HTTP. 85 | This allows you to query either WHM or cPanel accounts from a perl interface. The purpose 86 | of this module is to provide an easy-to-use interface into cPanel's various APIs without 87 | requiring much knowledge of how they work. 88 | 89 | =head2 Object Construction 90 | 91 | a cPanel::PublicAPI object is constructed with the new() method. 92 | 93 | my $publicapi = cPanel::PublicAPI->new(); 94 | 95 | When passed no parameters, this will create the object using the accesshash in ~/.accesshash. If no .accesshash file exists, it will attempt to use the REMOTE_PASS environment variable. If the REMOTE_PASS variable is not defined, object creation will error out. 96 | 97 | =head3 new() parameters 98 | 99 | options for new() are specified as a hash reference, the following parameters are supported: 100 | 101 | =over 102 | 103 | =item * user - The username to authenticate as. 104 | 105 | =item * pass - The password to use for authentication. 106 | 107 | =item * accesshash - The accesshash to use for authentication (WHM only). 108 | 109 | =item * api_token - The API token to use for authentication. 110 | 111 | =item * timeout - The length of time (in seconds) before an http request should time out. Default to 300. 112 | 113 | =item * ip - The IP to be queried. defaults to 127.0.0.1, if host is defined it will take precedence over the 'ip' parameter. 114 | 115 | =item * host - The hostname to be queried. This will take precedence over the 'ip' parameter. 116 | 117 | =item * usessl - 1 or 0, Indicates whether communication should be performed over SSL or not (default to 1). 118 | 119 | =item * ssl_verify_mode - 1 or 0, Indicates whether to verify SSL certificates or not. (default to 1). 120 | 121 | =item * error_log - Path to where you want debug and error logging information to be written to. If this is not defined or the module is unable to open the path in question, it will default to STDERR. 122 | 123 | =item * debug - Enables debug logging, which will place considerably more information into the error_log. 124 | 125 | =item * http_tiny_creator - An optional code reference that receives the list 126 | of key/value pairs that normally goes into L’s constructor to 127 | create an instance of that class for this module’s internal use. The code 128 | reference, when called, should return an object that implements 129 | an HTTP::Tiny-compatible interface. 130 | 131 | This parameter is useful for customizing that internal 132 | HTTP::Tiny instance that cPanel::PublicAPI uses. Handle with care, though: 133 | this parameter may break cPanel::PublicAPI in various ways—some subtle, 134 | others less so. 135 | 136 | For example, if you want a custom User-Agent header, you might do: 137 | 138 | http_tiny_creator => sub { 139 | return HTTP::Tiny->new( 140 | @_, 141 | agent => 'My Custom UA String', 142 | ); 143 | }, 144 | 145 | =back 146 | 147 | =head3 Authentication methods 148 | 149 | This module supports three authentication methods: 150 | 151 | =over 152 | 153 | =item 1. Username & Password 154 | 155 | use cPanel::PublicAPI; 156 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'pass' => 'bar' ); 157 | 158 | =item 2. API Token 159 | 160 | (Note: This method does not work with Webmail.) 161 | 162 | To create an API token, visit "Manage API Tokens" in cPanel or WHM, and follow the appropriate prompts. 163 | Your token will appear in a special notice. Make certain that you save your API token in a safe location, as this is the only time the token will be shown 164 | to you. 165 | 166 | To use an API token with this module, do the following: 167 | 168 | use cPanel::PublicAPI; 169 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'api_token' => $string_containing_api_token ); 170 | 171 | =item 3. WHM Access Hash 172 | 173 | B Accesshash authentication is deprecated as of cPanel & WHM version 64. 174 | 175 | To configure accesshashes, you can either: 176 | 177 | =over 178 | 179 | =item * In cPanel & WHM version 66 and earlier, visit “Setup remote access key” 180 | in WHM which will generate an accesshash for your server if one does not already exist. 181 | 182 | =item * Run F. This will overwrite 183 | any existing access hash. 184 | 185 | =back 186 | 187 | The generated accesshash is stored in F<~/.accesshash>. 188 | 189 | To use an accesshash with this module, do the following: 190 | 191 | use cPanel::PublicAPI; 192 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'accesshash' => $string_containing_access_hash ); 193 | 194 | It should be noted that the accesshash can contain newlines in it. Newlines will be stripped by the object when 195 | it attempts to perform a query. 196 | 197 | =back 198 | 199 | =head3 Dependencies 200 | 201 | This module will fall back on different modules if one fails to load. This allows for compatibility with cPanel & WHM's internal perl parser and maintain compatibility with a standard perl implementation. The order that it will fall back on serialization modules is: 202 | 203 | =over 204 | 205 | =item * JSON::Syck 206 | 207 | =item * JSON 208 | 209 | =item * JSON::XS 210 | 211 | =item * JSON::PP 212 | 213 | =back 214 | 215 | If you installed this module via CPAN, this should never be an issue. If you are wishing to use this 216 | module on a system where you do not have access to compiled modules, JSON::PP is the recommended serializer. 217 | 218 | =head1 Two-Factor Authentication (2FA) 219 | 220 | cPanel version 54 and above allows users to configure 2FA on their accounts - this security policy requires that the API queries 221 | are performed after authenticating and establishing a session. The workflow to accomodate 2FA will be as so: 222 | 223 | use cPanel::PublicAPI; 224 | 225 | use lib '/usr/local/cpanel'; 226 | use Cpanel::Security::Authn::TwoFactorAuth::Google (); # only available in 11.54+ 227 | 228 | my $pubapi = cPanel::PublicAPI->new( 'user' => 'foo', 'pass' => 'bar' ); 229 | my $google_auth = Cpanel::Security::Authn::TwoFactorAuth::Google->new( 230 | { 231 | 'account_name' => 'foo', 232 | 'secret' => $user_2fa_secret, 233 | 'issuer' => '' 234 | } 235 | ); 236 | $pubapi->establish_tfa_session('whostmgr', $google_auth->generate_code()); 237 | $pubapi->whm_api('applist'); 238 | 239 | Anytime you change services (e.g. from 'whostmgr' to 'cpanel'), you must establish the 2FA session for the new service. 240 | 241 | eval { 242 | $pubapi->cpanel_api2_request('cpanel', { 'user' => 'foo', 'module' => 'MysqlFE', 'func' => 'listdbs' }, {} ); 243 | }; 244 | print "failed cause 2fa session wasn't established\n" if $@; 245 | 246 | $pubapi->establish_tfa_session('cpanel', $google_auth->generate_code()); 247 | eval { 248 | $pubapi->cpanel_api2_request('cpanel', { 'user' => 'foo', 'module' => 'MysqlFE', 'func' => 'listdbs' }, {} ); 249 | }; 250 | print "success\n" if not $@; 251 | 252 | B: Additionally, since accesshash authentication is not allowed to establish sessions, you must use the 'user'/'pass' 253 | authentication in order to make API requests as a user with 2FA configured. 254 | 255 | =head1 Important Methods 256 | 257 | =head2 Querying the xml-api - whm_api() 258 | 259 | The XML-API is WHM's API used for administrative functions is handled via the whm_api() method. 260 | 261 | The syntax for whmapi is: 262 | 263 | $cp->whm_api($call [, \%formdata, $format ] ); 264 | 265 | The meaning of these parameters is: 266 | 267 | =over 268 | 269 | =item * $call - The XML-API call you wish to query 270 | 271 | =item * $formdata - The parameters for the XML-API call in question, f.ex. for suspendacct, here you would pass in a hashref containing “user” and “reason”. If there are no parameters, this can be undef or a blank hash. 272 | 273 | =item * $format - The requested response format. The valid values here are “xml”, “json” or “ref” (perl hash reference). This will default to returning a perl hash reference when the value is undef. 274 | 275 | =back 276 | 277 | By default, WHM API v1 is used. If, for legacy reasons, you need to use v0, 278 | please set the C key to 0 in the formdata parameter. 279 | 280 | For more information on what calls are available and how they can be referenced, please see the xml-api documentation at L. 281 | 282 | =head2 Querying cPanel's APIs 283 | 284 | cPanel supports two APIs, designated "API1" and "API2". 285 | 286 | cPanel API calls are seperate into Modules, these module names relate to modules within the Cpanel namespace on a cPanel server. Each module defines a set of functions that are from either API1 or API2 (or both). 287 | 288 | There are two distinct differences between API1 and API2: 289 | 290 | =over 291 | 292 | =item * API1 Takes in ordered parameters and returns strings 293 | 294 | =item * API2 uses named parameters and returns hashes or arrays of hashes 295 | 296 | =back 297 | 298 | Within the context of the public api, calling a function from API1 or API2 will always return a hash, but the specific data returned from the API call will be contained within the 'data' key of the response. 299 | 300 | For more information on the differences between API1 and API2 please see the documentation: L 301 | 302 | For information on calling API1 and API2 direct via HTTP, please see: L 303 | 304 | =head3 cpanel_api1_request() 305 | 306 | C is used to query cPanel's API1, the function used for querying API1 has the following syntax: 307 | 308 | $cp->cpanel_api1_request($service, \%cfg [, \@params, $format ] ); 309 | 310 | =over 311 | 312 | =item * $service - The service that you wish to query. This can be 'cpanel' 'whostmgr', or 'webmail'. It is important to note that what services you are able to query depends on the user you are authenticated as. Only a user with reseller or root access can use the whostmgr service. If you are authenticated as root, you will not be able to query the 'cpanel' service. When the service is set to 'whostmgr' a 'user' must be set in the $cfg hash. 313 | 314 | =item * $cfg - A hash reference describing the call you wish to make. Required parameters are 'module' and 'func', which correspond to the module and function of the API call you wish to query. If you are querying the "whostmgr" service, you will need to specify 'user' as well. 315 | 316 | =item * $params - An array reference containing the parameters you wish to pass to the API call. 317 | 318 | =item * $format - The format for the xml-api to respond in. The valid values here are “xml”, “json” or “ref” (perl hash reference). This will default to returning a perl hash reference. 319 | 320 | =back 321 | 322 | To see what modules and functions are available for making API1 calls, please see: L 323 | 324 | =head3 cpanel_api2_request() 325 | 326 | C is used to query cPanel's API2, the function use for querying API2 has the following syntax: 327 | 328 | $cp->cpanel_api2_request( $service, \%cfg [, \%params, $format ] ); 329 | 330 | =over 331 | 332 | =item * $service - The service that you wish to query. This can be 'cpanel' 'whostmgr', or 'webmail'. It is important to note that what services you are able to query depends on the user you are authenticated as. A user that does not have reseller or root access will not be able to use the whostmgr service. If you are authenticated as root, you will not be able to query the 'cpanel' service. When the service is set to 'whostmgr' a 'user' must be set in the $cfg hash. 333 | 334 | =item * $cfg - A hash reference describing the call you wish to make. required parameters here are 'module' and 'func', which correspond to the module and function of the API call you wish to query. If you are querying the "whostmgr" service, you will need to specify 'user' as well. 335 | 336 | =item * $params - An hash reference containing the parameters you wish to pass to the API call. 337 | 338 | =item * $format - The format for the xml-api to respond in. The valid values here are “xml”, “json” or “ref” (perl hash reference). This will default to returning a perl hash reference when the value is undef. 339 | 340 | =back 341 | 342 | To see what modules and functions are available for making API2 calls, please see: L 343 | 344 | =head2 api_request() - Making direct URL requests to cPanel & WHM. 345 | 346 | There are some situations where you will need to query cPanel and WHM URLs directly. This should ONLY be done when there is not an API call available for the function you wish to query. 347 | 348 | The function used for querying URLs directly is api_request(). It will always return a string rather than converting the response into a hash reference. It uses the following syntax: 349 | 350 | $cp->api_request( $service, $uri, $method, \%formdata, $headers) 351 | 352 | =over 353 | 354 | =item * $service - The service that you wish to query. This can be 'cpanel' 'whostmgr', or 'webmail', when passed an numerical value, PublicAPI will query that port directly. 355 | 356 | =item * $uri - The URL you wish to query, e.g. '/xml-api/cpanel' 357 | 358 | =item * $method - 'GET' or 'POST' 359 | 360 | =item * $formdata - The data you wish to pass to the URL 361 | 362 | =item * $headers - Any additional headers are to be passed with the request. These can be either a flat string or as a hashref like {'headertitle' =E 'headerdata'} 363 | 364 | =back 365 | 366 | =head1 Other Features 367 | 368 | =over 369 | 370 | =item C 371 | 372 | =back 373 | 374 | See L above. 375 | 376 | =over 377 | 378 | =item C 379 | 380 | =back 381 | 382 | This function allows you to enable/disable debug mode by passing a value that evaluates to 'true' or 'false'. 383 | 384 | =over 385 | 386 | =item C 387 | 388 | =back 389 | 390 | Allows you to change the user that your PublicAPI object is authenticating with. 391 | 392 | =over 393 | 394 | =item C 395 | 396 | =back 397 | 398 | Allows you to change the password that your PublicAPI object is authenticating with, this will remove the stored accesshash from the object. 399 | 400 | =over 401 | 402 | =item C 403 | 404 | =back 405 | 406 | Allows you to change the accesshash that your PublicAPI object is authenticating with, this will remove the stored password from the object. 407 | 408 | =over 409 | 410 | =item C 411 | 412 | =back 413 | 414 | Allows you to change the API token that your PublicAPI object is authenticating with, this will remove the stored password from the object. 415 | 416 | =over 417 | 418 | =item C 419 | 420 | =back 421 | 422 | Allows you to construct formdata for an http query from a hash. For Example: 423 | 424 | $pubapi->format_http_query( { 'one' => '1', 'two' => 2 } ); 425 | 426 | would return: 427 | 428 | 'one=1&two=2' 429 | 430 | =over 431 | 432 | =item C 433 | 434 | =back 435 | 436 | Allows you to construct headers for an http query from a hash. For Example: 437 | 438 | $pubapi->format_http_headers( { 'Authorization' => 'Basic cm9vdDpsMGx1cnNtNHJ0IQ=='} ); 439 | 440 | would return: 441 | 442 | 'Authorization: Basic cm9vdDpsMGx1cnNtNHJ0IQ==\r\n' 443 | 444 | =over 445 | 446 | =item C<$pubapi-E{'error'}> 447 | 448 | =back 449 | 450 | Errors encountered within the class are stored here before being written out to the error_fh filehandle. This can be used for checking the existance of query errors. 451 | 452 | =head1 Bugs 453 | 454 | see http://rt.cpan.org to report and view bugs 455 | 456 | =head1 License 457 | 458 | Copyright (c) 2015, cPanel, Inc. 459 | All rights reserved. 460 | http://cpanel.net 461 | 462 | Redistribution and use in source and binary forms, with or without 463 | modification, are permitted provided that the following conditions are met: 464 | * Redistributions of source code must retain the above copyright 465 | notice, this list of conditions and the following disclaimer. 466 | * Redistributions in binary form must reproduce the above copyright 467 | notice, this list of conditions and the following disclaimer in the 468 | documentation and/or other materials provided with the distribution. 469 | * Neither the name of cPanel, Inc. nor the 470 | names of its contributors may be used to endorse or promote products 471 | derived from this software without specific prior written permission. 472 | 473 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 474 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 475 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 476 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 477 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 478 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 479 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 480 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 481 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 482 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 483 | --------------------------------------------------------------------------------