Andy Fletcher

Registered
Oct 8, 2010
4
0
51
Does anyone have a working code sample for using the Fileman::uploadfiles API call?

I've tried lots of different combinations of stuff to get it to work but it never seems to do the upload. I'm sure it's just me missing something obvious.

Cheers,

Andy
 

cPanelDavidN

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

If you have any sample code, I'm sure we can work it out. My understanding is that if you use this API call, you'll need to be sending a multi-part POST request. Does your code do that?

Regards,
-DavidN
 

Andy Fletcher

Registered
Oct 8, 2010
4
0
51
Hi David,

Wow, a support forum that does actual support. I'm very impressed ... and grateful :)

Apologies for not including my current code in the OP, here goes -

PHP:
$fp = fopen( 'zip.zip', 'r' );
	
	if ( $fp ) {
		echo "Opened Successfully\n";
	} else {
		echo "Failed to Open\n";
	}

	$ch = curl_init();
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_VERBOSE, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    curl_setopt($ch, CURLOPT_UPLOAD, 1);
 	curl_setopt($ch, CURLOPT_INFILE, $fp);
 	curl_setopt($ch, CURLOPT_INFILESIZE, filesize( 'zip.zip' ) );
    
 	$header = array();
 	
 	// $user and $pass are definitely correct and tested against
 	// a call in the xmlapi library to see they work
 	$authstr = 'Authorization: Basic ' . base64_encode($user .':'. $pass) . "\r\n";
 	
 	$data = array(
 		'cpanel_xmlapi_user' => $user,
 		'cpanel_xmlapi_module' => 'Fileman',
 		'cpanel_xmlapi_func' => 'uploadfiles',
 		'cpanel_xmlapi_apiversion' => '1',
 		'dir' => '/public_html/cpaneltest.com',
        'file1' => 'file-zip.zip'
 	);

 	// I'd normally use http_build_query but cpanel throws an error about no module defined when
 	// I do that.  I suspect because of the & being used instead of & as the whole thing gets URL encoded
 	$postdata = '';
 	$first = true;
 	foreach ( $data as $key => $value ) {
 		if ( ! $first ) {
 			$postdata .= '&';
 		}
 		$key = urlencode( $key );
 		$value = urlencode( $value );
 		$postdata .= "$key=$value";
 		$first = false;
 	}

 	$header[0] =$authstr.
			"Content-Type: application/x-www-form-urlencoded\r\n" .
			"Content-Length: " . strlen($postdata) . "\r\n" . "\r\n" . $postdata;
 	
 	// from the xmlapi cpanel library
 	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
 	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
 	curl_setopt($ch, CURLOPT_BUFFERSIZE, 131072);
 	
 	// standard stuff
	curl_setopt($ch, CURLOPT_HTTPHEADER, $header);  
    curl_setopt($ch, CURLOPT_URL, "https://$host:2083/xml-api/cpanel" );
    curl_setopt($ch, CURLOPT_POST, true);
    //curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
    
    $response = curl_exec($ch);
    $info = curl_getinfo( $ch );
    
    print_r( $info );
    print_r( $response );
And the result returned -

Code:
<cpanelresult><module>Fileman</module><func>uploadfiles</func><type>event</type><source>internal</source><apiversion>1</apiversion><data><result></result></data>  <event> 
    <result>1</result> 
  </event> 
</cpanelresult>
Any and all thoughts gratefully received.

Cheers,

Andy
 

cPanelDavidN

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

Your code looks sound. I ran it and got the same results as you. Upon further investigation, it looks like the Fileman::uploadfiles is one of the API1 oddities that is, well, simply a pain in the rear...

API1 calls are suppose to accept ordered arguments. This paradigm falls complete flat on it's face when we examine the requirements of the call, documented here.

Digging further into cPanel path execution, it looks like the Fileman::uploadfiles() actually is reading the parameter arguments from an internal hash, which will only be populated when the request is for a cPanel page, and not an XML-API request, instead of receiving them by reference (so to speak). Thus, no matter what arguments we send, if the request is via XML-API, the function will not receive those parameter arguments...:mad: Consequentially, Fileman::uploadfiles() cannot be successfully invoked via the XML-API -- only through a cPanel page.

The solutions I see are:

1) use PHP's ftp functions to upload the file. Each cPanel account has an FTP user with the same credentials and the cPanel login.

2) Make a custom API2 function that can populate the internal hash before relying the call to Fileman::uploadfiles(). This actually may not be an option for a couple of reasons. One, the Fileman module is compiled and I'm not certain exactly how/if we can wrap/invoke it within an uncompiled Perl module. As well, I'm not sure if we could successfully and safely populate the internal hash.

I will have to investigate option #2 further and get back with you. Sorry there isn't a more simple or direct solution, other than FTP.

Best Regards,
-DavidN
 

cPanelDavidN

Well-Known Member
Staff member
Dec 17, 2009
571
3
68
Houston, TX
cPanel Access Level
Root Administrator
I guess there's a 3rd option:

code against the cPanel html interface...that is, POST to the cPanel URL. If your user is using the x3 theme, it would be
https://$host:2083/frontend/x3/files/doupload.html
However, I think this is would be a very poor decision:
1) you can't count on the user as always using the x3 theme.
2) the x3, or whatever theme the user is using, can change without notice

I never advise developers to code against the html interface. But if you're in a pinch, that is a decision you can evaluate for yourself ;)

-DavidN
 

Andy Fletcher

Registered
Oct 8, 2010
4
0
51
Thanks David!

I was originally doing option 1 but since I need to call the extract API function I thought it'd be easier to do it all via the fileman module. You live and learn :)

I'll swap back to the FTP code and just do the extract via the API.

I'd appreciate it if you'd update the Wiki. I have no problem losing a bit of time to this myself (we didn't know this before) but since we do now it'd be a crime to let other's waste the same time.

Cheers,

Andy
 

Andy Fletcher

Registered
Oct 8, 2010
4
0
51
Hi David,

Just wanted to take a moment to pop back and say thanks for your help. I've got what I needed working now using FTP and then the extractfiles API call.

I really appreciate your help. You saved me from hours of head banging against an API call that would never have worked.

Cheers,

Andy