Here is the example I prepared to tell about the problem easier.
http://codepen.io/anon/pen/EVpYXm
As you can see the initial <html> is set to display a text:
"This is the old html!"
It sets the whole content to the data in the variable myHtml. however here is what I notice:
the style is not carried from the <body> element. Moreover, the <body> element is somehow not created at all!
Here is the sring myHtml, tidied up to display as an html:
<html>
<head>
<title>Title Here</title>
<link href='style.css' rel='stylesheet' type='text/css'/>
</head>
<body style='background-color: red'>
<div>Div!</div>
</body>
</html>
I've realized that when link element is removed, everything works fine. Try it, see it yourself.
Stuck with this issue for the last few hours. Looking for a result.
Here is the full code:
page html:
<html>
This is the old html!
</html>
javascript:
$(function(){
var myHtml = "<html><head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body></html>"
$("html").html(myHtml);
})
The main purpose of this question is to understand the reason of this behavior as well as finding the best solution.
The issue is that, when you use jQuery's html(val), it does something like this:
html: function(value) {
/* ... */
// See if we can take a shortcut and just use innerHTML
if ( typeof value === "string" && !rnoInnerhtml.test( value ) && /* ... */) {
/* ... */ elem.innerHTML = value; /* ... */
}
/* ... */
}
That is, it checks the string with the regex rnoInnerhtml, which is
rnoInnerhtml = /<(?:script|style|link)/i
Therefore, presumably to avoid inserting stylesheets, jQuery avoids innerHTML and does complicated things with domManip.
I recommend using native innerHTML:
$("html").prop('innerHTML', myHtml);
var myHtml = "<head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body>"
$("html").prop('innerHTML', myHtml);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This is the old html!
Or with vanilla-js:
document.documentElement.innerHTML = myHtml;
var myHtml = "<head><title>Title Here</title><link href='style.css' rel='stylesheet' type='text/css'/></head><body style='background-color: red'><div>Div!</div></body>"
document.documentElement.innerHTML = myHtml;
This is the old html!
The problem is that you're appending an html element inside the root html element, which is undefined behavior and cannot be rendered reliably by the browser. Strip the opening and closing <html> and </html> tags from your myHtml string and it works!
Working demo
$(function() {
var myHtml = "<head><title>Title Here</title></head><body style='background-color: red; '><div>Div!</div></body>"
$('html').html(myHtml);
})
Alternatively, you could keep the tags and write directly to the document object instead, which opens a new stream and overwrites the previous document.
// ...
document.write(myHtml);
Related
Is there anyway of disabling loading external content inside of an iFrame?
Imagine there is a an iframe defined like:
<iframe srcdoc="
<html>
<head>
<title>Example Page!</title>
<link rel='stylesheet' type='text/css' href='http://example.com/mystyle.css'>
</head>
<body>
<p class='main'>Here goes the text.
</p>
<script src='http://example.com/js/superscript.js'>
</body>
</html>">
</iframe>
The loading of JS can be disabled with the allow-scripts inside of the sanbox attribute, but is there any way of disabling the load of the external css (and other external content)?
If not, is there any replacement for "rendering" html code (for example by JS), which would enable this?
I've made the following function to remove loading some assets from emails displayed in an iframe:
const replaced = []
const h = html
.replace(/url\s*\(([\s\S]+?)\)/g, (m,url) => {
url = url.trim()
try {
url = decodeURIComponent(url)
} catch (err) {/**/}
replaced.push(url)
return 'url()'
})
.replace(/[\s'"](?:src|srcset|background)?\s*=\s*(['"])([^\1]*?)\1/g, (m,q,src) => {
if (!src) return m // empty
replaced.push(src)
return ''
})
.replace(/<\s*link[^>]*?([\s'"]href\s*=\s*(['"])([^\2]*?)\2)/g, (m,attr,q,src) => {
if (!src) return // empty
replaced.push(src)
return m.replace(attr, '')
})
interestingly, <img alt="test"src="http://src.com/img.jpg"> is valid and will be displayed by chrome so whitespace before an attribute is actually not required, so I edited this answer to account for that...
It's probably not perfect, but you can tweak it as you see more cases by adding attributes...
Yes you can achieve it by using src not srcdoc and prefixing with data:text/html;charset=UTF-8,.
In your example:
<iframe src="data:text/html;charset=UTF-8,<html> <head> <title>Example Page!</title> <link rel='stylesheet' type='text/css' href='http://example.com/mystyle.css'> </head> <body> <p class='main'>Here goes the text. </p><script src='http://example.com/js/superscript.js'> </body> </html>">
</iframe>
I want to dynamically set the text of a p element with styling, but I do not know how to do this.
Here is my HTML element: <p id="delete-speaker-info-message"> </p>
Here is my current code to set the text:
document.getElementById("delete-speaker-info-message").innerHTML = `Are you sure you want to delete <b>${speakerName}</b> from <b>${eventName}</b>? This cannot be undone.`
Although the code above works, the speakerName, and eventName values are user inputted and need to be escaped. I know innerText can do this but it also escapes the bold tags. I am sure there is a way to do this but I just could not find it online. Thanks for the help!
Your best bet is to use a templating library. If you try to roll your own, you're probably going to mess it up and end up with XSS vulnerabilities. There's always a hacker out there who will think of something you haven't. Using a library also lets you do nice things like have an html template and pass in variables to be safely interpolated into it.
It sounds like you're not using any of the larger frameworks like React or Angular, so I'd say Lodash's template function is your best bet. Here's an example from their docs:
// Use the HTML "escape" delimiter to escape data property values.
var compiled = _.template('<b><%- value %></b>');
compiled({ 'value': '<script>' });
// => '<b><script></b>'
You should use something like my special function:
//<![CDATA[
/* external.js */
var doc, bod, I, special, unspecial; // for use on other loads
addEventListener('load', function(){
doc = document; bod = doc.body;
I = function(id){
return doc.getElementById(id);
}
special = function(str){
return str.replace(/&/g, '&').replace(/'/g, ''').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
}
unspecial = function(str){
return str.replace(/&/g, '&').replace(/'/g, "'").replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
}
var speakerName = '<i>Cool Joe</i>', eventName = '<div>Keeping it Real</div>';
var deleteSpeakerInfoMsg = I('delete-speaker-info-message');
deleteSpeakerInfoMsg.innerHTML = 'Are you sure you want to delete <b>'+special(speakerName)+'</b> from <b>'+special(eventName)+'</b>? This cannot be undone.';
console.log(deleteSpeakerInfoMsg.innerHTML);
}); // end load
//]]>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1' />
<title>Test Template</title>
<link type='text/css' rel='stylesheet' href='external.css' />
<script type='text/javascript' src='external.js'></script>
</head>
<body>
<div id='delete-speaker-info-message'></div>
</body>
</html>
I'm trying to get the html of www.soccerway.com. In particular this:
that have the label-wrapper class I also tried with: select.nav-select but I can't get any content. What I did is:
1) Created a php filed called grabber.php, this file have this code:
<?php echo file_get_contents($_GET['url']); ?>
2) Created a index.html file with this content:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<meta charset=utf-8 />
<title>test</title>
</head>
<body>
<div id="response"></div>
</body>
<script>
$(function(){
var contentURI= 'http://soccerway.com';
$('#response').load('grabber.php?url='+ encodeURIComponent(contentURI) + ' #label-wrapper');
});
var LI = document.querySelectorAll(".list li");
var result = {};
for(var i=0; i<LI.length; i++){
var el = LI[i];
var elData = el.dataset.value;
if(elData) result[el.innerHTML] = elData; // Only if element has data-value attr
}
console.log( result );
</script>
</html>
in the div there is no content grabbed, I tested my js code for get all the link and working but I've inserted the html page manually.
I see a couple issues here.
var contentURI= 'http:/soccerway.com #label-wrapper';
You're missing the second slash in http://, and you're passing a URL with a space and an ID to file_get_contents. You'll want this instead:
var contentURI = 'http://soccerway.com/';
and then you'll need to parse out the item you're interested in from the resulting HTML.
The #label-wrapper needs to be in the jQuery load() call, not the file_get_contents, and the contentURI variable needs to be properly escaped with encodeURIComponent:
$('#response').load('grabber.php?url='+ encodeURIComponent(contentURI) + ' #label-wrapper');
Your code also contains a massive vulnerability that's potentially very dangerous, as it allows anyone to access grabber.php with a url value that's a file location on your server. This could compromise your database password or other sensitive data on the server.
I am using prestashop 1.6 . I want to add google ads in top of the header and bottom in footer. I tried many ways but all are not succeed. Please how can i add script in my prestashop website?
Thanks in advance.
You need to find header.tpl file:
https://github.com/PrestaShop/PrestaShop/blob/develop/themes/default-bootstrap/header.tpl
<head>
{$HOOK_HEADER}
<link rel="stylesheet" href="http{if Tools::usingSecureMode()}s{/if}://fonts.googleapis.com/css?family=Open+Sans:300,600&subset=latin,latin-ext" type="text/css" media="all" />
<!--AdWords Code-->
</head>
Remember to disable CCC options for JS (especially moving JavaScript to the end):
Anything within {literal}{/literal} tags is not interpreted, but displayed as-is
{literal}
<script type="text/javascript">
// ...
</script>
{/literal}
{ldelim} and {rdelim} are used for escaping template delimiters, by default { and }:
<script type="text/javascript">
function foo() {ldelim}
// ...
{rdelim}
</script>
gives:
<script type="text/javascript">
function foo() {
// ...
}
</script>
If you still have a problem you may try to override Media Class:
https://gist.github.com/hereswhatidid/8c8edef106ee95138b03
<p>Some HTML goes here</p>
<script type="text/javascript" data-keepinline="true">
// this script will remain here when rendered
alert( "hello!" );
</script>
<script type="text/javascript">
// this script will be forced to the bottom of the page
alert( "hello again!" );
</script>
Media.php:
<?php
Class Media extends MediaCore
{
public static function deferScript($matches)
{
if (!is_array($matches))
return false;
$inline = '';
if (isset($matches[0]))
$original = trim($matches[0]);
if (isset($matches[1]))
$inline = trim($matches[1]);
/* This is an inline script, add its content to inline scripts stack then remove it from content */
if (!empty($inline) && preg_match('/<\s*script(?!.*data-keepinline)[^>]*>/ims', $original) !== 0 && Media::$inline_script[] = $inline)
return '';
/* This is an external script, if it already belongs to js_files then remove it from content */
preg_match('/src\s*=\s*["\']?([^"\']*)[^>]/ims', $original, $results);
if (isset($results[1]) && (in_array($results[1], Context::getContext()->controller->js_files)
|| in_array($results[1], Media::$inline_script_src)))
return '';
/* return original string because no match was found */
return $original;
}
}
The correct way should be using a module. Also check if the function htmlpurifier is blocking your scripts tags.
A little late, but it is solved by using {literal} //script here {/literal}. It's supposed to be used only if there are curly brackets in your script, but it works.
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
if (window.self === window.top) { $.getScript("Wing.js"); }
</script>
</head>
</html>
Is there a way in C# to modify the above HTML file and convert it into this format:
<html>
<head>
</head>
</html>
Basically my goal is to remove all the JavaScript from the HTML page. I don't know what is be the best way to modify the HTML files. I want to do it programmatically as there are hundreds of files which need to be modified.
It can be done using regex:
Regex rRemScript = new Regex(#"<script[^>]*>[\s\S]*?</script>");
output = rRemScript.Replace(input, "");
May be worth a look: HTML Agility Pack
Edit: specific working code
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
string sampleHtml =
"<html>" +
"<head>" +
"<script type=\"text/javascript\" src=\"jquery.js\"></script>" +
"<script type=\"text/javascript\">" +
"if (window.self === window.top) { $.getScript(\"Wing.js\"); }" +
"</script>" +
"</head>" +
"</html>";
MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(sampleHtml));
doc.Load(ms);
List<HtmlNode> nodes = new List<HtmlNode>(doc.DocumentNode.Descendants("head"));
int childNodeCount = nodes[0].ChildNodes.Count;
for (int i = 0; i < childNodeCount; i++)
nodes[0].ChildNodes.Remove(0);
Console.WriteLine(doc.DocumentNode.OuterHtml);
I think as others have said, HtmlAgility pack is the best route. I've used this to scrape and remove loads of hard to corner cases. However, if a simple regex is your goal, then maybe you could try <script(.+?)*</script>. This will remove nasty nested javascript as well as normal stuff, i.e the type referred to in the link (Regular Expression for Extracting Script Tags):
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
if (window.self === window.top) { $.getScript("Wing.js"); }
</script>
<script> // nested horror
var s = "<script></script>";
</script>
</head>
</html>
usage:
Regex regxScriptRemoval = new Regex(#"<script(.+?)*</script>");
var newHtml = regxScriptRemoval.Replace(oldHtml, "");
return newHtml; // etc etc
This may seem like a strange solution.
If you don't want to use any third party library to do it and don't need to actually remove the script code, just kind of disable it, you could do this:
html = Regex.Replace(html , #"<script[^>]*>", "<!--");
html = Regex.Replace(html , #"<\/script>", "-->");
This creates an HTML comment out of script tags.
using regex:
string result = Regex.Replace(
input,
#"</?(?i:script|embed|object|frameset|frame|iframe|meta|link|style)(.|\n|\s)*?>",
string.Empty,
RegexOptions.Singleline | RegexOptions.IgnoreCase
);