Unfixed

Member
May 26, 2016
6
0
1
Colorado
cPanel Access Level
Root Administrator
Hello, I am attempting to get uapi Fileman::upload_files to work. I get this error no matter what I use in the file-1 or dir key fields:

You must specify at least one file to upload.

My request looks like this:

Code:
$request = "/xml-api/cpanel?api.version=1&cpanel_xmlapi_user=test&cpanel_xmlapi_module=Fileman&cpanel_xmlapi_func=uploadfiles&cpanel_xmlapi_version=3&dir=" . urlencode('testdir') . "&file-1=" . urlencode("test.txt");
I have attempted urlencoding the entire request, just the key/value, and just the values. I have attempting using the xml-api php library as well as the WHM API 1 (the request above). I have also attempted using the API 2 (including using the correct key format) instead of the UAPI.

I should also point out that the above request is for WHM API 1, and when cpanel_xmlapi_verison is set to 3 upload_files does not work (as it is documented) vs uploadfiles which does work.

Has anyone had this issue before and fixed it? Thank you.
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,909
2,229
463
Hello,

Have you tried using the tutorial offered on our documentation website for this UAPI function? It's located at:

Tutorial - Use UAPI's Fileman::upload_files Function in Custom Code - Software Development Kit - cPanel Documentation

I used the completed Perl example, changed the authentication details, and it worked as expected with no additional steps required:

Code:
# /usr/local/cpanel/3rdparty/bin/perl cptest.pl
{
   "data" : {
      "failed" : 0,
      "succeeded" : 1,
      "uploads" : [
         {
            "file" : "nonindex.html",
            "reason" : "Upload of “nonindex.html” succeeded.",
            "size" : 58,
            "status" : 1,
            "warnings" : []
         }
      ],
      "warned" : 0
   },
   "errors" : null,
   "messages" : null,
   "metadata" : {},
   "status" : 1
}
Thank you.
 

Unfixed

Member
May 26, 2016
6
0
1
Colorado
cPanel Access Level
Root Administrator
Code:
<?php
// Log everything during development.
// If you run this on the CLI, set 'display_errors = On' in php.ini.
error_reporting(E_ALL);
// Declare your username and password for authentication.
$username = 'test';
$password = 'test123';
// Define the API call.
$cpanel_host = 'localhost';
$request_uri = "https://$cpanel_host:2083/execute/Fileman/upload_files";
// Define the filename and destination.
$upload_file = realpath("/home/test/public_html/test/test.html");
$destination_dir = "public_html";
// Set up the payload to send to the server.
if( function_exists( 'curl_file_create' ) ) {
  $cf = curl_file_create($upload_file);
} else {
  $cf = "@/".$upload_file;
}
$payload = array(
  'dir'  => urlencode( $destination_dir ),
  'file-1' => $cf
);
// Set up the cURL request object.
$ch = curl_init( $request_uri );
curl_setopt( $ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC );
curl_setopt( $ch, CURLOPT_USERPWD, $username . ':' . $password );
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
// Set up a POST request with the payload.
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
// Make the call, and then terminate the cURL caller object.
$curl_response = curl_exec( $ch );
curl_close( $ch );
// Decode and validate output.
$response = json_decode( $curl_response );
if( empty( $response ) ) {
  echo "The cURL call did not return valid JSON:\n";
  die( $response );
} elseif ( !$response->status ) {
  echo "The cURL call returned valid JSON, but reported errors:\n";
  die( $response->errors[0] . "\n" );
}
// Print and exit.
die( print_r( $response ) );
?>
I get the same error no matter how i manipulate the request.
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,909
2,229
463
Is the Perl example referenced in my previous response working on your system? Could you post the specific error message you are receiving when running the PHP script from the command line? Note you must enable display_errors in the php.ini file associated with the PHP binary you are using.

Thank you.
 

Unfixed

Member
May 26, 2016
6
0
1
Colorado
cPanel Access Level
Root Administrator
I get
Code:
The cURL call did not return valid JSON:
with that php script. I have display_errors enabled for my current PHP binary. The perl script gives me a 500 error when run in my cgi-bin. I used the exact code from the tutorial, only changing the login details. in my apache error_log I got:

Code:
malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "Can't connect to loc...") at test.pl line 61.
 End of script output before headers: test.pl
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,909
2,229
463
Could you open a support ticket using the link in my signature so we can take a closer look? You can post the ticket number here so we can update this thread with the outcome.

Thank you.
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,909
2,229
463
To update, it was determined the function was attempting to reach localhost via IPv6 address on the server. The resolution in the support ticket was to update the "localhost" entry in the script to the server's IP address.

Thank you.
 

Unfixed

Member
May 26, 2016
6
0
1
Colorado
cPanel Access Level
Root Administrator
Code:
<?php
error_reporting(E_ALL);

$username = 'user';
$password = 'pass';

$cpanel_host = 'hostip';
$request_uri = "https://$cpanel_host:2083/execute/Fileman/upload_files";

$upload_file = realpath("/path/to/file.txt");
$destination_dir = "some/dir";

if( function_exists( 'curl_file_create' ) ) {
  $cf = curl_file_create( $upload_file );
} else {
  $cf = "@/".$upload_file;
}
$payload = array(
  'dir'  => $destination_dir,
  'file-1' => $cf
);

$ch = curl_init( $request_uri );
curl_setopt( $ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC );
curl_setopt( $ch, CURLOPT_USERPWD, $username . ':' . $password );
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );

curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );

$curl_response = curl_exec( $ch );
curl_close( $ch );

$response = json_decode( $curl_response );
if( empty( $response ) ) {
  echo "The cURL call did not return valid JSON:\n";
  die( $response );
} elseif ( !$response->status ) {
  echo "The cURL call returned valid JSON, but reported errors:\n";
  die( $response->errors[0] . "\n" );
}

die( print_r( $response ) );
?>
So this script works after fixing a few issues, one being the ipv6 issue from the support ticket. I will leave this here for anyone that ever comes across this issue.

However, I am still stuck with my original issue, needing this to work with hash instead of password. I have written a script to connect and use the WHM xml-api however I always get the specify file error. I am completely stuck now. Do I need to submit a POSTFIELD request with the WHM api? Or do I send it in the URI? If so, how? Like I said, any documentation on how to do this would be great!

EDIT: FWIW here is my xml-api code that uses the cpanel php class:

Code:
          $upload_file = realpath("/home/account/public_html/host.txt");
           $destination_dir = "public_html/test";

           if( function_exists( 'curl_file_create' ) ) {
            $cf = curl_file_create( $upload_file );
           } else {
            $cf = "@/".$upload_file;
           }
           $payload = array(
            'dir'  => $destination_dir,
            'file-1' => $cf
           );

           $upload_file = $cpanel->uapi_query($account, 'Fileman', 'upload_files', array('file-1' => $cf, 'dir' => $destination_dir));
           $upload_file = simplexml_load_string($upload_file);
           var_dump($upload_file);
I understand the curl operation is probably useless, I have tried using many different formats without the curl function.

This gives the same error, but it creates the "test" directory.
 
Last edited:

Unfixed

Member
May 26, 2016
6
0
1
Colorado
cPanel Access Level
Root Administrator
I can make every API1/API2/UAPI call using WHM without issue with the exception of file_uploads, I get the must select a file error when I go through WHM. The script that works through 2083 is using a curl post, does the same thing need to happen with WHM? If I use an absolute path it doesn't do anything :/. Is there a way to view the Fileman functions? I can't find anything in the /usr/local/cpanel/Cpanel/API directory. If all else fails (pretty much has) I'll just resort to a custom UAPI module.
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,909
2,229
463
I have written a script to connect and use the WHM xml-api however I always get the specify file error. I am completely stuck now.
Internal case CPANEL-2806 was opened to report this issue to our development team. Per this case, this behavior is by design. Here's a paraphrased quote from the case:

We disallow file uploads since the form is parsed (and the file stored in a temporary file) before privileges are dropped. When we go to actually run the function call as the user, the file is not accessible. We have to parse the form before dropping privileges in order to know what user we need to run as.
Thank you.