Why does file_get_contents() Javascript Output not Execute? - php

Backstory: I'm trying to use the Newsletter Widget from SendGrid but they currently don't offer it using SSL. So any requests to https:// just redirect to http:// and then browsers complain about insecure content on my secure site.
Ok fine, so I implement something like this in PHP:
$output = file_get_contents('http://sendgrid.com/newsletter/getSubscriptionWidget?p=xxx');
And then in my view have this:
<script type="text/javascript">
<?php echo($output); ?>
</script>
Viewing the source of this page after execution shows that it pulls the javascript widget code in just fine. BUT, it doesn't work. By "not working" I mean the javascript code never executes.
If I load it (in a non-https development environment) using the script tag like:
<script type="text/javascript" src="http://sendgrid.com/newsletter/getSubscriptionWidget?p=xxx">
Then it works just fine!
TL;DR; What would cause javascript to execute fine when loaded under the src attribute of the script element and not work when echoed as content inside script tags?
P.S. You can view the SendGrid widget source here.

SOLVED
Turns out the SendGrid code checks to ensure the script tag is pointing at the script using this:
// replace each instance
$('script').each(function (wIdx, wElem) {
var tag, src, table, trSubmit, tdSubmit, form, emailInput, message, params;
tag = $(this);
src = tag.attr('src');
params = RegExp('p=' + '(.+?)(&|$)').exec(src);
// check if corret script
if ($.isArray(params) && params.length > 1 && key === params[1]) {
form = $('<form />', {
'class': 'SG_widget_form',
'method': 'POST',
'action': postURL,
'accept-charset': 'UTF-8'
});
form.insertBefore(tag);
tag.remove();
message = $('<span />').insertBefore(form).hide();
... there is more after that, but that is the important piece. By adding the src attribute to the tag and pointing it at the correct location, the browser will block loading it normally, but will then execute the code I echoed with PHP inside of it.
Probably fairly specific to my problem, but hopefully it will help someone else.

Related

html2canvas - render picture without displaying the page

I have php API with $_POST , where i am getting API key and QR code from the request.
Then my php server generates the html code with <div>, <img> <html> <body> etc.. it means full website - getting data from the mysql server and rendering to html page.
At the end of the php code i have javascript code like this:
?>
<script>
window.scrollTo(0, 0);
html2canvas(document.getElementById("SelectorToPrint")).then(function (canvas) {
var dd= canvas.toDataURL("image/jpeg",1);
$.ajax({
type: "POST",
url: "https://myserver/API/sendimg.php",
data: {
key: '<?php echo $key;?>',
barkod: '<?php echo $qrcode;?>',
img: dd
}
}).done(function(o) {
});
});
</script>
When i am displaying the page, the picture is being saved (using html2canvas js) , everything is OK.
The problem is, when i am calling this API request from another php code, the page is not displaying, and for this reason the picture is not rendered.
Is there some way to render html page and save a picture without displaying the generated html code?
I changed the code for a while - to not have $_POST , but $_GET and testing with this code:
<?php
$key='my_api_key';
$qrcode='my_code';
$test = file_get_contents('https://myserver/API/apipage.php?key='.$key.'&qrcode='.$qrcode);
//var_dump($test) ;
?>
when the var_dump is removed from the code, the page is not rendered and the picture is not saved. When i enable the var_dump (or simply print_r or echo ) the picture is generated correctly. The problem is, that i dont want to display the html code (i think it's normal when i am talking about API calls).
Thanks for any hint
OK so my solution was the following:
installed xvfb on my linux server
installed ssh2 for php
installed CutyCapt on my linux server
instead of calling and rendering picture directly - i am calling with specially created user (with privileges only to do this job) the following script directly from php API
"/usr/bin/xvfb-run --server-args='-screen 0, 1920x1080x24' /usr/bin/CutyCapt --url='{$url}' --zoom-factor=1.4 --out=/home/myuser/public_html/rendered_images/{$filename}.{$extension}"
so as i learnt, there is no easy way to do it, but it's doable
hope it helps for someone

Injecting HTML into the DOM using script tag

We allow users to place a
<script language="javascript" src="oursite/script.php"></script>
tag on their page which should then embed some content from our site into their site. Currently script.php contains document.write("some content loaded from the database"), however there are some limitations.
Is there anyway I can have the same thing achieved using jQuery ? How do i tell jQuery to put a certain piece of HTML code EXACTLY where the script tag is ? document.write() can do this, but i'm not sure how to do this using jquery. (we are already providing the jquery js code to the client through script.php.
You don't need jQuery to do a document.write(). As long as it is executed inline (ie, not in an event handler such as $(document).ready()), it will work. Just make sure you escape the end script tag (like this: <\/script>), so that the HTML parser doesn't mistake it for an actual end script tag:
<script type="text/javascript">
document.write("<script language=\"javascript\" " +
"src=\"oursite/script.php\"><\/script>");
</script>
Alternatively, you could add the script using DOM manipulations. If you want to add the script after the page has loaded, this is your only option. To position it after the script tag that is calling it, give your script tag an id and use $("#myScript").after("<script>"):
<script type="text/javascript" id="myScript">
$(function () {
$("#myScript").after("<script>").attr({
language: "javascript",
src: "oursite/script.php"
});
});
</script>
You don't necessarily need to use jQuery, but you can.
The basic problem here is finding the script node as the page is loading.
You can give it an id and hope there are no duplicate ids on the other user's page.
But if you know the script will be evaluated as the page is loading, you can also do this:
(function(){ // this is just so you don't run into name collisions with the user's page
// Get all script elements
var scripts = document.getElementsByTagName('script');
// we know the last script element will be *this* one
var script = scripts[scripts.length-1];
var newp = document.createElement('p');
newp.textContent = 'inserted paragraph';
// now insert our new nodes after the current script
script.parentNode.insertBefore(newp, script.nextSibling);
})();
You can of course use jQuery as well with var $script = $('script:last');, but if you don't need it for anything else you can save some loading time by not using it.

Wordpress Admin - Function not defined?

I'm having problems trying to call a Javascript function from an enqueued javascript file used whilst editing Wordpress pages. I have created a simple meta box with some AJAX hyperlinks that I want to be able to call functions from the Javascript file (pretty simply stuff but I keep getting error "blah(1) is not defined".
HTML CONTAINED IN METABOX:
Delete Item
JS:
function blah(theid){
if ( confirm("Are you sure you wish to remove this image (Note: Images are not removed from the Media Library)?") ) {
var data = {
action: 'myajax-delete',
imgid: theid
};
jQuery.post(ajaxurl, data, function(response) {
//Parse the JSON Object
var object = jQuery.parseJSON(response);
if ( response.status == 'true' )
{
jQuery('#file_' + theid + '_row').remove(); //remove TR
alert('Image removed from this portfolio');
}else{
alert('Sorry, that image could not removed right now, please reload the page and try again.');
}
});
Note: The PHP server side code works fine and responds absolutely as expected to my manual Posts. The javascript file is definitely present and being downloaded by the browser as expected.
If I use the following line of code below, the AJAX works (so I know the JS is OK) but I need to be able to call the function by name rather use a selector. I'm very keen to work out why I can't call a simple function!!!!
jQuery('.delete_pimg').click(function() { ^Above code^ }
Just to re-cap the error I get when the link is clicked: 'blah(1) is not defined'
I hope I've explained this clearly - if not, please give me a shout :)
Ok Basically - I could not get this to work. My javascript is absolutely fine, so In order to call my own functions, I declared them within the page itself rather than calling in a JS file. This seems to work and my code executed with no errors straight away.
I.e
<script type="text/javascript">function blah(id){alert("This Works Nicely!");}</script>
A work around but at least solved my problem anyway.
Wipes sweat from forehead
I was having the same issue where blah() is not defined, and found out I needed to have the enqueued js file just define the function, instead of wrapped with a jQuery(document).ready(function($) { function blah(param){[...]} }).
Here's what my code looks like now, which got everything working for me:
Inside of functions.php
(short snippet within my file)
function blah_init() {
# Want this on all pages
# Queue JS and CSS
wp_enqueue_script(
'blah-file', // handle
get_template_directory_uri() . '/assets/js/blah-file.js', // source
array('jquery'), // registered script handles this script depends on
'1.0', // version
true // true = in footer, false (or blank) = in <head>
);
}
add_action('wp_enqueue_scripts', 'blah_init');
Inside of blah-file.js
(this is the full contents of the file)
//jQuery(document).ready(function($) {
function blah(param) {
console.log('Blah triggered: ', param);
}
//})
Inside of header.php and footer.php
(short snippet where I output some link, such as social link)
<!-- Ignore the href, this has nothing to do with getting this to work -->
Facebook

html body tag limitations in chrome and 'I.E'

to boost up the performance of the web site i put all the contents from the db ( not very big ) to body data tag. i.e.
<body data-blog="<?php echo htmlspecialchars( json_encode($blog) ); ?>">
The site worked ok on localhost and i updated it to the live server.
When i access the data from this site it is working fine no problem here. The problem comes when some one else accesses the site. I tested it using firefox 4. on my computer it works but it does not work on any other computer. It does show the data in the body tag but the simple javascript fails to display content without giving any error.
I do not know how can i debug this and what could be the potential problem with it. below is the code i am using to display the data out of the body tag.
<body data-blog="<?php echo htmlspecialchars( json_encode($blog) ); ?>">
<script>
$(document).ready(function()
{
$("#h_menu li").click(function(e)
{
var cid = $(this).attr('id');
$("#contents").empty();
var blog = $(document.body).data('blog');
var tags = $.parseJSON(blog);
$("#tmenu").empty();
for(var n in tags)
{
if( tags[n].cat_id == cid )
$('#tmenu').append("<li id='"+tags[n].id+"'>"+ tags[n].tag_name +"</li>");
}
});
$("#tmenu li").live("click",function()
{
var id = $(this).attr('id') ;
var blog = $(document.body).data('blog');
var tags = $.parseJSON(blog);
$('#contents').empty().hide();
$('#contents').html(tags[id-1].tag_content).fadeIn(600);
});
});
</script>
I forgot to mention it only works in FF4, chrome and I.E doesn't show data even on my computer from localhost so i am sure i must be doing some thing WRONG. but which thing i dont know and why is it working even from live site in my firefox ?
I think it would be better to stick that data in an hidden element somewhere instead of using the data. Also data is meant to be written and read using jQuery, I don't know if writing directly data-blog in the html will do the same without issues.

Why doesn't my <script> tag work from php file? (jQuery involved here too)

Here is what I am trying to accomplish. I have a form that uses jQuery to make an AJAX call to a PHP file. The PHP file interacts with a database, and then creates the page content to return as the AJAX response; i.e. this page content is written to a new window in the success function for the $.ajax call. As part of the page content returned by the PHP file, I have a straightforward HTML script tag that has a JavaScript file. Specifically:
<script type="text/javascript" src="pageControl.js"></script>
This is not echoed in the php (although I have tried that), it is just html. The pageControl.js is in the same directory as my php file that generates the content.
No matter what I try, I can't seem to get the pageControl.js file included or working in the resulting new window created in response to success in the AJAX call. I end up with errors like "Object expected" or variable not defined, leading me to believe the file is not getting included. If I copy the JavaScript directly into the PHPfile, rather than using the script tag with src, I can get it working.
Is there something I am missing here about scope resolution between calling file, php, and the jQuery AJAX? I am going to want to include javascript files this way in the future and would like to understand what I am doing wrong.
Hello again:
I have worked away at this issue, and still no luck. I am going to try and clarify what I am doing, and maybe that will bring something to mind. I am including some code as requested to help clarify things a bit.
Here is the sequence:
User selects some options, and clicks submit button on form.
The form button click is handled by jQuery code that looks like this:
$(document).ready(function() {
$("#runReport").click(function() {
var report = $("#report").val();
var program = $("#program").val();
var session = $("#session").val();
var students = $("#students").val();
var dataString = 'report=' +report+
'&program=' +program+
'&session=' +session+
'&students=' +students;
$.ajax({
type: "POST",
url: "process_report_request.php",
cache: false,
data: dataString,
success: function(pageContent) {
if (pageContent) {
$("#result_msg").addClass("successMsg")
.text("Report created.");
var windowFeatures = "width=800,menubar=yes,scrollbars=1,resizable=1,status=yes";
// open a new report window
var reportWindow = window.open("", "newReportWindow", windowFeatures);
// add the report data itself returned from the AJAX call
reportWindow.document.write(pageContent);
reportWindow.document.close();
}
else {
$("#result_msg").addClass("failedMsg")
.text("Report creation failed.");
}
}
}); // end ajax call
// return false from click function to prevent normal submit handling
return false;
}); // end click call
}); // end ready call
This code performs an AJAX call to a PHP file (process_report_request.php) that creates the page content for the new window. This content is taken from a database and HTML. In the PHP file I want to include another javascript file in the head with javascript used in the new window. I am trying to include it as follows
<script src="/folder1/folder2/folder3/pageControl.js" type="text/javascript"></script>
Changed path folder names to protect the innocent :)
The pageControl.js file is actually in the same folder as the jQuery code file and the php file, but I am trying the full path just to be safe. I am also able to access the js file using the URL in the browser, and I can successfully include it in a static html test page using the script src tag.
After the javascript file is included in the php file, I have a call to one of its functions as follows (echo from php):
echo '<script type="text/javascript" language="javascript">writePageControls();</script>';
So, once the php file sends all the page content back to the AJAX call, then the new window is opened, and the returned content is written to it by the jQuery code above.
The writePageControls line is where I get the error "Error: Object expected" when I run the page. However, since the JavaScript works fine in both the static HTML page and when included "inline" in the PHP file, it is leading me to think this is a path issue of some kind.
Again, no matter what I try, my calls to the functions in the pageControls.js file do not work. If I put the contents of the pageControl.js file in the php file between script tags and change nothing else, it works as expected.
Based on what some of you have already said, I am wondering if the path resolution to the newly opened window is not correct. But I don't understand why because I am using the full path. Also to confuse matters even more, my linked stylesheet works just fine from the PHP file.
Apologies for how long this is, but if anyone has the time to look at this further, I would greatly appreciate it. I am stumped. I am a novice when it comes to a lot of this, so if there is just a better way to do this and avoid this problem, I am all ears (or eyes I suppose...)
I have also had problems with a similar issue to this, and this was a real headache. The following approach may not be elegant, but it worked for me.
Make sure that your php file, just outputs what you want in your
body
Add jquery to the window head dynamically
Add any external script files to the window head dynamically
use jQuery html on the window's document to call html() with your loaded content on the body, so that scripts are evaluated.
For example, in your ajax success:
success: function(pageContent) {
var windowFeatures = "width=800,menubar=yes,scrollbars=1,resizable=1,status=yes";
var reportWindow = window.open("", "newReportWindow", windowFeatures);
// boilerplate
var boilerplate = "<html><head></head><body></body></html>";
reportWindow.document.write(boilerplate);
var head = reportWindow.document.getElementsByTagName("head")[0];
var jquery = reportWindow.document.createElement("script");
jquery.type = "text/javascript";
jquery.src = "http://code.jquery.com/jquery-1.7.min.js";
head.appendChild(jquery);
var js = reportWindow.document.createElement("script");
js.type = "text/javascript";
js.src = "/folder1/folder2/folder3/pageControl.js";
js.onload= function() {
reportWindow.$("body").html(pageContent);
};
head.appendChild(js);
reportWindow.document.close();
}
Good luck!
It probably isn't looking where you think it is looking to grab your javascript file.
Try a server-relative format like this:
<script src="/some/path/to/pageControl.js"></script>
If that still isn't working, verify that you can type the url to your script file into your browser and get it to download.
Make sure that you have that within either <head> or <body> of the HTML page. Also, I'd double check the path to the .js file. You could do that by pasting "pageControl.js" at the root of your web address.
Things to look for:
Use Firebug (NET tab) to check if the js file is loaded with status 200. Also check in the Console tab for any javascript errors.
Are you using HTML5 offline. If you do, maybe it serves a cached version that doesn't include your <script> tag.
View the page source and make sure it includes the script tag.
Change the source attribute to absolute path: <script src="http://www.example.com/js/pageControl.js" type="text/javascript"></script>
Visit http://www.example.com/js/pageControl.js and make sure it shows correctly.
Try to place the <script> right after the <head> so that it loads first.
This is all I could think of.
You can dynamically load script by creating the element and then append it to head or other element:
reportWindow.document.write(pageContent);
var script = document.createElement('script');
script.src = 'pageControl.js';
script.type = 'text/javascript';
reportWindow.document.getElementsByTagName('head')[0].appendChild(script);
reportWindow.document.close();
Have you tried using the jquery $("#target_div").load(...)
This also executes JS inside the output...
Read this doc to find out how to use it :
http://api.jquery.com/load/
To me it sounds like you're expecting an unloaded script to work.
Try taking a look here: http://ensure.codeplex.com/SourceControl/changeset/view/9070#201379
This is a bit of javascript that ensures that the script is loaded properly before access is attempted. You can use this either as lazy loading (loading javascript files only when required), or, as I interpret your problem, loading a script based on the result of ajax calls.
What's probably happening is, you're echoing a string via an ajax callback, not inserting an element. External scripts require a second GET call to load their contents, which isn't happening - only the first call happened. So, when the first call includes the inline code, the DOM doesn't have to make an additional GET request to fetch the contents. If the DOM doesn't see the script, the DOM won't execute it, which means it's just some random tag.
There's a very fast way to find out. In Chrome (or Firefox with the Firebug plugin installed), check the console > scripts dropdown to see all the loaded scripts. If it's not listed, it's not loaded and the script tag you see in the markup is otherwise inert.
Since it's probably just a string as far as PHP cares, you could create it as PHP DOM object and insert it properly (although this could be laborious). Instead, maybe place it at the very end of the page, just before the closing body tags. (This is the preferred position for js anyway - dead last, after all the other elements on the page have loaded and are available to the DOM.)
HTH :)

Categories