I'm using file_get_contents() to get a PHP file which I use as a template to create a PDF.
I need to pass some POST values to it, in order to fill the template and get the produced HTML back into a PHP variable. Then use it with mPDF.
This works perfectly on MY server (a VPS using PHP 5.6.24)...
Now, at the point where I'm installing the fully tested script on the client's live site (PHP 5.6.29),
I get this error:
PHP Warning: file_get_contents(http://www.example.com/wp-content/calculator/pdf_page1.php): failed to open stream: HTTP request failed! HTTP/1.1 406 Not Acceptable
So I guess this can be fixed in php.ini or some config file.
I can ask (I WANT TO!!) my client to contact his host to fix it...
But since I know that hosters are generally not inclined to change server configs...
I would like to know exactly what to change in which file to allow the code below to work.
For my personnal knowledge... Obviously.
But also to make it look "easy" for the hoster (and my client!!) to change it efficiently. ;)
I'm pretty sure this is just one PHP config param with a strange name...
<?php
$baseAddr = "http://www.example.com/wp-content/calculator/";
// ====================================================
// CLEAR OLD PDFs
$now = date("U");
$delayToKeepPDFs = 60*60*2; // 2 hours in seconds.
if ($handle = opendir('.')) {
while (false !== ($entry = readdir($handle))) {
if(substr($entry,-4)==".pdf"){
$fileTime = filemtime($entry); // Returns unix timestamp;
if($fileTime+$delayToKeepPDFs<$now){
unlink($entry); // Delete file
}
}
}
closedir($handle);
}
// ====================================================
// Random file number
$random = rand(100, 999);
$page1 = $_POST['page1']; // Here are the values, sent via ajax, to fill the template.
$page2 = $_POST['page2'];
// Instantiate mpdf
require_once __DIR__ . '/vendor/autoload.php';
$mpdf = new mPDF( __DIR__ . '/vendor/mpdf/mpdf/tmp');
// GET PDF templates from external PHP
// ==============================================================
// REF: http://stackoverflow.com/a/2445332/2159528
// ==============================================================
$postdata = http_build_query(
array(
"page1" => $page1,
"page2" => $page2
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
// ==============================================================
$STYLE .= file_get_contents("smolov.css", false, $context);
$PAGE_1 .= file_get_contents($baseAddr . "pdf_page1.php", false, $context);
$PAGE_2 .= file_get_contents($baseAddr . "pdf_page2.php", false, $context);
$mpdf->AddPage('P');
// Write style.
$mpdf->WriteHTML($STYLE,1);
// Write page 1.
$mpdf->WriteHTML($PAGE_1,2);
$mpdf->AddPage('P');
// Write page 1.
$mpdf->WriteHTML($PAGE_2,2);
// Create the pdf on server
$file = "training-" . $random . ".pdf";
$mpdf->Output(__DIR__ . "/" . $file,"F");
// Send filename to ajax success.
echo $file;
?>
Just to avoid the "What have you tried so far?" comments:
I searched those keywords in many combinaisons, but didn't found the setting that would need to be changed:
php
php.ini
request
header
content-type
application
HTTP
file_get_contents
HTTP/1.1 406 Not Acceptable
Maaaaany thanks to #Rasclatt for the priceless help! Here is a working cURL code, as an alternative to file_get_contents() (I do not quite understand it yet... But proven functional!):
function curl_get_contents($url, $fields, $fields_url_enc){
# Start curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
# Required to get data back
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
# Notes that request is sending a POST
curl_setopt($ch,CURLOPT_POST, count($fields));
# Send the post data
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_url_enc);
# Send a fake user agent to simulate a browser hit
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56');
# Set the endpoint
curl_setopt($ch, CURLOPT_URL, $url);
# Execute the call and get the data back from the hit
$data = curl_exec($ch);
# Close the connection
curl_close($ch);
# Send back data
return $data;
}
# Store post data
$fields = array(
'page1' => $_POST['page1'],
'page2' => $_POST['page2']
);
# Create query string as noted in the curl manual
$fields_url_enc = http_build_query($fields);
# Request to page 1, sending post data
$PAGE_1 .= curl_get_contents($baseAddr . "pdf_page1.php", $fields, $fields_url_enc);
# Request to page 2, sending post data
$PAGE_2 .= curl_get_contents($baseAddr . "pdf_page2.php", $fields, $fields_url_enc);
Related
I am trying to use a PHP CURL request to upload data to Pass Slot to change an image, and I am continually getting errors.
This is the CURL request needed from their developer section on their website
POST https://api.passslot.com/v1/passes/pass.example.id1/27f145d2-5713-4a8d-af64-b269f95ade3b/images/thumbnail/normal
and this is the data that needs to be sent in its requested format
------------------------------330184f75e21
Content-Disposition: form-data; name="image"; filename="icon.png"
Content-Type: application/octet-stream
.PNG
imagedata
This is the code I am using currently, as I am not familiar with what is required on Multipart Form requests on API
$passId = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx";
$pass_generate_url = "pass.xxxxxxxxxxxx";
$url1 = 'https://api.passslot.com/v1/passes/'.$pass_generate_url.'/'.$passId.'/images/strip/normal';
$logo_file_location = "image.png";
$logo_file_location1 = "http://xxxxxxx.com/uploads/";
$data1 = array('image' => '#uploads/'.$logo_file_location,'application/octet-string',$logo_file_location1,'some_other_field' => 'abc',);
$auth1 = array( 'Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=',
'Content-Type: text/plain');
$ch1 = curl_init($url1);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch1, CURLOPT_POST, 1);
curl_setopt($ch1, CURLOPT_POSTFIELDS, $data1);
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch1, CURLOPT_HTTPHEADER, $auth1);
$response1 = curl_exec($ch1);
$ch1 = curl_init($url1);
When I run the code, this is the response from the CURL I get
{"message":"Validation Failed","errors":[{"field":"image","reasons":["Required"]}]}
Is there something I need to add to make the code work please?
Yes, I think you can build your own curl including to use say PHP CURLFile (sending the Multipart delimiter boundary and then the graphic data, etc) But you may choose to use an API (Say PassSlot PHP SDK)
https://github.com/passslot/passslot-php-sdk
General usage
require 'passslot-php-sdk/src/PassSlot.php';
$engine = PassSlot::start('<YOUR APP KEY>');
$pass = $engine->createPassFromTemplate(<Template ID>);
$engine->redirectToPass($pass);
For PNG file, it is like:
<?php
require_once('../src/PassSlot.php');
$appKey ='<YOUR APP KEY>';
$passTemplateId = 123456;
$outputPass = FALSE;
$values = array(
'Name' => 'John',
'Level' => 'Platinum',
'Balance' => 20.50
);
$images = array(
'thumbnail' => dirname(__FILE__) . '/thumbnail.png'
);
try {
$engine = PassSlot::start($appKey);
$pass = $engine->createPassFromTemplate($passTemplateId, $values, $images);
if($outputPass) {
$passData = $engine->downloadPass($pass);
$engine->outputPass($passData);
} else {
$engine->redirectToPass($pass);
}
} catch (PassSlotApiException $e) {
echo "Something went wrong:\n";
echo $e;
}
For further reference, please visit this
https://github.com/passslot/passslot-php-sdk/blob/master/examples/example.php
You may also view the source of the API to get inspired:
https://github.com/passslot/passslot-php-sdk/blob/master/src/PassSlot.php
Additional remark:
In case there is certificate expiry warning/error when running the SDK, please download the latest cacert.pem from https://curl.se/docs/caextract.html and replace the one in the SDK
I used to include files between sites routinely, until my webhost banned the practice. Now it appears that a recent PHP upgrade also tightened the screws, as I'm getting a "no suitable wrapper could be found" error - and I'm working with LOCAL sites.
Let's start with a website # www.gx.com and a subdomain at subdomain.mysite.com. However, they display locally as two separate websites - mysite.com and subdomain.com.
A page on subdomain.com features the following include request:
require_once($GX_URL."/2b/inc/D/Shared/Body/Bottom/Footer.php
$GX_URL displays as http[://]gx locally and http[://]gx.com online.
How can I modify this include so it works in both situations? I can use the following switch to hold two separate includes, one for online use and the other for local use:
switch(PHP_OS)
{
case 'Linux':
break;
default:
break;
}
I just figured the answer to my first question; I simply mapped out the entire path to the file in the other website on my computer:
/Applications/MAMP/htdocs/gx/2b/inc/D/Shared/Body/Bottom/Footer.php
So I guess I need to do something similar to include a file from my main domain. However, I'll leave this question open in case anyone has a more elegant solution.
I have more you can try one.
Try download html and include to your php page :).
Http Request or CURL request
Use Allow_url_include, example: http://wiki.dreamhost.com/Allow_url_include
Use Object download: http://php.net/manual/de/function.ob-start.php
Example::
1. Curl Download html string
function curl_get($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_USERAGENT, $this->CURL_UA);
curl_setopt($ch, CURLOPT_REFERER, $this->YT_BASE_URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$contents = curl_exec ($ch);
curl_close ($ch);
return $contents;
}
2. Http send request width file_get_contents
function sendRequest($url, $data = array())
{
$data = http_build_query($data);
$context_options = array('http' => array('method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($data) . "\r\n",
'content' => $data)
);
$context = stream_context_create($context_options);
$result = file_get_contents($url, false, $context);
return $result;
}
3 Object : http://php.net/manual/de/function.ob-start.php
I should start by saying I have no php experience what so ever, but I know this script can't be that ambitious.
I'm using Wordpress' metaWeblog API to batch the creation of several hundred posts. Each post needs a discrete title, a description, and url's for two images, the latter being custom fields.
I have been successful producing one post by manually entering data into the following file;
<?php // metaWeblog.Post.php
$BLOGURL = "http://path/to/your/wordpress";
$USERNAME = "username";
$PASSWORD = "password";
function get_response($URL, $context) {
if(!function_exists('curl_init')) {
die ("Curl PHP package not installed\n");
}
/*Initializing CURL*/
$curlHandle = curl_init();
/*The URL to be downloaded is set*/
curl_setopt($curlHandle, CURLOPT_URL, $URL);
curl_setopt($curlHandle, CURLOPT_HEADER, false);
curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $context);
/*Now execute the CURL, download the URL specified*/
$response = curl_exec($curlHandle);
return $response;
}
function createPost(){
/*The contents of your post*/
$description = "post description";
/*Forming the content of blog post*/
$content['title'] = $postTitle;
$content['description'] = $description;
/*Pass custom fields*/
$content['custom_fields'] = array(
array( 'key' => 'port_thumb_image_url', 'value' => "$imagePath" ),
array( 'key' => 'port_large_image_url', 'value' => "$imagePath" )
);
/*Whether the post has to be published*/
$toPublish = false;//false means post will be draft
$request = xmlrpc_encode_request("metaWeblog.newPost",
array(1,$USERNAME, $PASSWORD, $content, $toPublish));
/*Making the request to wordpress XMLRPC of your blog*/
$xmlresponse = get_response($BLOGURL."/xmlrpc.php", $request);
$postID = xmlrpc_decode($xmlresponse);
echo $postID;
}
?>
In an attempt to keep this short, here is the most basic example of the script that iterates through a directory and is "supposed" to pass the variables $postTitle, and $imagePath and create the posts.
<?php // fileLoop.php
require('path/to/metaWeblog.Post.php');
$folder = 'foldername';
$urlBase = "images/portfolio/$folder";//truncate path to images
if ($handle = opendir("path/to/local/images/portfolio/$folder/")) {
/*Loop through files in truncated directory*/
while (false !== ($file = readdir($handle))) {
$info = pathinfo($file);
$file_name = basename($file,'.'.$info['extension']); // strip file extension
$postTitle = preg_replace("/\.0|\./", " ", $file_name); // Make file name suitable for post title !LEAVE!
echo "<tr><td>$postTitle</td>";
$imagePath = "$urlBase/$file";
echo " <td>$urlBase/$file</td>";
createPost($postTitle, $imagePath);
}
closedir($handle);
}
?>
It's supposed to work like this,
fileLoop.php opens the directory and iterates through each file
for each file in the directory, a suitable post title(postTitle) is created and a url path(imagePath) to the server's file is made
each postTitle and imagePath is passed to the function createPost in metaWeblog.php
metaWeblog.php creates the post and passes back the post id to finish creating the table row for each file in the directory.
I've tried declaring the function in fileLoop.php, I've tried combining the files completely. It either creates the table with all files, or doesn't step through the directory that way. I'm missing something, I know it.
I don't know how to incorporate $POST_ here, or use sessions as I said I'm very new to programming in php.
You need to update your declaration of the createPost() function so that it takes into account the parameters you are attempting to send it.
So it should be something like this:
function createPost($postTitle, $imagePath){
/*The contents of your post*/
$description = "post description";
...
}
More information about PHP function arguments can be found on the associated manual page.
Once this has been remedied you can use CURL debugging to get more information about your external request. To get more information about a CURL request try setting the following options:
/*Initializing CURL*/
$curlHandle = curl_init();
/*The URL to be downloaded is set*/
curl_setopt($curlHandle, CURLOPT_URL, $URL);
curl_setopt($curlHandle, CURLOPT_HEADER, false);
curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $context);
curl_setopt($curlHandle, CURLOPT_HEADER, true); // Display headers
curl_setopt($curlHandle, CURLOPT_VERBOSE, true); // Display communication with server
/*Now execute the CURL, download the URL specified*/
$response = curl_exec($curlHandle);
print "<pre>\n";
print_r(curl_getinfo($ch)); // get error info
echo "\n\ncURL error number:" .curl_errno($ch); // print error info
echo "\n\ncURL error:" . curl_error($ch);
print "</pre>\n";
The above debug example code is from eBay's help pages.
It should show you if Wordpress is rejecting the request.
I need to get the complete output from an aspx site. When the user leaves I will save what's in some specific elements in cookies. The problem is that the aspx is on a domain I don't have access to. I want the output to behave as in an iframe so links need to be clickable but it won't leave my page.
I think of either AJAX with PHP-proxy or an iframe that I can modify content in.
Is this possible?
If it is possible and it involves server-side code I would like to know if there are any free web hosts that support the full code( for example almost every free web host has safe_mode on for PHP).
EDIT: I want to display this page : School scheme. The URL doesn't to change, it just sends requests to the server (think via JavaScript). When the user leaves I will see what's in the select box id="TypeDropDownList" and what's in the select box id="ScheduleIDDropDownList".
When the user returns to my page I will print those values to the page via URL like this "http://www.novasoftware.se/webviewer/(S(lv1isca2txx1bu45c3kvic45))/design1.aspx?schoolid=27500&code=82820&type=" + type + "&id=" + id + "
I tried several php proxy scripts on 000webhost before I posted here.
for example this :
<?php
ob_start();
function logf($message) {
$fd = fopen('proxy.log', "a");
fwrite($fd, $message . "\n");
fclose($fd);
}
?>
<?
$url = $_REQUEST['url'];
logf($url);
$curl_handle = curl_init($url);
curl_setopt($curl_handle, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, "Owen's AJAX Proxy");
$content = curl_exec($curl_handle);
$content_type = curl_getinfo($curl_handle, CURLINFO_CONTENT_TYPE);
curl_close($curl_handle);
header("Content-Type: $content_type");
echo $content;
ob_flush();
?>
But it returns Warning: curl_setopt(): supplied argument is not a valid cURL handle resource in /home/a5379897/public_html/ajax-proxy.php on line 16
I tried to contact them about this because they say they have cURL enabled but they haven't responded yet.
I think it would be possible to just display the two select boxes when the user first visit the page. When options is selected it will make an iframe show the right page by passing "http://www.novasoftware.se/webviewer/(S(lv1isca2txx1bu45c3kvic45))/design1.aspx?schoolid=27500&code=82820&type=" + type + "&id=" + id + " to the src attribute.
The problem with that is that I will need to retrieve the select boxes someway and I will have the same problem.
You would need to use PHP as Javascript doesn't doesn't allow cross domain requests. Your PHP code would literally grab the page the client wants, process it (changing link's href to your page with a get variable of the page the original href links to). When they click the link they will be sent to the same page they are on now but the page will grab the new page and return that(processing that page too) and so on.
000webhost are a nice free webhost that allow you to do most of PHP's functions and don't put adverts on your site.
To get the whole aspx output as a string to manipulate, you can use file_get_contents(http://yoursite.com/yourpage.aspx);
For best results, open a stream as the context via http.
<?php
// Create a stream
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);
$context = stream_context_create($opts);
// Open the file using the HTTP headers set above
$file = file_get_contents('http://www.example.com/', false, $context);
?>
Thanks to greg I could create this script that gets the page.
<html>
<head>
</head>
<body>
<?php
// Create a stream
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);
$context = stream_context_create($opts);
$host = 'http://www.novasoftware.se/webviewer/(S(bkjwdqntqzife4251x4sdx45))/';
$url = '/design1.aspx?schoolid=27500&code=82820&type=3&id={7294F285-A5CB-47D6-B268-E950CA205560}';
$changetothis='src="'.$host;
// Open the file using the HTTP headers set above
$file = file_get_contents($host.$url, false, $context);
$changed = str_replace('src="', $changetothis,$file);
echo $changed;
?>
</body>
</html>
I'm trying to convert this PHP cURL function to work with my rails app. The piece of code is from an SMS payment gateway that needs to verify the POST paramters. Since I'm a big PHP noob I have no idea how to handle this problem.
$verify_url = 'http://smsgatewayadress';
$fields = '';
$d = array(
'merchant_ID' => $_POST['merchant_ID'],
'local_ID' => $_POST['local_ID'],
'total' => $_POST['total'],
'ipn_verify' => $_POST['ipn_verify'],
'timeout' => 10,
);
foreach ($d as $k => $v)
{
$fields .= $k . "=" . urlencode($v) . "&";
}
$fields = substr($fields, 0, strlen($fields)-1);
$ch = curl_init($verify_url); //this initiates a HTTP connection to $verify_url, the connection headers will be stored in $ch
curl_setopt($ch, CURLOPT_POST, 1); //sets the delivery method as POST
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); //The data that is being sent via POST. From what I can see the cURL lib sends them as a string that is built in the foreach loop above
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //This verifies if the target url sends a redirect header and if it does cURL follows that link
curl_setopt($ch, CURLOPT_HEADER, 0); //This ignores the headers from the answer
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //This specifies that the curl_exec function below must return the result to the accesed URL
$result = curl_exec($ch); //It ransfers the data via POST to the URL, it gets read and returns the result
if ($result == true)
{
//confirmed
$can_download = true;
}
else
{
//failed
$can_download = false;
}
}
if (strpos($_SERVER['REQUEST_URI'], 'ipn.php'))
echo $can_download ? '1' : '0'; //we tell the sms sever that we processed the request
I've googled a cURL lib counterpart in Rails and found a ton of options but none that I could understand and use in the same way this script does.
If anyone could give me a hand with converting this script from php to ruby it would be greatly appreciated.
The most direct approach might be to use the Ruby curb library, which is the most straightforward wrapper for cURL. A lot of the options in Curl::Easy map directly to what you have here. A basis might be:
url = "http://smsgatewayadress/"
Curl::Easy.http_post(url,
Curl::PostField.content('merchant_ID', params[:merchant_ID]),
# ...
)