webkitgtk custom scheme and XMLHttpRequest - javascript

I have a custom scheme ("embed") which serves data from an sqlite db
while I can do (inside a embed scheme page)
<img src="embed://any/old/uri/image.gif" />
if I try to do XMLHttpRequests I can only do relative paths, and only ones without double dots which seem to be stripped
Is there any way to get resources anywhere from the same scheme without issues. I notice the issue (as well as simple jscript tests) with three.js and howl.js It would be nice to be able to pull resources from anywhere within the same scheme.
I have tried the following
WebKitSettings *wks = webkit_web_view_get_settings (webView);
webkit_settings_set_enable_webgl (wks, TRUE);
webkit_settings_set_enable_webaudio (wks, TRUE);
webkit_settings_set_enable_xss_auditor(wks,FALSE);
webkit_settings_set_enable_hyperlink_auditing(wks, FALSE);
webkit_settings_set_enable_write_console_messages_to_stdout(wks, TRUE);
I also tried
webkit_security_manager_register_uri_scheme_as_local(wksm ,"embed");
but that seems to make things worse! I tried a bunch of other stuff but just seem to be chasing my own tail at the moment!
To be clear I'd be quite happy to turn off all "security" and let any embed:// resource have access to any other embed:// resource regardless of access method.

interesting one this!
a URI specification must contain a domain
as such this is the first part of the URI
embed://demo/content/main.js
embed://demo/image/texture.jpg
will work (here main.js is accessing texture.jpg)
embed://content/main.js
embed://image/texture.jpg
won't work! accessing texture.jpg from main.js looks to webkit as if a script on the content domain is accessing a resource on the image domain

Related

Load external page and Replace text

Would it be possible to load an external page inside a container and replace text elements?
We work with ad campaigns and earn a percentage whenever a user signs up.
Can a script replace certain words? For instance “User” to “Usuario” or “Password” to “Contraseña” without affecting the original website or its functions.
Note: These links always pass through a redirection.
Example:
http://a2g-secure.com/?E=/0yTeQmWHoKOlN6zUciCXQwUzfnVGPGN&s1=
Note 2: Using an iframe is out of the question due to “Same-origin policy”.
I'm not sure if this answers your question, but you might find it useful.
(Perhaps you might give a step-by-step example of what you're trying to accomplish?)
If we assume that a browser attempts to retrieve page P from a proxy which first retrieves the content of page P from its actual home and then performs some transformation on its content before returning that page content to the browser, what you're describing is a Reverse HTTP Proxy and is a very well-known page serving technique.
Rather than performing complex transformations at the server (which require specialized knowledge of the page layout), this technique is usually used to inject a single line into the retrieved source that calls a JavaScript file to actually perform the required transformation at the browser.
So in essence:
Browser requests Page P from Proxy 1.
Proxy 1 retrieves the actual Page P from its real home, Server 2.
Proxy 1 adds the line <script src="//proxy1.com/transform.js"></script> to the source of Page P.
Proxy 1 then returns the modified source of Page P to Browser.
Once the Browser has received the page content, the JavaScript file is also retrieved, which can then modify the page contents in any way required.
This technique can be used to solve your "Same origin policy" issue by loading an iframe from a URL that points to the same server as that which provided the parent or owning page of the iframe which acts as proxy, like:
http://example.com/?proxy_target=//server2.com/pageP.html
Thus, the browser only "sees" content from a single server.
You would need to load the external page server-side, and then you can do whatever you want with it. You can do serverside string replacement, or you can do it later in javascript.
But, remember that as soon as you add a whole webpage into for example a div in your own page, the css from your page will affect it.
Plus, you would need to manipulate all the links in the documents, to have absolute urls. If the page depends on ajax, there is pretty much no way to accomplish what you want to do.
If on the other hand the pages you will be loading are static html, it is possible, though there are a lot of things you need to take care of before you can actually present the page to the user, like adjusting links, urls to stylesheets and so on.
It seems you are trying to localize a website on the fly, using your server as a proxy for that content. Does it make sense? If that's the case, depending on the size of your operation, there are several proxy translation services out there (I'll name them if needed).
Basically, they scrape a website, providing a way for you to translate and host the translated content. Of course, this depends on your relationship with the content providers. You should also take this into consideration, since modifying content, even for translation, can be a copyright problem.
All things considered, if you trust the provider's javascript, the solution involves scraping the content, as mentioned in other answers, and serving that modified content. You really need to trust the origin...
update per request
http://www.easyling.com
http://www.smartling.com
http://www.motionpoint.com
http://www.lionbridge.com/solutions/translation-proxy/
http://www.sajan.com/translation-proxy-technology-and-traditional-website-translation-understanding-your-options/
They are all aimed at enterprise-grade projects, but I would say Easyling is the most accessible.
Hope this helps.
Using the .load() callback function, this will replace the text
$(function(){
$("#Content").load("http://example.com?user=Usuario",function() {
$(this).html($(this).html().replace("user", +get param value+));
});
redirection u can use
// similar behavior as an HTTP redirect
window.location.replace("url");
// similar behavior as clicking on a link
window.location.href = "url";
The answer is NO, not without using a server-side proxy. For a really good overview of how to use a proxy, see this YUI page: https://developer.yahoo.com/javascript/howto-proxy.html (Be patient, as it will take time to load, but the illustrations are worth it!)
When I try to do this in jsfiddle to see what data that the 3 parameters contain, then the error below appears:
$(function() {
$(this).load('https://stackoverflow.com/questions/36003367/load-external-page-and-replace-text', function(responseText, textStatus, jqXHR){
debugger;
});
});
ERROR:
XMLHttpRequest cannot load Load external page and Replace text.
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://fiddle.jshell.net' is therefore not allowed access.

Can I use indexeddb across subdomains?

I'm building a Chrome extension and using the db.js wrapper to utilize the indexeddb. The problem is, I've got several subdomains and I'd like to be able to share the information across them.
When I use the Chrome Dev tools to view Resources, all of the individual subdomains have their own copy of the schema I'm creating, and each has it's own data.
The only thing I knew to try was to set the document.domain but that didn't help. I wasn't surprised.
Documentation on indexeddb is very slim it seems. I keep finding the same 2 or 3 blog posts copied word for word in several different blogs and nothing specifies that this is possible or impossible.
You can't access the same database from multiple subdomains, the access scope is limited to html origin.
html_Origin = protocol + "://" + hostname + ":" + port + "/";
As #Xan mentioned, if you can use a common origin owned by the extension itself, rather than by the content pages, that sounds like it would be by far the easiest solution. If for whatever reason you can't do that (or for readers who got here wanting to know about regular page javascript or Greasemonkey-style userscripts, rather than extensions), the answer is:
Yes, though it's a slightly awkward and takes some work:
Since you're using a number of related subdomains, (rather than completely unrelated domains), there's a technique you can use in that situation. It can be applied to IndexedDB, localStorage, SharedWorker, BroadcastChannel, etc, all of which offer shared functionality between same-origin pages, but for some reason don't respect modifications to document.domain.
(1) Pick one "main" subdomain to for the data to belong to. i.e. if your subdomains are https://a.example.com, https://b.example.com, and https://c.example.com, you might choose to have your IndexedDB database stored under the https://a.example.com subdomain.
(2) Use it normally from all the the https://a.example.com pages.
(3) On https://b.example.com and https://c.example.com, use javascript to set document.domain = "example.com";. Then also create a hidden <iframe>, and navigate it to some page on the https://a.example.com domain (It doesn't matter what page, as long as you can insert a very little snippet of javascript on there. If you're creating the site, just make an empty page specifically for this purpose. If you're writing an extension or a userscript and so don't have any control over pages on the example.com server, just pick the most lightweight page you can find and insert your script into it. Some kind of "not found" page would probably be fine).
(4) The script on the hidden iframe page need only (a) set document.domain = "example.com";, and (b) notify the parent window when this is done. After that, the parent window can access the iframe window and all its objects without restriction! So the minimal iframe page is something like:
<!doctype html>
<html>
<head>
<script>
document.domain = "example.com";
window.parent.iframeReady(); // function defined & called on parent window
</script>
</head>
<body></body>
</html>
If writing a userscript, you might not want to add externally-accessible functions such as iframeReady() to your unsafeWindow, so instead a better way to notify the main window userscript might be to use a custom event:
window.parent.dispatchEvent(new CustomEvent("iframeReady"));
Which you'd detect by adding a listener for the custom "iframeReady" event to your main page's window.
(5) Once the hidden iframe has informed its parent window that it's ready, script in the parent window can just use iframe.contentWindow.indexedDB, iframe.contentWindow.localStorage, iframe.contentWindow.BroadcastChannel, iframe.contentWindow.SharedWorker instead of window.indexedDB, window.localStorage etc. ...and all these objects will be scoped to the https://a.example.com origin - so they'll have the this same shared origin for all of your pages!
The "awkward" part of this technique is mostly that you have to wait for the iframe to load before proceeding. So you can't just blithely initialize IndexedDB in your DOMContentLoaded handler, for example. Also you might want to add some error handling to detect if the hidden iframe fails to load correctly.
Obviously, you should also make sure the hidden iframe is not removed or navigated during the lifetime of your page... OTOH I don't know what the result of that would be, but very likely bad things would happen.
And, a caveat: setting/changing document.domain can be blocked using the Feature-Policy header, in which case this technique will not be usable as described.
However, there is a significantly more-complicated generalization of this technique, that can't be blocked by Feature-Policy, and that also allows entirely unrelated domains to share data, communications, and shared workers (i.e. not just subdomains off a common superdomain). #Xan alludes to it in point (2) of his answer:
The general idea is that, just as above, you create a hidden iframe to provide the correct origin for access; but instead of then just grabbing the iframe window's properties directly, you use script inside the iframe to do all of the work, and you communicate between the iframe and your main window only using postMessage() and addEventListener("message",...).
This works because postMessage() can be used even between different-origin windows. But it's also significantly more complicated because you have to pass everything through some kind of messaging infrastructure that you create between the iframe and the main window, rather than (for example) just using the IndexedDB API directly in your main window's code.
HTML-based storage (indexedDB, localStorage) in Chrome extensions behaves in a way that might not be expected, but it's perfectly natural.
In the background page, the domain is chrome-extension://yourextensionid/, and this is shared by all extension pages and is persistent.
In the content scripts though, you're sharing the HTML storage with the domain you're operating on. This makes life difficult if you want it to share/persist things. Note that sometimes this behavior is actually helpful.
The universal solution is to keep the DB in a background script, and communicate data/requests by means of Messaging API.
This was the usual solution for localStorage use until chrome.storage came along. But since you're using a database, you don't have a ready extension-friendly replacement.

GET arbitrary URLs with JavaScript

I want to be able to access /robots.txt from a variety of sites using JavaScript. This is for a side project that tests the availability of sites, not all of which are under my control. I've tried this:
$.get(robotsUrl, function() {
console.log('success!');
}, "text")
.fail(function() {
console.log('failed :(');
});
However, this fails with
XMLHttpRequest cannot load https://my.test.url/robots.txt. Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin
MDN's page on Same-Origin-Policy says that it's possible to embed content with some elements, such as <script>, <iframe> <embed>. Could I load /robots.txt from an arbitrary site with any of these? Is there any other way I can access this file on other domains?
You could load it with any of them, you just won't be able to make the data available to JavaScript. That's rather the point of the Same Origin Policy.
If you want to get arbitrary data from arbitrary sites, you need to do it server side.
To get around a same origin policy, you need to either have control over the host site and set the allow-origin (not an option here), or load it by a method other than JavaScript (which JSONP does; it is loaded as a standard script).
That means you could display the robots.txt in an iframe, for example, by just setting its src attribute.
If you want to manipulate the contents in JavaScript, that won't work (even after you load the content in an iframe, you're still not allowed to interact with it). Your final option is to set up a proxy. Have a script on your server which when called will load the relevant file and redirect the content. It's not hard to do, but means your server will have higher traffic (and you'll need to lock it down so that it isn't used maliciously).
iframes won't let you peek at the content. You could show it to your user, but I'm guessing you want to analyze it with code.
You could do it on your server. Even if you just have a /cors/robots/domain.tld handler (and others for other files you need to access). This is probably the best way, if it's feasible for your situation.
AnyOrigin, is a free service allows you to make cross-origin requests.
$.getJSON('http://anyorigin.com/get?url=google.com/robots.txt&callback=?', function(data){
console.log(data.contents); // contents of Robots.txt
});
Pretty sure this is possible with Chrome by runnning the browser with the Same Origin Policy disabled: Disable same origin policy in Chrome.
It may be preferable to do something like this outside the context of a browser however, on the command line perhaps using something like CURL?

Remove target attribute in iframe link

I have an iframe on one of my pages that shows content on an external site (vendor product). All works well except a few links that have target="_main" in them. These links open in a new tab. What I need to do is strip the target attribute from all links within the iframe so all links stay within the iframe rather than opening a new window or tab.
It seems like there should be a simple javascript solution to this.
If I can't get this to work in an iframe then I will be forced to re-create all the content on my site which would be very painful..... to say the least.
Any help???
You need access to the external site's codebase in order to dynamically fix this. What you want to do in the external site's codebase is to check if the sites is within an iframe. If it is within an iframe then run a function to remove all target attributes on links.
// vendors product page
if ( self !== top ){
$('a').removeAttr('target');
} // else do nothing
self !== top is the same as saying if my site isn't the top most window then return true.
Not directly that I am aware of.
However, if you have access to a scripting language (like PHP or ASP) on your site you can read your vendors' page directly from your server, do a find & replace on it & then render that onto your site; either in an iframe or however else you want.
Edit
There are many ways to do this, depending on how much control you have over you PHP config. Have a look at these resources & see if you can figure out what to do. If not I would suggest you start a new question specifically focused on what it is you are struggling with.
http://php.net/manual/en/function.file-get-contents.php With this method you have to be aware of the tip on the page:
A URL can be used as a filename with this function if the fopen wrappers have been enabled. See fopen() for more details on how to specify the filename. See the Supported Protocols and Wrappers for links to information about what abilities the various wrappers have, notes on their usage, and information on any predefined variables they may provide.
http://php.net/manual/en/function.fsockopen.php Again, be aware of the warning & notes.
http://php.net/manual/en/book.curl.php
I personally have written a class that uses fsockopen because it is the most flexible for my needs but usually file_get_contents does the trick because it is the simplest to set up out of the 3 options, if you have the right wrappers configured & you don't need to start working with SSL or funny protocols. I stay away from CURL because you have to install a library in order for it to work. I prefer my code to be portable for standard installs.
Some useful links that might help:
PHP readfile from external server
Possible Example
$vendorUrl = isset( $_REQUEST['vendor'] ) ? $_REQUEST['vendor'] : 'www.default-vendor.com';
$iframeContents = file_get_contents("http://$vendorUrl", false);
exit str_replace( 'target="_main"', '', $iframeContents );
Then you just have point your iframe at whatever page you save this script in on your server & include ?vender=www.vendor-url.com as the query string.
How about giving your own iframe the name _main?
<iframe name="_main" ...
The other links should then open in that iframe too.
Regards, Max

Is there a way to mitigate downloading of resources (images/css and js files) with Javascript?

I have a html page on my localhost - get_description.html.
The snippet below is part of the code:
<input type="text" id="url"/>
<button id="get_description_button">Get description</button>
<iframe id="description_container" src="#"/>
When the button is clicked the src of the iframe is set to the url entered in the textbox. The pages fetched this way are very big with lots of linked files. What I am interested in the page is a block of text contained in a <div id="description"> element.
Is there a way to mitigate downloading of resources linked in the page that loads into the iframe?
I don't want to use curl because the data is only available to logged in users and the steps to take with curl to get the content is too complicated. The iframe is simple as I use this on a box which sends the right cookies to identify the request as coming from a logged in user, but the problem is that it is very wasteful to get nearly 1 MB of data to keep 1 KB of it and throw out the rest.
Edit
If the proposed method just works in Firefox it is fine, so I added Firefox tag. Also, it is possible that the answer actually is from the realm of Firefox add-on techniques, so I added that tag as well.
The problem is not that I cannot get at what I'm looking for, rather, the problem is the easy iframe method is wasteful.
I know that Firefox does allow loading only the text of a page. If you open a page and press Ctrl+U you are taken to 'view page source' window, There links behave as normal and are clickable, if you click on a link in source view, the source of the new page is loaded into the view source window, without the linked resources being downloaded, exactly what I'm trying to get. But I don't know how to access this behaviour.
Another example is the Adblock add-on. It somehow kills elements before they get loaded. With plain Javascript this is not possible. Because it only is triggered too late to intervene in good time.
The Same Origin Policy forbids any web page to access contents of any other web page in a different domain so basically you cannot do that.
However it seems that with some browsers it is allowed to access web pages content if you are trying to access it from a local web page which seems to be your case.
Safari, IE 6/7/8 are browser that allow a local web page to do so via XMLHttpRequest (source: Google Browser Security Handbook) so you may want to choose to use one of those browsers to do what you need (note that future versions of those browsers may not allow to do so anymore).
A part from this solution I only see two possibities:
If the web pages you need to fetch content from are somehow controlled by you, you can create a simpler interface to let other web pages to get the content you need (for example allowing JSONP requests).
If the web pages you need to fetch content from are not controlled by you the only solution I see is to fetch content server side logging in from the server directly (I know that you don't want to do so, but I don't see any other possibility if the previous I mentioned are not practicable)
Hope it helps.
Actually I've seen Cross Domain jQuery .load request before, here: http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
The author claims that codes like these found on that page
$('#container').load('http://google.com'); // SERIOUSLY!
$.ajax({
url: 'http://news.bbc.co.uk',
type: 'GET',
success: function(res) {
var headline = $(res.responseText).find('a.tsh').text();
alert(headline);
}
});
// Works with $.get too!
would work. (The BBC code might not work because of the recent redesign, but you get the idea)
Apparently it is using YQL wrapped into a jQuery plugin to do the trick. Now I cannot say I fully understand what he is doing there but it appears to work, and fits the bill. Once you load the data I suppose it is a simple matter of filtering out the data that you need.
If you prefer something that works at the browser level, may I suggest Mozilla's Jetpack framework for lightweight extensions. I've not yet read the documentations in its entirety but it should contain the APIs needed for this to work.
There are various ways to go about this in AJAX, I'm going to show the jQuery way for brevity as one option, though you could do this in vanilla JavaScript as well.
Instead of an <iframe> you can just use a container, let's say a <div> like this:
<div id="description_container"></div>
Then to load it:
$(function() {
$("#get_description_button").click(function() {
$("#description_container").load($("input").val() + " #description");
});
});
This uses the .load() method which takes a string in this format: .load("url selector"), then takes that element in the page and places it's content inside the container you're loading, in this case #description_container.
This is just the jQuery route, mainly to illustrate that yes, you can do what you want, but you don't have to do it exactly like this, just showing the concept is getting what you want from an AJAX request, rather than in an <iframe>.
Your description sounds like you are fetching pages from the same domain (you said that you need to be logged in and have session credentials) so have you tried to use async request via XMLHttpRequest? It might complain if the html on a page is particularly messed up but you chould still be able to get raw text via .responseText and extract what you need with a regex.

Categories