mPDF failed to open stream: operation failed - mpdf

mPDF stopping working for me, pdfs generated from php are now blank, when I turn on debug I get the following error message.
Error detected. PDF file generation aborted: file_get_contents(https://www.myurl.com/pdf.php): failed to open stream: operation failed
When I go directly to the php page it appears fine.
Here is the code I'm using, I changed permissions to 777 on the file and the folder and it still doesn't work yet if I change the url to an external one it works perfectly. So I'm guessing something on my server is blocking it.
require __DIR__ . '/vendor/autoload.php';
$invoice_id = $_GET['invoice_id'];
$url="https://www.myurl.com/pdf.php";
if (ini_get('allow_url_fopen')) {
$html = file_get_contents($url);
} else {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , 1 );
$html = curl_exec($ch);
curl_close($ch);
}
try
{
$mpdf = new \Mpdf\Mpdf();
$mpdf->debug = true;
$mpdf->SetDisplayMode('fullwidth');
$mpdf->CSSselectMedia='mpdf'; // assuming you used this in the document header
$mpdf->setBasePath($url);
$mpdf->WriteHTML($html);
$mpdf->Output('invoice'.$invoice_id.'.pdf','D');
} catch (\Mpdf\MpdfException $e) { // Note: safer fully qualified exception
echo $e->getMessage();
}

Related

Download all files in all folders from URL

I'd like to recursively download all files from nested folders from this URL to my computer in the same nested structure:
https://hazardsdata.geoplatform.gov/?prefix=Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings%20HYDA/
I've tried several different approaches, using curl and RCurl, including this and some others. There are multiple file types within this folder. But I keep running into cryptic error message such as Error in function (type, msg, asError = TRUE) : error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
I'm not even sure how to begin.
in their javascript you'll find the url https://hazards-geoplatform.s3.amazonaws.com/ and there you'll find a xml file containing the path to (seemingly?) all their files, from there it shouldn't be hard, so
1: download the XML list of files from https://hazards-geoplatform.s3.amazonaws.com
2: each of the XML's <content> tag describes a file or a folder. filter out all the tags that is not relevant to you, that means if the content->key tag does not contain the text Brookings HYDA, filter it out.
3: the remaining content tags contain your download path and save path, for every key tag that ends with /: this is a "folder", you can't download a fol6der, just create the path, for example if the key is
<Contents>
<Key>Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Correspondence/</Key>
this means you should create the folders Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Correspondence and move on, however if the key's value does not end with /, it means you should download it, for example if you find
<Contents>
<Key>Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Correspondence/200724-CityBrookings-AirportInfo_Email.pdf</Key>
<LastModified>2022-03-04T17:54:48.000Z</LastModified>
<ETag>"9fe9af393f043faaa8e368f324c8404a"</ETag>
<Size>303737</Size>
<StorageClass>STANDARD</StorageClass>
</Contents>
it means the save filepath is Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Correspondence/200724-CityBrookings-AirportInfo_Email.pdf
and the url to download the file is https://hazards-geoplatform.s3.amazonaws.com/ + urlencode(key), in this case:
https://hazards-geoplatform.s3.amazonaws.com/Region8%2FR8_MIT%2FRisk_MAP%2FData%2FBLE%2FSouth_Dakota%2F60601300_BrookingsCO%2FBrookings%20HYDA%2FHydraulics_DataCapture%2FCorrespondence%2F200724-CityBrookings-AirportInfo_Email.pdf
idk how to do it with curl/r, but here's how to do it in PHP, happy porting
<?php
declare(strict_types=1);
function curl_get(string $url): string
{
echo "fetching {$url}\n";
static $ch = null;
if ($ch === null) {
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_ENCODING => '',
CURLOPT_FOLLOWLOCATION=>1,
CURLOPT_VERBOSE=>0
));
}
curl_setopt($ch, CURLOPT_URL, $url);
$ret = curl_exec($ch);
if(curl_errno($ch)) {
throw new Exception("curl error ".curl_errno($ch).": ".curl_error($ch));
}
return $ret;
}
$base_url = 'https://hazards-geoplatform.s3.amazonaws.com/';
$xml = curl_get($base_url);
$domd = new DOMDocument();
#($domd->loadHTML($xml));
$xp = new DOMXPath($domd);
foreach($xp->query("//key[contains(text(),'Brookings HYDA')]") as $node) {
$relative = $node->nodeValue;
if($relative[-1] === '/'){
// it's a folder, ignore
continue;
}
$dir = dirname($relative);
if(!is_dir($dir)) {
mkdir($dir, 0777, true);
}
$url = $base_url . urlencode($node->nodeValue);
file_put_contents($relative, curl_get($url));
}
after running that for a few seconds i have
$ find
.
./fuk.php
./Region8
./Region8/R8_MIT
./Region8/R8_MIT/Risk_MAP
./Region8/R8_MIT/Risk_MAP/Data
./Region8/R8_MIT/Risk_MAP/Data/BLE
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Correspondence
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Correspondence/200724-CityBrookings-AirportInfo_Email.pdf
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Correspondence/2D_Exceptions_2021Update.pdf
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/DCS_Checklist_Hydraulics_BrookingsCoSD.xlsx
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Simulations
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Simulations/RAS
./Region8/R8_MIT/Risk_MAP/Data/BLE/South_Dakota/60601300_BrookingsCO/Brookings HYDA/Hydraulics_DataCapture/Simulations/RAS/0.2PAC
soo it seems to be working.
the last output from the command is
fetching https://hazards-geoplatform.s3.amazonaws.com/Region8%2FR8_MIT%2FRisk_MAP%2FData%2FBLE%2FSouth_Dakota%2F60601300_BrookingsCO%2FBrookings+HYDA%2FHydraulics_DataCapture%2FSimulations%2FRAS%2F0.2PAC%2FPostProcessing.hdf
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 65019904 bytes) in /home/hans/test/fuk.php on line 17
meaning some of their files are over 134MB in size - it's easy to optimize the curl code to write directly to disk instead of storing the entire file in ram before writing to disk, but since you want to do this in R anyway, i won't bother optimizing the sample php script.

How to download a ZIP file into the wp-plugins folder programmatically?

I am creating a WordPress plugin which should download a ZIP file from a remote location and place it into the wp-plugins folder.
So I created a method which downloads the file using Curl (this works fine) and should then place the file into the wp-plugins folder. I am using the WP_Filesystem in order to make sure I have the rights to place a file on the server. This is what I have until now:
public function download_plugin($url, $path)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);
global $wp_filesystem;
if(defined('FS_CHMOD_FILE'))
{
$chmod = FS_CHMOD_FILE;
}
else
{
$chmod = 0755;
}
if (empty($wp_filesystem))
{
require_once (ABSPATH . '/wp-admin/includes/file.php');
WP_Filesystem();
}
if(!$wp_filesystem->put_contents(
$path,
$data,
$chmod
))
else
{
return new \WP_Error('writing_error', 'Error when writing file');
}
}
When I run the method no file is being created on the server. The $path variable however has the right path and the $data variable does contain the ZIP file as a string. The WordPress method put_contents however does nothing. It returns null even when I change the method's parameter to something that should definitely work like $wp_filesystem->put_contents(WP_PLUGIN_DIR.'example.txt','Some text',FS_CHMOD_FILE));.
Is there anything I am doing wrong? It's really difficult to debug since I don't get any errors and put_contents always returns null.

Symfony 2.6: Error loading web debug toolbar only when xdebug cookie not set

Whenever I run a page on my site with the xdebug cookie set, I see the web debug toolbar just fine. However, if I disable that cookie in my browser and try to run the same page, I get the following error:
An error occurred while loading the web debug toolbar (404: Not Found)
How can I use the web debug toolbar without xdebug?
update: here's my app_dev.php file. This works on other servers but not this one for some reason:
if (isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|| !in_array(#$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1', '74.80.8.75', '192.168.56.1'))
) {
header('HTTP/1.0 403 Forbidden');
exit('You are not allowed to access this file. Check ' . basename(__FILE__) . ' for more information.' . $_SERVER['REMOTE_ADDR']);
}
if (!isset($_COOKIE['XDEBUG_SESSION'])) {
$loader = require_once __DIR__ . '/../app/bootstrap.php.cache';
} else {
$loader = require_once __DIR__ . '/../app/autoload.php';
}
Debug::enable();
require_once __DIR__ . '/../app/AppKernel.php';
$kernel = new AppKernel('dev', true);
if (!isset($_COOKIE['XDEBUG_SESSION'])) {
$kernel->loadClassCache();
}
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
edit2:
It actually works fine with and without the cookie on the home page route. However, if I use a different route, for example app_dev.php/my-route/, then it only works with the XDEBUG cookie set.
It turns out this was caused by PHP running out of memory. Increasing memory_limit fixed it.

Client for Google API PHP Client and nested requires?

I'm trying to implement Google analytics api in a wordpress dashboard plugin.
Following the simplest implementation for using the Google API for PHP for the first time, its not working right away at practically the first step.
According to the tutorial README.md, my app, placed ajacent to the library folder, should load the library like so:
require_once 'Google/Client.php';
require_once 'Google/Service/Books.php';
$client = new Google_Client();
Now, the structure of the library within my app (plugin) is:
myapp.php
/Google
/Google/Client.php
/Google/otherfolders/otherfiles.php
and my app attempts to load the library per the require_once above. But of course the Client.php has many require_once calls itself such as:
require_once 'Google/Auth/AssertionCredentials.php';
Which seem to ignore its position -- already within /Google.
So I'm getting errors:
PHP Warning: require_once(Google/Auth/AssertionCredentials.php) [<a href='function.require-once'>function.require-once</a>]: failed to open stream: No such file or directory in <wpengine host path removed>/wp-content/plugins/mmstats/Google/Client.php on line 18
and
PHP Fatal error: require_once() [<a href='function.require'>function.require</a>]: Failed opening required 'Google/Auth/AssertionCredentials.php' (include_path='.:/usr/share/php:/usr/share/pear') in <wpengine host path removed>/wp-content/plugins/mmstats/Google/Client.php on line 18
This PHP is listed as "Beta" but surely I'm doing something wrong rather than this being a problem with Client.php
Any help appreciated!
The Google Director needs to be in the same directory as your file. If its not your going to have to edit all the required_once's yourself. Here is some working code for use with the Google Analytics API.
<?php
require_once 'Google/Client.php';
require_once 'Google/Service/Analytics.php';
session_start();
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey("{devkey}");
$client->setClientId('{clientid}.apps.googleusercontent.com');
$client->setClientSecret('{clientsecret}');
$client->setRedirectUri('http://www.daimto.com/Tutorials/PHP/Oauth2.php');
$client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));
//For loging out.
if ($_GET['logout'] == "1") {
unset($_SESSION['token']);
}
// Step 2: The user accepted your access now you need to exchange it.
if (isset($_GET['code'])) {
$client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
// Step 1: The user has not authenticated we give them a link to login
if (!$client->getAccessToken() && !isset($_SESSION['token'])) {
$authUrl = $client->createAuthUrl();
print "<a class='login' href='$authUrl'>Connect Me!</a>";
}
// Step 3: We have access we can now create our service
if (isset($_SESSION['token'])) {
print "<a class='logout' href='".$_SERVER['PHP_SELF']."?logout=1'>LogOut</a><br>";
$client->setAccessToken($_SESSION['token']);
$service = new Google_Service_Analytics($client);
// request user accounts
$accounts = $service->management_accountSummaries->listManagementAccountSummaries();
foreach ($accounts->getItems() as $item) {
echo "Account: ",$item['name'], " " , $item['id'], "<br /> \n";
foreach($item->getWebProperties() as $wp) {
echo ' WebProperty: ' ,$wp['name'], " " , $wp['id'], "<br /> \n";
$views = $wp->getProfiles();
if (!is_null($views)) {
foreach($wp->getProfiles() as $view) {
// echo ' View: ' ,$view['name'], " " , $view['id'], "<br /> \n";
}
}
}
} // closes account summaries
}
print "<br><br><br>";
print "Access from google: " . $_SESSION['token'];
?>
You can find a tutorial for this code at Google Oauth2 PHP, there is a little test app at the bottom where you can see it working.

Quick way to find out if website is down or up?

Using my wordpress functions.php file to check if every image displayed is up and running or down. I think what I want to do is to break this functions code (below) into two.
function 1: check if mirror1.com is up (instead of checking every image in loop). insert if/then statement depending on http status of mirror1.com. (if mirror1.com is down, then use mirror2.com) -- pass that into $mirror_website
function 2: simply pass in $mirror_website.. (the front end has <img src="<?php echo $mirror_website; ?>/image.png"> )
The code below works, but it's checking EVERY simple image and slows down the site.
function amazons3acctreplaceto() {
$url = 'http://www.mirror1.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (200==$retcode) {
$as3replaceto = "www.mirror1.com"; // All's well
} else {
$as3replaceto = "www.mirror2.com"; // not so much
}
A simple solution might be to cache the result (eg. in the APC or memcache) with a TTL so you don't need to work out if the site is up or down for every eventuality.
eg. Here's an example that might work using APC to cache the result of the site status for 2 minutes:
function amazons3acctreplaceto() {
$as3replaceto = FALSE;
if (function_exists('apc_fetch')) {
$as3replaceto = apc_fetch('as3replaceto');
}
if ($as3replaceto === FALSE) {
$url = 'http://www.mirror1.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
$retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (200==$retcode) {
$as3replaceto = "www.mirror1.com"; // All's well
} else {
$as3replaceto = "www.mirror2.com"; // not so much
}
if (function_exists('apc_store')) {
apc_store('as3replaceto', $as3replaceto, 120); //Store status for 2 minutes
}
}

Resources