Reading WordPress header.php/footer.php to a text string - wordpress

I am attempting to read the results of the executed header.php/footer.php files as a string of html. Here's the scenario:
There are pages in the site that are developed in a .net environment but they want to share common headers/footers across the entire domain. They wish to have WordPress be the repository for this code and any time there is an update have a PHP cURL call to a .net web service and feed it the new HTML for the header/footers.
I tried calling get_header() but that does not return a string (as I anticipated) so then I tried this test solution in functions.php:
function write_header() {
$header_content = file_get_contents(get_bloginfo('wpurl').'/index.php' );
$fp = fopen('c:\header.txt', 'a+');
fwrite($fp, $header_content);//just testing the output, this will be a cURL call eventually.
fclose($fp);
}
add_action( 'wp_update_nav_menu', 'write_header' );
It seems to be a very heavy handed method of getting the HTML since I'll have to do a lot of string manipulation to parse out the pieces I want. Is there a simpler way of doing this that I'm missing?

If get_header() outputs the header for you, try just wrapping it with an ob_start() and ob_get_contents() to extract the header to a string. You can then discard the output with ob_end_clean(). See the PHP output buffering documentation.
ob_start();
get_header();
$header_as_string = ob_get_contents();
ob_end_clean();

There's a couple ways you can approach this problem (both are a bit of kludge, but what isnt...). The first would be to create a template in your theme's directory that will include only the header and footer calls -- the body of the template can contain a delimiter string like an html comment, e.g. <!-- SPLIT HERE -->.
Request the page through CURL into an output buffer, capturing the resulting response, which you can split into it's component parts using the above delimiter. That will give you your header and footer, complete with the fully rendered tags in the header for css,js, etc. It's not pretty, but it does the job.
The second approach would be an adaptation of the first, which, rather than you doing the splitting, have your .net team take care of it on their end if possible.
UPDATE
Okay, so there's actually a third option, which I completely forgot about, and that's to use one of WP's features: wp_remote_get() http://codex.wordpress.org/Function_API/wp_remote_get
Retrieves a URL using the HTTP GET method, returning results in an array. Results include HTTP headers and content.
This is what you should get back (excerpted from the API docs):
Array
(
[headers] => Array
(
[date] => Thu, 30 Sep 2010 15:16:36 GMT
[server] => Apache
[x-powered-by] => PHP/5.3.3
[x-server] => 10.90.6.243
[expires] => Thu, 30 Sep 2010 03:16:36 GMT
[cache-control] => Array
(
[0] => no-store, no-cache, must-revalidate
[1] => post-check=0, pre-check=0
)
[vary] => Accept-Encoding
[content-length] => 1641
[connection] => close
[content-type] => application/php
)
[body] => <html>This is a website!</html>
[response] => Array
(
[code] => 200
[message] => OK
)
[cookies] => Array
(
)
)
All you'd have to do is pass the URL to a page that's using the template I mentioned above, then handle response from wp_remote_get(); extract the html content form [body] and do your string splitting. Pretty much what you want.
Further reading: wp_remote_retrieve_body() http://codex.wordpress.org/Function_API/wp_remote_retrieve_body

Related

Downloading remote file using WordPress forbidden

I am trying to use WordPress' media_sideload_image with a remotely hosted image in S3 in order to save it into WordPress' media gallery.
But for whatever reason, I always get a forbidden response no matter what I try and do regarding request options for the WordPress request. Visiting the URL directly in the browser works, wget works, postman works.
Does anyone have any ideas on how to make WordPress be able to successfully download this file?
Here's the code I'm using:
$attachment_ID = media_sideload_image('https://s3.amazonaws.com/mlsgrid/images/0788b2c2-d865-496b-bad3-69ebe9c1db79.png');
And here's the WordPres error response I get:
object(WP_Error)[2090]
public 'errors' =>
array (size=1)
'http_404' =>
array (size=1)
0 => string 'Forbidden' (length=9)
public 'error_data' =>
array (size=1)
'http_404' =>
array (size=2)
'code' => int 403
'body' => string '<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>39B59073BBC1205F</RequestId><HostId>6TwMl4cMbLXzr7jbx6ykQKaQuk0Rn5Oyc2Q3+02zmgtNoDqUvcg8VY32qGuS1ZMzgpZuLAefK3g=</HostId></Error>' (length=243)
protected 'additional_data' =>
array (size=0)
empty
Thanks!
After digging around WordPress' request functionality, it looks like it is setting a referer header on each request to be the same as the URL being fetched and I guess Amazon S3 rejects requests with a referer header set? (not sure if that is specific to the bucket I'm fetching images from or true across every single bucket).
Here's how I got it working by removing the referer header from the request, basically just filter for all S3 URLs and remove the referer request header.
// Remove referer from request headers if the URL is an S3 bucket.
add_action( 'http_api_curl', function ($ch, $parsed_args, $url) {
$s3_url = 'https://s3.amazonaws.com';
if (substr($url, 0, strlen($s3_url)) === $s3_url) {
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Referer:']);
}
}, 10, 3);

Computer Vision API - v1.0 Recognize Handwritten Text returns empty response

I am trying to start using the computer vision API but I keep getting an empty response. My request in php (as exported by Postman) looks like this:
<?php
$request = new HttpRequest();
$request->setUrl('https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/recognizeText');
$request->setMethod(HTTP_METH_POST);
$request->setQueryData(array(
'language' => 'en',
'handwriting' => 'true'
));
$request->setHeaders(array(
'Postman-Token' => '442d04f7-49a0-4262-9d0f-666fe5240cc7',
'Cache-Control' => 'no-cache',
'Content-Type' => 'application/octet-stream',
'Ocp-Apim-Subscription-Key' => 'KEY'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
The above code works fine with the ocr endpoint!
The file is passed as binary using Postman.
Edit: I also tried to copy/paste the code from here: https://learn.microsoft.com/en-gb/azure/cognitive-services/computer-vision/quickstarts/php#ocr-php-example-request and if I change the ocr endpoint to recognizeText I get an empty response as well!
Unlike the other Computer Vision endpoints, RecognizeText is an asynchronous operation. Barring some issue with the image, you will get a 202 response instead of the usual 200 response. 202 responses customarily contain an empty response body. In this particular case you can find the URL where you can query for completion of the task. The documentation is here. The header you're looking for is Operation-Location.

Some authenticated users can't access secure content or use the restricted API

I'm in desperate need for help on this.
I'm the developer of a site (rockalingua.com) that offers subscriptions to a Learning Management system. We have developed the LMS creating several drupal modules.
It's working quite well so far but we are getting reports from some schools that some students (authenticated users) can't access some content (They get messages stating that they don't have permission to see that content)
This seems to be random, but when this happens the site acts as if they where not logged in. If the log-in again they can access the content usually (they report they sometimes have to restart the browser for that to happen)
The pages that have this problem use a REST API created by us for tracking the students progress.
Searching the logs I realized that some time after a class starts using the system a lot of warning and notice messages are dumped to the messages log reporting unauthenticated users trying to use the API from the same IPs and urls seconds or minutes before, authenticated users where accessing it without any problem.
I've examined all the code involved several times and can't find anything wrong with it, specially when it seems to happen randomly.
I know most schools have a proxy that use a cache. But don't know much about proxies or whether they could be affecting this issue.
If so, what could be do to avoid school proxies caching dynamic pages?
UPDATE:
I include the typical response headers we are sending on the typical affected requests, and some relevant code:
Accept-Ranges: bytes
Age: 0
Cache-Control: no-cache, must-revalidate
Content-Encoding: gzip
Content-Language: en
Content-Length: 4590
Content-Type: text/html; charset=utf-8
Date: Fri, 26 Jan 2018 08:53:52 GMT
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Server: Apache
Vary: Accept-Encoding
Via: 1.1 varnish
X-Content-Type-Options: nosniff
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Powered-By: PHP/5.4.45
X-UA-Compatible: IE=Edge,chrome=1
X-Varnish: 1592956310
And here you have the code for a typical AJAX request that I have seem to behave as described sometimes:
// ...
if($form_state['data']['is_student']) {
$form['submit'] = [
'#type' => 'submit',
'#value' => t('Go back'),
'#attributes' => [
'class' => [$form_state['data']['activity_type']],
],
'#ajax' => [
'callback' => 'activity_modal_form_submit_callback'
],
];
} else {
}
return $form;
}
/* Ajax callback to update the activity item after closing its modal */
function activity_modal_form_submit_callback($form, &$form_state) {
ctools_include('modal');
ctools_include('ajax');
global $user;
$activities_retriever = new student_task_activities($user->uid, $form_state['data']['task_id']);
$activity = $activities_retriever->lms_student_task_activity($form_state['data']['activity_id']);
$activity_data = array(
//'activity_name' => $activity['title'],
'times' => $activities_retriever->lms_student_task_activity_repetitions_assigned($activity['activity_id']),
'task_activity_entity_id' => $activity['activity_entity'],
'type' => $activity['activity_type'],
'title' => $activity['activity_title'],
'status' => $activity['status'],
'progress' => $activity['progress'],
'is_correctness_supported' => $activity['is_game_supported'],
'percent_right' => $activity['percent_right'],
'is_student' => $form_state['data']['is_student'],
);
$item_updated = render_activity_item(
$form_state['data']['activity_id'],
$activity_data,
$form_state['data']['task_id'],
$form_state['data']['is_student'],
$form_state['data']['due_date'], false);
$commands[] = ctools_modal_command_dismiss();
if($activity_data['type'] == 'video' || $activity['activity_type'] == 'song') {
$commands[] = ajax_command_replace('#activity_' . $form_state['data']['activity_id'], $item_updated);
}
print ajax_render($commands);
drupal_exit();
}
As it calls student_task_activities needs the uid on the constructor to retrieve the activity data and in the described situations it receives a 0, the activity array is empty and when trying to render the activity item a notice is dumped to the log warning about the missing information. There is where it says the uid is 0 and that's how I realized the user id was lost somewhere in the process.

Testing file uploads with codeception

Problem:
No data and files are coming through to the Silex application when a request is made from codeception test using the REST module with PhpBrowser driver.
// ApiTester $I
$I->wantTo('Submit files');
// prepare:
$data = ['key' => 'value'];
$files = [
'file_key' => 'path/to/file.doc',
'file2_key' => 'path/to/file2.doc'
];
// act:
$I->haveHttpHeader('Content-Type', 'multipart/form-data');
$I->sendPOST('/attachments/', $data, $files);
Current response
I have http header "Content-Type","multipart/form-data"
I send post "/attachments/",{"key":"value"},{"file_key":"/path/to/file/...}
[Request] POST http://localhost/attachments/ {"key":"value"}
[Request Headers] {"Content-Type":"multipart/form-data"}
[Page] http://localhost/attachments/
[Response] 400
[Request Cookies] []
[Response Headers] {"Date":["Tue, 25 Oct 2016 09:15:31 GMT"],"Server":["Apache/2.4.10 (Debian)"],"Cache-Control":["no-cache"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Headers":["Content-Type, Authorization"],"Access-Control-Allow-Methods":["GET,PATCH,PUT,POST,HEAD,DELETE,OPTIONS"],"Content-Length":["1235"],"Connection":["close"],"Content-Type":["application/json"]}
[Response] {"status":400,"meta":{"time":"2016-10-25 09:15:31"},"title":"Invalid Request","errors":"No data received","details":{"error_class":"Symfony\Component\HttpKernel\Exception\BadRequestHttpException"
Tried:
changing the Content-Type header
changing files array passed to sendPOST to an array of:
file paths file objects ( UploadedFile )
file arrays
The test works with Silex driver, but that won't be an option on the CI server. Also we've checked with Postman and the API route works as intended, files are sent and all good.
The actual problems:
$I->haveHttpHeader('Content-Type', 'multipart/form-data'); overwrites the Content-Type as it should be set by the http library (in phpbrowser is guzzle) to include the boundary, it's related to this.
Also be mindful that the $I->header does not reset after each request, to unset it use $I->deleteHeader('Content-Type');
Solution
Don't set the 'Content-Type' headers when sending files.

Paypal recurring payment profile API

I'm trying to create a recurring payment profile using paypal API in Wordpress. After taking the required information from the user I'm making a request using the following url.
https://api-3t.sandbox.paypal.com/USER=xylon-facilitator_api1.sjinnovation.com&PWD=9GDLFHDX3TQYWX4F&SIGNATURE=AO0B8EcgGN1ir1vqHVNLJ4fmaGxoAbfv5uwkwVkBxkD8vVif33kMJlD0&METHOD=CreateRecurringPaymentsProfile&CREDITCARDTYPE=Visa&ACCT=4311196648584326&EXPDATE=122019&FIRSTNAME=Xylon&LASTNAME=Gracias&PROFILESTARTDATE=2014-12-29T12:14:38Z&BILLINGPERIOD=Month&BILLINGFREQUENCY=1&AMT=20
But for the response i get following data
Array ( [headers] => Array ( [date] => Mon, 29 Dec 2014 12:14:39 GMT [server] => Apache [content-length] => 445 [connection] => close [content-type] => text/html; charset=iso-8859-1 ) [body] =>
Not Found
The requested URL /cgi-bin/ppapi was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
Apache Server at api-3t.sandbox.paypal.com Port 443
[response] => Array ( [code] => 404 [message] => Not Found ) [cookies] => Array ( ) [filename] => )
I'm using following link for reference
https://developer.paypal.com/docs/classic/paypal-payments-pro/integration-guide/WPRecurringPayments/
I'm Using direct payement method
Look at the API reference documentation here: https://developer.paypal.com/docs/classic/api/#merchant
... and then some of the many examples out on the web. As a 404 usually indicates, you have an incorrect URL (you probably meant to post to https://api-3t.sandbox.paypal.com/nvp if you are using the signature authentication and NVP; you omitted the path "nvp") and there are further issues after that with your variable handling.

Resources