Mar 29, 2010
9
0
51
Hi,

Before someone says it, I have searched for this on the forum, Google etc... I could only come up with the following: WritingCpanelModules < SoftwareDevelopmentKit < TWiki

But I personally don't think it is very well explained... Plus, I think it's talking about calling API functions, not creating them for access over HTTP.

I am fluent in PHP, but never written a line of Perl... I don't plan learning the entire language for something simple like I need to do, so if someone could point me in the correct direction or write an example for me, I would be very grateful! :)

Basically all I need to do is execute a line of code... the code will be modifying accounts files directly. The API will be called as root. It will be passes a username & the rest is static, that's all.

Does that make sense? I hope so, I'm stuck for searching, I can't find anything like this, althought I'm sure there must be.

Thank you in advance,

Josh
 

cPanelDavidN

Well-Known Member
Staff member
Dec 17, 2009
571
3
68
Houston, TX
cPanel Access Level
Root Administrator
Hi Josh,

That documentation is the correct starting point for creating custom API calls. Currently, on APIs design for cPanel (not WHM) can be created. Fortunately, all cPanel APIs (eg, API1 & API2) can be call, not only locally for use in the cPanel UI, but remotely ala the XML/JSON-API.

However, cPanel APIs are typically designed to be run as the cPanel user, not root. If I understand properly, you want root to do stuff related to the user, as opposed to a user doing particular actions as a privilege user (ie, root). There's a distinction. If you want the latter, then there's a way you can perform privilege escalation that's documented here.

I'm happy to explain (hopefully in a meaningful way) how to create custom cPanel modules, but I'm wonder if it's really the solution that's best for you? If you have root access, and you're performing file manipulations, won't it make sense to create a shell script? And there are pure PHP SSH/SCP clients out there, so you can copy/trigger the remote script even within a web application.

Let me know you're thoughts, and we can press onwards accordingly.

Regards,
-DavidN
 
Mar 29, 2010
9
0
51
Hi David,

Thank you for your detailed reply. Basically, I will be calling this function (or existing function, but I can't see one to do this) to change the permissions on an account. Simply to comply with suPHP etc, incase a clients break them & starts to receive 500 Int Server Errors.

I would like to call the JSON API & authenticate as root, which I will be supplying with a hash. I then need to change the permissions on the account with the specified username...

I hope that makes sense...

Thanks again.
 

cPanelDavidN

Well-Known Member
Staff member
Dec 17, 2009
571
3
68
Houston, TX
cPanel Access Level
Root Administrator
Josh,

There really isn't an API for what you want. You have three choices:

1) make your own API2 custom module that we validate the requested action then escalates to root to perform the action.
2) you could utilize a combination of API2 Fileman::listfiles, Fileman::fileop to recursively fetch the filenames and then perform a chmod on them (I assume that is the only "permissions" that your talking about; if you need to chown, this method won't work because Fileman::fileop don't have that option)
3) do the operation via SSH.

I kinda think that a options 3 will be the simplest and most straight forward to maintain.

Regards,
-DavidN

If, by chance, you decide to do method 2, here's a sample in PHP (using the PHP XML-API client class) of how to recursively fetch the file list...just something I whipped up to see how feasible it was
PHP:
require "xmlapi.php";

//////////////////////////////////////////////////////////////////
// Extend PHP Class ///////////////////////////////////////////

class CustomXmlapi extends xmlapi
{
    private $cpuser;
    
    public function __construct($host = null, $user = null, $pass = null) 
    {
        parent::__construct($host,$user,$pass);
        $this->set_output('json');
        return $this;
    }
    
    public function set_cpuser($user)
    {
        $this->cpuser = $user;
        return $this;
    }
    
    public function get_dir_list($listdir)
    {
        $args = array(
        	'dir'          => $listdir,
            'checkleaf'    => 1,
            'showdotfiles' => 0,
            'types'        => 'dir|file',
        );
        
        $list = $this->api2_query($this->cpuser, 'Fileman', 'listfiles', $args);
        $list = $this->_getValidResult($list);
        $files = array();
        $rdirs = array();
        foreach($list as $item) {
            if ( $item['type'] == 'file'){
                #just a normal file
                array_push($files, $item['fullpath']);
            } elseif ( $item['type'] == 'dir' && $item['isleaf'] == 1) {
                #a directory that contains files;
                array_push($rdirs, $item['fullpath']);
            }
        }
        foreach( $rdirs as $dir) {
            $tmp_files = $this->get_dir_list($dir);
            foreach( $tmp_files as $more ){
                array_push($files, $more);
            }
        }
        return $files;
    }
    
    private function _getValidResult( $json_str ) 
    {
        $arr = json_decode($json_str,1);
        if ( $arr === null || !is_array($arr)) {
            return null;
        } elseif ( !array_key_exists("cpanelresult", $arr)
          || !is_array($arr['cpanelresult']) 
          || !array_key_exists("data", $arr['cpanelresult']) 
          || !is_array($arr['cpanelresult']['data'])) {
            return null;
        }
        
        return $arr['cpanelresult']['data'];
    }
}

//////////////////////////////////////////////////////////////////
// Main script //////////////////////////////////////////////////

$ip = 'my.server.net';
$loginUser = 'root';
$accessHash = get_file_contents('/stored/root/.accesshash');
$user = 'mycpanel';  //user with permission issues

$xmlapi = new CustomXmlapi($ip);
$xmlapi->set_user($loginUser);
$xmlapi->set_hash($accessHash);
$xmlapi->set_port(2087);

$xmlapi->set_cpuser($user);

//$xmlapi->set_debug(1);

$list = $xmlapi->get_dir_list('public_html');
//var_dump($list);

// Now that we have list we can use Fileman::fileop to perform a chmod on the files.
 
Mar 29, 2010
9
0
51
Sweet, thanks David.

I will try it out & build it into my app & get back to you to let you know it worked (Fingers corssed! :) )

Have a great day.
 
Mar 29, 2010
9
0
51
Worked like a charm, thank you David! I simply sepperated the output into files & folders, then called to mod the permissions on each type in two calls. Total thing only uses 3 calls to the API! (More depending on the depth of the dir)

Thanks again! :)
 
Last edited: