accessing $_SESSION when using file_get_contents in PHP - php

I have a page called send.email.php which sends an email - pretty simple stuff - I pass an order id, it creates job request and sends it out. This works fine when used in the context I developed it (Use javascript to make an AJAX call to the URL and pass the order_id as a query parameter)
I am now trying to reuse the exact same page in another application however I am calling it using php file_get_contents($base_url.'admin/send.email.php?order_id='.$order_id). When I call the page this way, the $_SESSION array is empty isempty() = 1.
Is this because I am initiating a new session using file_get_contents and the values I stored in the $_SESSION on login are not available to me within there?
--> Thanks for the feedback. It makes sense that the new call doesn't have access to the existing session...
New problem though:
I now get: failed to open stream: HTTP request failed! When trying to execute:
$opts = array('http' => array('header'=> 'Cookie: ' . $_SERVER['HTTP_COOKIE']."\r\n"));
$context = stream_context_create($opts);
$contents = file_get_contents($base_url.'admin/send.sms.php?order_id='.order_id, false, $context);
YET, the URL works fine if I call it as: (It just doesn't let me access session)
$result file_get_contents($base_url.'admin/send.sms.php?order_id='.$order_id);

file_get_contents() shouldn't be used anywhere you need authentication/session information transmitted. It's not going to send any cookies, so the user's authentication information will not be included by default.
You can kind of hack around it by including the session identifier (e.g. 'PHPSESSID' by default) as a query parameter in the URL, and have the other script check for that. But transmitting session identifiers in the URL is horribly bad practice, even if it's just to the same server.
$contents = file_get_contents("http://.... /send_sms.php?order_id=$order_id&" . session_name() . '=' . session_id());
To do this properly, use CURL and build a full HTTP request, including the cookie information of the parent page.

you'd have to include the file or call the respective functions from your send.sms.php script. instead you call it like a webservice (which it isn't)

Related

How to use get_file_contents in PHP when authorization is needed for URI?

I'm making a request to retrieve a JSON file to a server at a particular secure DocuSign uri. However, unless I put in the authorization information (which I do have), I am unable to have the file returned.
<?php
$json = file_get_contents("https://example.docusign.com/sensitiveIDs/moreID");
echo $json
?>
Where would I put in authorization information for the specific server/username/password/other info needed to access the particular DocuSign server using a method like this in PHP? Is there a better method to use for this scenario in PHP?
It depends on how the authorization is implemented. If its basic or digest HTTP authentication then specify it in the URL:
file_get_contents("https://$USER:$PASSWORD#example.docusign.com/sensitiveIDs/moreID");
Cookie based authentication is a lot more difficult (and probably easier to use Curl or even a more complex system like Guzzle. If its oauth2, then you probably want an oauth2 library.
Your call needs to include authentication to make the GET call to retrieve the file.
If your app is initiated by a human use Oauth to retrieve access and refresh tokens. Then included the access token with the GET request.
If your app is a "system app" that wants to autonomously retrieve the file, then you should authenticate by using X-DocuSign-Authentication -- include the following header in your HTTPS request. Since the request is HTTPS, the content is encrypted on the wire:
X-DocuSign-Authentication: <DocuSignCredentials><Username>{name}</Username><Password>{password}</Password><IntegratorKey>{integrator_key}</IntegratorKey></DocuSignCredentials>
Replace {name} with your email address (no braces), etc.
The bottom line is that you can't use the file_get_contents Php method. Instead, you'd do something like the following:
Use https://github.com/rmccue/Requests or a similar library to help with the https request. (http is not allowed due to security issues.)
(untested code)
$url = $base_url . $the_url_section_for_this_call
$headers = array('X-DocuSign-Authentication' =>
'<DocuSignCredentials><Username>your_name</Username><Password>your_password</Password><IntegratorKey>your_integrator_key</IntegratorKey></DocuSignCredentials>');
$request = Requests::get($url, $headers);
# Check that the call succeeded (either 200 or 201 depending on the method
$status_code = $request->status_code;
if ($status_code != 200 && $status_code != 201) {
throw new Exception('Problem while calling DocuSign');
}
$json = $request->body;

Why does ini_get('user_agent') doesn't work with file_get_contents() in php?

I have a situation like this.
A crawler script fetches the content of the URL using
file_get_contents().
It sets the user agent as "CrawlerBot" just
above the line where file_get_contents() is called using
ini_set('user_agent').
My concern is when I write ini_get('user_agent') in the code of URL, it gets a blank value. However when I use $_SERVER['HTTP_USER_AGENT'] it detects the correct user agent. Both the files are hosted on same server.
Anybody aware why does it happen?
That's not what ini_get() does. It's for retrieving server configuration values (the configuration of your server), not request-specific values like the user agent sent by a requesting browser/script/whatever.
So, you can use ini_get() to find out what user agent value, if any, is set for requests made by your server, like the one you are actually making. You cannot use it to find out the user agent of a request made to your server.
Here is an example of code to set user agent and retrive a ressource with file_get_contents.
//Set uri
$uri = 'http://example.com';
//Init context
$ctx = stream_context_create(
array(
'http' => array(
'user_agent' => 'MySuperAgent/3.0'
)
)
);
//Try to retrieve content
if (($data = file_get_contents($uri, false, $ctx)) === false) {
die('file_get_contents error');
}
ps : Note that the context array should be under http key even for https ressources.
ps2 : I strongly suggests that you set the timeout and maximum acceptable redirections on the context to avoid slowdown in your application.

Callback function

So in JavaScript, I used to be able to have an http request initiate a callback when AJAX sent a response back to some data I sent to the server, successfully being a callback function. I'm now experimenting with the OAuth2 gem for Ruby, and I'm finding callbacks to not be the same;
I have a web server and facebook app set up, and I have a small php script that writes the current URL (including the auth code, for example) to a file, no problem. All the settings in the facebook app are set up, and if I put this in the URL in the browser:
http://graph.facebook.com/oauth/authorize?client_id=[my_client_id]&redirect_uri=http://localhost/oauth/callback/index.php
It redirects successfully to that script, which then writes the authorization code to a file which I can then use to get the access token. Problem is that I can only do this process manually; using the Net::HTTP.get(URI(address)) command in ruby doesn't seem to initiate the php script.
Ayone have any ideas?
I have no idea why you posted your history with javascript ajax requests, as it has no bearing on your ruby script, which by the way doesn't even use a callback method/function. Using a callback function just means you are calling some function and passing it another function as an argument. When I started programming, the term callback function was very confusing to me, and in my opinion the term should be dropped from the lingo.
As for your ruby script, you need to use something like Firebug to look at the request headers that are being sent by your browser to the server when you manually enter the url in your browser. If you use those same headers in your ruby script, then it should work, e.g.:
req['header1'] = 'hello'
req['header2'] = '10'
or:
headers = {
'header1' => 'hello',
'header2' => '10',
...
}
req = Net::HTTP::Get.new(uri.request_uri, headers)
http = Net::HTTP.new(uri.host, uri.port)
resp = http.request(req)
It's possible that you have a cookie set in your browser, which your browser automatically adds to the request headers when it sends the request to the server. Your browser probably adds thousands of headers to the request--many of which will have no bearing on your problem. If you have the patience, you can try to figure out which header is causing your ruby script's request to malfunction.
Another option is to use the mechanize gem, which will automatically handle cookies and redirects for requests sent by ruby scripts:
http://docs.seattlerb.org/mechanize/GUIDE_rdoc.html
(Read the section Let's Fetch a Page; Don't use the line require 'rubygems' if you are using ruby 1.9+).

accessing $_SESSION when using file_get_contents in PHP [duplicate]

This question already has answers here:
How to send cookies with file_get_contents
(4 answers)
Closed 2 years ago.
I have a page called send.email.php which sends an email - pretty simple stuff - I pass an order id, it creates job request and sends it out. This works fine when used in the context I developed it (Use javascript to make an AJAX call to the URL and pass the order_id as a query parameter)
I am now trying to reuse the exact same page in another application however I am calling it using php file_get_contents($base_url.'admin/send.email.php?order_id='.$order_id). When I call the page this way, the $_SESSION array is empty isempty() = 1.
Is this because I am initiating a new session using file_get_contents and the values I stored in the $_SESSION on login are not available to me within there?
-->
Thanks for the feedback. It makes sense that the new call doesn't have access to the existing session...
New problem though:
I now get: failed to open stream: HTTP request failed! When trying to execute:
$opts = array('http' => array('header'=> 'Cookie: ' . $_SERVER['HTTP_COOKIE']."\r\n"));
$context = stream_context_create($opts);
$contents = file_get_contents($base_url.'admin/send.sms.php?order_id='.order_id, false, $context);
YET, the URL works fine if I call it as: (It just doesn't let me access session)
$result file_get_contents($base_url.'admin/send.sms.php?order_id='.$order_id);
It is because the server uses cookies to track clients. When you call the page from your browser the session cookie is passed along the request. When you use file_get_contents function, no cookie is passed and the server cannot identify the client. Here's a post that might help you.

How to send cookies with file_get_contents

I'm trying to get the contents from another file with file_get_contents (don't ask why).
I have two files: test1.php and test2.php. test1.php returns a string, bases on the user that is logged in.
test2.php tries to get the contents of test1.php and is being executed by the browser, thus getting the cookies.
To send the cookies with file_get_contents, I create a streaming context:
$opts = array('http' => array('header'=> 'Cookie: ' . $_SERVER['HTTP_COOKIE']."\r\n"))`;
I'm retrieving the contents with:
$contents = file_get_contents("http://www.example.com/test1.php", false, $opts);
But now I get the error:
Warning: file_get_contents(http://www.example.com/test1.php) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
Does somebody knows what I'm doing wrong here?
edit:
forgot to mention: Without the streaming_context, the page just loads. But without the cookies I don't get the info I need.
First, this is probably just a typo in your question, but the third arguments to file_get_contents() needs to be your streaming context, NOT the array of options. I ran a quick test with something like this, and everything worked as expected
$opts = array('http' => array('header'=> 'Cookie: ' . $_SERVER['HTTP_COOKIE']."\r\n"));
$context = stream_context_create($opts);
$contents = file_get_contents('http://example.com/test1.txt', false, $context);
echo $contents;
The error indicates the server is returning a 404. Try fetching the URL from the machine PHP is running on and not from your workstation/desktop/laptop. It may be that your web server is having trouble reaching the site, your local machine has a cached copy, or some other network screwiness.
Be sure you repeat your exact request when running this test, including the cookie you're sending (command line curl is good for this). It's entirely possible that the page in question may load fine in a browser without the cookie, but when you send the cookie the site actually is returning a 404.
Make sure that $_SERVER['HTTP_COOKIE'] has the raw cookie you think it does.
If you're screen scraping, download Firefox and a copy of the LiveHTTPHeaders extension. Perform all the necessary steps to reach whatever page it is you want in Firefox. Then, using the output from LiveHTTPHeaders, recreate the exact same request requence. Include every header, not just the cookies.
Finally, PHP Curl exists for a reason. If at all possible, (I'm not asking!) use it instead. :)
Just to share this information.
When using session_start(), the session file is lock by PHP. Thus the actual script is the only script that can access the session file. If you try to access it via fsockopen() or file_get_contents() you can wait a long time since you try to open a file that has been locked.
One way to solve this problem is to use the session_write_close() to unlock the file and relock it after with session_start().
Example:
<?php
$opts = array('http' => array('header'=> 'Cookie: ' . $_SERVER['HTTP_COOKIE']."\r\n"));
$context = stream_context_create($opts);
session_write_close(); // unlock the file
$contents = file_get_contents('http://120.0.0.1/controler.php?c=test_session', false, $context);
session_start(); // Lock the file
echo $contents;
?>
Since file_get_contents() is a blocking function, both script won't be in concurrency while trying to modify the session file.
But i'm sure this is not the best manner to manipulate session with an extend connection.
Btw: it's faster than cURL and fsockopen()
Let me know if you find something better.
Just out of curiosity, are you attempting file_get_contents on a page that has a space in it? I remember trying to use fgc on a URL that had a space in the name and while my web browser parsed it just fine, fgc didn't. I ended up having to use a str_replace to replace ' ' with '%20'.
I would think that this should have been relatively easy to spot that though as it would report only half of the filename. Also, I noticed in one of these posts, someone used \r\n while defining the headers. Keep in mind that PHP doesn't like these to be in single quotes, but they work fine in double.
Make sure that file1.php exists on the server. Try opening it in your own browser to make sure!

Categories