When using cURL to send data via POST, if that data string is URL encoded or if parts of it are URL encoded, cURL automatically decodes the data when sending it.
This happens when using cURL in PHP or directly in the command line.
I've tested with 2 different version of cURL: 7.19 and 7.49. Both exhibit the same behavior
I've sent the cURL request from two different servers thinking that the the way the servers was configured somehow influenced this, but the result was the same.
Here is a simple PHP cURL request that I've used for my test:
$ua = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.A.B.C Safari/525.13';
$data = "https%3A%2F%2Fexample.com%3A8081%2Ftemoignez%3FQid%3D%26"
$ch = curl_init( "https://example.com/test/webhook.php" );
curl_setopt($ch, CURLOPT_USERAGENT, $ua);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "payload=".$data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec( $ch );
The data will be sent decoded even though the initial string is URL encoded.
I'm retrieving the data by dumping the POST data into a file on disk using PHP.
Is this normal? Any idea what may cause this?
You have two different assertions here:
cURL automatically decodes the data when sending it.
...
I've simply dumped the POST data into a file after retrieving it.
It is PHP that automatically DECODES the data when receiving it. It is NOT getting decoded upon sending it!
This integrates with the behaviour of other values, like cookie data, post and get variables, header information like referrer, ... everything get's decoded automatically when it is received, because it is expected to be sent encoded.
When you want to see the exact data that is getting send over the wires, use a tool like ngrep on port 80 to sniff the TCP HTTP traffic.
Related
I'm running into an issue with cURL while getting customer review data from Google (without API). Before my cURL request was working just fine, but it seems Google now redirects all requests to a cookie consent page.
Below you'll find my current code:
$ch = curl_init('https://www.google.com/maps?cid=4493464801819550785');
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
print_r($result);
$result now just prints "302 Moved. The document had moved here."
I also tried setting curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); but that didn't help either.
Does anyone has an idea on how to overcome this? Can I programmatically deny (or accept) Google's cookies somehow? Or maybe there is a better way of handling this?
What you need is the following:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
The above curl option is what tells curl to follow redirects. However, I am not sure whether what is returned will be of much use for the specific URL you are trying to fetch. By adding the above option you will obtain the HTML source for the final page Google redirects to. But this page contains scripts that when executed load the map and other content that is ultimately displayed in your browser. So if you need to fetch data from what is subsequently loaded by JavaScript, then you will not find it in the returned results. Instead you should look into using a tool like selenium with PHP (you might take a look at this post).
I'm trying to write a PHP script using cURL that will eventually run a bunch of test on a website to check for content, however I can't seem to get past the actual logging in part.
This is the code that I'm currently trying:
function loginCurl() {
$url = "https://mywebsite.com/main/login";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$login_page = curl_exec($ch);
$csrf = preg_replace("/_csrf\"\svalue=\"/", "", substr($login_page, strpos($login_page, "_csrf"), 70));
$username = "myEmail#mywebsite.com";
$password = "abcde12345";
$post_data = http_build_query(array(
'_csrf' => $csrf,
'LoginForm' => array (
'username' => $username,
'password' => $password,
'rememberMe' => 1
)
));
$HttpRequestHeaders = array(
"Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language:en-US,en;q=0.8",
"Cache-Control:max-age=0",
"Connection:keep-alive",
"Referer:https://mywebsite.com/main/login",
"Upgrade-Insecure-Requests:1"
);
curl_setopt($ch, CURLOPT_URL, "https://mywebsite.com/main/login");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
curl_setopt($ch, CURLOPT_HTTPHEADER, $HttpRequestHeaders);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
$home_page = curl_exec($ch);
curl_close($ch);
return $home_page;
}
However, every time that I run this code, I end up with the server responding with an HTTP 400 error, although my request isn't malformed as far as I can see.
When I log into the actual website with the developer view open in Chrome, I can open up the login page under network and see all the data getting passed in the form fields, and it's just the 5 things I've got in my code. I'm not entirely sure why it's sending the "rememberMe" checkbox twice, but no matter how many times I send that box, it fails anyways.
The issue here is that now, although I have identical form data and request headers as when I log in to the real site manually, I still get a 400 error.
I guess my real question then comes in a few different parts:
Is there a better way to be logging into the website remotely than using cURL. As far as I'm aware, this is the best way.
If this is the best way to be doing it, is there a better way to tell exactly what's getting sent when I log in to the page than looking at the developer view's Form Data that it logs.
If there is not better way than what I'm doing, is it possible that the site is inaccurately throwing a 400 error, and it should really be something else? If that is the case, how would I get past this bug?
Finally, because I don't know if it's relevant, here's the actual stuff getting logged in the developer view:
Request headers:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/ *;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:212
Content-Type:application/x-www-form-urlencoded
Cookie:_csrf=1c43726b4d2c2298b2667f1c9b47d420ee594f2de08a9ce928ee155b174c624aa%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22niY-LESiKNwZkfg7mclgTuBPDJeLACz2%22%3B%7D; PHPSESSID=itnbbfiph1gj2p9movpmi9pmb7
Host:mywebsite.com
Origin:https://mywebsite.com
Referer:https://mywebsite.com/main/login
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Form Data:
_csrf:Z0owR2dpVXQJI2lqKywGHSwERx0MDzJDCilcIDMcFyQjAFULJiovRg==
LoginForm[username]:myEmail#mywebsite.com
LoginForm[password]:abcdefg12345
LoginForm[rememberMe]:0
LoginForm[rememberMe]:1
This is the developer view only stuff that it only tracks if you have it open.
And this is the stuff it logs for the actual request to the web page:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/ *;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Cookie:_csrf=1c43726b4d2c2298b2667f1c9b47d420ee594f2de08a9ce928ee155b174c624aa%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22niY-LESiKNwZkfg7mclgTuBPDJeLACz2%22%3B%7D; PHPSESSID=i4ppm1ggcq1cq6hkvilesggr10; _identity=2ca675db2d582db9f7ab8761cc0a07a14e2e2dece90386b11392b270637b0559a%3A2%3A%7Bi%3A0%3Bs%3A9%3A%22_identity%22%3Bi%3A1%3Bs%3A19%3A%22%5B1267%2Cnull%2C2592000%5D%22%3B%7D
Host:mywebsite.com
Referer:https://mywebsite.com/main/login
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
This is the tag in the sites HTML that contains the csrf token, when I echo the csrf, it displays as should. I don't believe there's a parsing error, however it does appear differently in the HTTP response headers, which is strange to me.
<input type="hidden" name="_csrf" value="T25ZVmZGZi4hBwB7KgM1RwQgLgwNIAEZIg01MTIzJH4LJDwaJwUcHA==">
I hope someone is able to help me out with this, I've been going at it for a few days now!
you do a couple of mistakes,
your post_data is not properly encoded, [ should be %5B , and the ] should be %5D, like
"&LoginForm%5Busername%5D=" . urlencode($username)
, furthermore, you're redefining LoginForm[rememberMe] to both 0 and 1 in the same form, pretty sure that's not legal.
but rather than making the encoded string yourself, which is ugly and (as you have just proven) error-prone, have http_build_query do it for you, like this:
$post_data = http_build_query ( array (
'_csrf' => $csrf,
'LoginForm' => array (
'username' => $username,
'password' => $password,
'rememberMe' => 1
)
) );
and you say that you "Accept-Encoding:gzip, deflate, sdch, br" , but you provide no code to handle any of those encodings, should the server decide to use any of them, and your loginCurl() function has no way of telling the caller which encoding the server decided to use.. best way of handling that, is to have curl handle encodings for you, automatically. don't send the accept-encoding header yourself, but set CURLOPT_ENCODING to emptstring '', and curl will automatically accept-encoding: <all encodings that libcurl was compiled with here> - and automatically decode it, if the server decided to use an encoding.
and you set the "Host: header manually, don't do that, let curl set it for you, as curl_initdoes for you (or use CURLOPT_URL), furthermore, you probably want to use CURLOPT_USERAGENT rather than setting the useragent header yourself (its easy to forget if you do it manually)
also, some pages can detect that you're faking the referrer header, you should probably just set CURLOPT_AUTOREFERER, and make a GET request to the url you want a referrer from first, rather than faking the referrer header :P
question Is there a better way to be logging into the website remotely than using cURL. As far as I'm aware, this is the best way. - if there's not a specific api for the website, then, in my experience, (lib)curl is the best way to log in like a browser.
question If this is the best way to be doing it, is there a better way to tell exactly what's getting sent when I log in to the page than looking at the developer view's Form Data that it logs. - idk, but 99% of the time, chrome developer tools works fine for me. sometimes, i have to resort to Fiddler Proxy or ReDox Packet Editor, when i want analyze non-browser applications, though..
question If there is not better way than what I'm doing, is it possible that the site is inaccurately throwing a 400 error, and it should really be something else? If that is the case, how would I get past this bug?
- well, as i've said higher up, you're doing it wrong here, but when it works in the browser, and doesn't work in curl, the trick is compare the request that curl does, with the request that chrome does, and systematically take away every single difference between the curl-based request and browser-based request, until they're exactly equal, and retrying every step of the way.. FiddlerProxy and netcat (common in Linux, needs Cygwin in windows) comes in handy here
edit 9001:
PS, looking at the test data you provide, looks like your preg $csrf = preg_replace(... code isn't able to properly extract the CSRF token. your curl csrf Z0owR2dpVXQJI2lqKywGHSwERx0MDzJDCilcIDMcFyQjAFULJiovRg== looks nothing like the recorded csrf 1c43726b4d2c2298b2667f1c9b47d420ee594f2de08a9ce928ee155b174c624aa%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22niY-LESiKNwZkfg7mclgTuBPDJeLACz2%22%3B%7D
My shared hosting does not support postgresql php functions, but I need to load some images from postgresql which is hosted remotely on a dedicated server.
Would it be possible to have a PHP script on the server with postgresql and then another PHP script on the shared hosting would call the script on the postgresql server to get the images from the dedicated server to the shared hosting but I don't want the IP or domain of the dedicated server ever to be revealed.
Would this be possible? if so how?
it's even much easier with file_get_contents():
$img_binary = file_get_contents("https://i.imgur.com/1H9Ht5a.png");
$img_base64 = base64_encode($img_binary);
echo '<img src="data:image/png;base64,' . $img_base64 . '">';
plus: it's a standard PHP method where "cURL" might not be activated in every PHP environment.
be careful with the type of your image. replace data:image/png; with data:image/jpeg; or other image formats accordingly.
Yes it's possible. However, you need to make a JSON API: the server wich serve postgresql needs to fetch results from Database, then encode it in json with json_encode() method and return it with echo.
Then, you need to make an HTTP request from your shared hosting using CURL, here's an example:
function GetContent($url) {
$curl = curl_init();
$ua = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36";
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl ,CURLOPT_USERAGENT, $ua);
curl_setopt($curl, CURLOPT_COOKIESESSION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
$return = curl_exec($curl);
curl_close($curl);
return $return;
}
Then, call the function:
$sql = json_decode(GetContent('http://urlofyourserver/testJSON.php'));
You can now get the result in the $sql variable :)
Oh and don't forget, make a password request using $_GET requests on your server wich serves postgresql, otherwise everyone will be able to access to data if they found your server URL.
e.g: http://urlofyourserver/testJSON.php?secret=xxx
You can also pass the query as a get parameter, but It can be risked if your password is cracked.
Postgresql server sample
$realPass = "blablah";
if(isset($_GET['secret'])) {
$pass = $_GET['secret'];
if($pass === $realPass) {
header('Content-type: application/json');
// do query here and return it as $test var
echo json_encode($test);
}
}
You could use php curl
Example that will send the get parameters get1 and get2 to a test.php on a server with IP 192.168.2.2
// Get cURL resource
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'http://192.168.2.2/test.php?get1=value&get2=value2',
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'
));
// Send the request & save response
// The response could be JSON with the results from the database
$resp = curl_exec($curl);
// Close request to clear up some resources
curl_close($curl);
You could use PHP to encode and decode your results in JSON to make things easier. To do this use json_encode() and json_decode()
If you want some more information check out:
http://codular.com/curl-with-php
http://php.net/manual/en/curl.examples.php
http://php.net/manual/en/curl.examples-basic.php
I just came up with another idea that is much better imho; it also might be better in terms of security.
use a PHP script that simulates being an image file:
// example code for getting binary image data from db
// (PDO and MySQL in this example)
$stmt = $pdo->prepare( "SELECT image_bin FROM image_table WHERE id = :id LIMIT 1" );
$stmt->bindValue(":id", $_GET["id"], PDO::PARAM_INT);
$stmt->execute();
$image_bin = $stmt->fetchColumn();
header('Content-Type: image/png');
echo $image_bin;
on the page where you want to show the image you don't even need to use PHP:
<img src="http://myimageserver.com/image.php?id=3425">
in this example you just need to use the GET variable id to define/decide which image is shown. most of the work is done on the remote server where you could grab the desired image by using POSTGRESQL like you mentioned.
I have a peculiar issue.
I have a script which fetches a JSON. It works perfectly fine in the browser (gives the correct json). For eg. accessing the URL
http://example.com/json_feed.php?sid=21662567
in browser gives me following JSON (snippet shown):
{"id":"21662567","title":"Camp and Kayak in Amchi Mumbai. for 1 Booking...
As can be seen, the sid (of URL) and id of JSON match and is the correct json.
But the same URL when accessed via file_get_contents, gives me wrong result. The code is rather trivial and hence, I am completely stumped as to why this will happen.
$json = file_get_contents("http://example.com/json_feed.php?sid=21662567");
echo "<pre>";
var_dump($json);
echo "</pre>";
The JSON response of above code is:
string(573) "{"id":"23160210","title":"Learn about Commodity Markets (Gold\/Silver) for...
As can be seen, sid and id don't match now and the JSON fetched is incorrect.
I tried using curl also, thinking that it could be some format issue, but to no avail. curl also fetches the same incorrect JSON.
At the same time, accessing the original URL in browser will fetch the correct JSON.
Any ideas on what's happening here?
EDIT by Talvinder (14 April, 2014 at 0913 IST)
ISSUE SPOTTED: the script json_feed.php is session dependent and file_get_contents doesn't pass session values. I am not sure how to build the HTTP_REQUEST in cURL. Can someone help me with this? My current cURL code is:
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 OPR/20.0.1387.91');
curl_setopt($ch, CURLOPT_URL,$url);
$result=curl_exec($ch);
Where $url is the url given at the beginning of the question.
EDIT by TALVINDER(14 april, 1805 IST)
Killed the links shared earlier as they are dead now.
EDIT by TALVINDER (14 april, 0810 IST):
JSON can be seen here: JSON GENERATOR
file_get_content results can be seen here: file_get_contents script
Without any links that we can investigate, I guess there's some sort of user-agent magic going on.
Try spoofing it with cURL.
Someting like this:
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36 OPR/20.0.1387.91');
You can use your own user agent or find something else here.
Not 100% this is the issue, but considering the data provided by you, this is the only solution I can think of. I am sure you've double checked that the urls etc are correct in the scripts etc.
Figured out the issue and sharing it here for others to take note of:
Lesson 1
file_get_contents doesn't pass session or cookies to the URL, so don't use it to fetch data from URLs which are session or cookie dependents
cURL is your friend. You will have to build full HTTP request to pass proper session variables
Lesson 2
Session dependent scripts will behave properly when accessed via browser but not when accessed via file_get_contents or partially formed cURL
List item
Lesson 3
When the code is too trivial and yet buggy, Devil is in details - question every little function (apologies for philosophical connotation here :) )
SOLUTION
The json_feed.php I created is session dependent. So it was being naughty when accessed via file_get_contents. With cURL too it wasn't behaving properly.
I changed the cURL to include suggestions given here: Maintaining PHP session while accessing URL via cURL
My final cURL code (which worked is below):
$strCookie = 'PHPSESSID=' . $_COOKIE['PHPSESSID'] . '; path=/';
session_write_close();
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt( $ch, CURLOPT_COOKIE, $strCookie );
curl_setopt($ch, CURLOPT_URL,$url);
$result = curl_exec($ch);
curl_close($ch);
I hope it saves some time for someone.
Thanks for all the replies.
I'm trying to write a simple PHP script which automatically sets up new etherpads (see http://etherpad.com/).
They don't have an API (yet) for creating new pads so I'm trying to figure if I can do things another way.
After playing around some, I found that if you append a random string to etherpad.com to a not-yet-created pad, it'll come back with a form asking if you want to create a new etherpad at that address. If you submit that form, a new pad will be created at that URL.
My thought then was I could just create a PHP script using CURL that would duplicate that form and trick etherpad into creating a new pad at whatever URL I give it. I wrote the script but so far I can't get it working. Can someone tell me what I'm doing wrong?
First, here's the HTML form on the etherpad creation page:
`
<p><tt id="padurl">http://etherpad.com/lsdjfsljfa-fdj-lsdf</tt></p>
<br/>
<p>There is no EtherPad document here. Would you like to create one?</p>
<input type="hidden" value="lsdjfsljfa-fdj-lsdf" name="padId"/>
<input type="submit" value="Create Pad" id="createPad"/>
`
Then here's my code which tries to submit the form using CURL
$ch = curl_init();
//set POST variables
$url = "http://etherpad.com/ep/pad/create?padId=ldjfal-djfa-ldkfjal";
$fields = array(
'padId'=>urlencode("ldjfal-djfa-ldkfjal"),
);
$useragent="Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)";
// set user agent
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
//url-ify the data for the POST
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value; }
print_r($fields_string);
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
//execute post
$result = curl_exec($ch);
print_r($result);
//close connection
curl_close($ch);
When I run the script, PHP reports back that everything executed correctly but etherpad doesn't create my pad. Any clues what's going on?
I have not investigated this specific site but I guess there are some important headers which are missing. Here is a very general approach that is applicable for nearly any website:
Use a network sniffer such as Wireshark to capture all connectons. Then compare the sent POST fields with yours.
An even easier way is to use Netcat. Just save the page to disk, change the form-URL to http://localhost:3333/ and run
$ nc -l -p 3333
Now open the local HTML file and fill in the fields appropriately. Immediately you will see all headers that would have been transmitted to the host.
(There are also extensions for Mozilla Firefox but in general they just slow down the browser without providing much benefit.)
Also read what I have posted on To auto fill a text area using php curl as it might help you with your realization in PHP.
By the way, you are sending the parameter "padId" via GET and POST. That is not necessary. Check what the Etherpad-form actually uses and stick with it.
My guess is that you're missing the cookies and/or the referrer. It may be checking the referrer to ensure people aren't creating pads without confirmation.
Wireshark will help, but add that to your curl and see if it works.
Here's the answer a friend helped me come up with:
They're apparently doing some cookie
validation, that's why your script
isn't working. You can find this out
by loading the new pad creation prompt
page, clearing your cookies, and then
reloading the page. It won't work.
Tricky, but effective for most casual
bots.
Here's a script that gets around the
limitation. Just insert your desired
$padId and away you go.
<?php
$padId = 'asdfjklsjfgadslkjflskj';
$ch = curl_init();
# for debugging
curl_setopt($ch, CURLOPT_HEADER, true);
# parse cookies and follow all redirects
curl_setopt($ch, CURLOPT_COOKIEFILE, '/dev/null');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
# first, post to get a cookie
curl_setopt($ch, CURLOPT_URL, 'http://etherpad.com/' . urlencode
($padId));
$result = curl_exec($ch);
echo $result;
# next, post to actually create the etherpad
curl_setopt($ch, CURLOPT_URL, 'http://etherpad.com/ep/pad/create');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'padId=' . urlencode($padId));
$result = curl_exec($ch);
echo $result;
curl_close($ch);
To create a file directly from HTML or TEXT
Use the setText or setHTML API endpoint. http://etherpad.org/doc/v1.5.0/#index_sethtml_padid_html
To easily do this use the Etherpad PHP Client https://github.com/TomNomNom/etherpad-lite-client
To post from a file
This feature is provided by an Etherpad plugin. To enable it...
Install the Etherpad ep_post_data plugin by typing npm install ep_post_data on your Etherpad instance.
At your client machine CLI type: curl -X POST -d #yourfile.here http://youretherpad/post
Replace yourfile.here with your file
Replace the url with the Etherpad instance you want to work to.
Source: http://blog.etherpad.org/2014/12/17/post-to-etherpad-with-this-simple-plugin/