URL draft specification validate method - javascript

I've been looking at the new URL specification which is now implemented in Chrome Canary, and it looks very useful.
Is there any way to validate a URI before it is passed into the URL object?
For example
var urlToCheck = "http//www.google.com";
if(URL.isValid(urlToCheck)) {
var u = new URL(urlToCheck, baseUrl);
console.log(u.hostname);
}
I can't see anything in the linked specification doc. I would really not like to have to process the thrown Exception just to check the URI is valid.

Actually the 2-parameter version of the URL constructor accepts anything as its first parameter:
try{
new URL(null, 'http://www.example.com');
new URL({ob:'jects',even:{nested:'ones'}}, 'http://www.example.com');
new URL(['arrays'], 'http://www.example.com');
new URL(/regexes/, 'http://www.example.com');
new URL(false, 'http://www.example.com');
new URL(undefined, 'http://www.example.com');
console.log('new URL() takes any value as its first parameter!');
}catch(e){}
This means you don't have to validate both URLs; you only have to validate the base URL. Therefore a simple solution like this should suffice:
URL.isValid = function(url) {
try{
new URL(url);
} catch(e) {
return false;
}
return true;
};

You said in your comment that you can't tell if it's the base URL or the URL that's invalid so you'd rather check them both separately. If so, why not just do that? For example, something like this:
URL.isValid = function(url, base) {
if(base !== undefined) {
try {
new URL(base);
}
catch(e) {
return false;
}
}
try {
new URL(url, base);
return true;
}
catch(e) {
return false;
}
});
Lets you check both at the same time if preferred, or as you said you wanted, separately by first checking URL.isValid(base) and then checking URL.isValid(url, base). If the first check fails you know base is invalid, if the second does, you know url is invalid. If you really wanted, you could return separate error codes from .isValid based on which url was invalid.

You can use this function to validate url:
function isValidUrl(url) {
return url.match(/^(ht|f)tps?:\/\/[a-z0-9-\.]+\.[a-z]{2,4}\/?([^\s<>\#%"\,\{\}\\|\\\^\[\]`]+)?$/);
}

Related

Decode Url Recursively giving error for valid URL

I have trying to decode Recursively encoded url . But for even valid URL it is giving error .
I am calling
decodeURIRecursively({},"https%3A%2F%2Fgmail.com%3Frate%3D95%25")
It should return "https://gmail.com?rate=95%" But return string.
If I modify code and change catch block to return url it works well for this scenario but for malformed URL like decodeURIRecursively({},'%E0%A4%A'). It gives same url .
const decodeURIRecursively = (req, url) => {
// Early return on missing required parameter
if (!req || !url) {
return '';
}
try {
while (decodeURIComponent(url) !== url) {
url = decodeURIComponent(url);
}
} catch (e) {
return ''; // Return empty string as it is not a safe string to decode and use in
}
return url;
};
console.log(decodeURIRecursively({},"https%3A%2F%2Fgmail.com%3Frate%3D95%25"));
The url "https://gmail.com?rate=95%" has one invalid character which is "%".
So that why you get exception when run final step decodeURLComponent.
%3A, %2F, %3F... can be decode but only "%" is impossible.
catch (e) {
return url;
}
Return url when get the error is good choice as you mentioned.
My question is why you need decode recursively?
As I see you only need run decodeURLComponent one time.

writing to a file with php and javascript

So I want to use buttons on my HTML page to call a php program that will write to a text file. What I currently get is a success package from my Ajax function, but the file that it has supposed to have written does not exist.
my HTML
<button type = "button" onclick = "getRequest('changeState.php', changeState('1'), 0)"></button>
my Javascript functions:
function getRequest(url, success, error) {
var req = false;
try{
// most browsers
req = new XMLHttpRequest();
}
catch (e){
// IE
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
}
catch(e) {
// try an older version
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e) {
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function () {};
if (typeof error!= 'function') error = function () {};
req.onreadystatechange = function()
{
if(req.readyState == 4) {
return req.status === 200 ?
success(req.responseText) : error(req.status);
}
}
req.open("GET", url, true);
req.send(null);
return req;
}
function changeState(input)
{
state = input;
document.GetElementById("state_current").innerHTML = state;
}
My PHP file:
<?php
$f = fopen("file.txt");
fwrite($f, "Hello World");
fclose($f);
?>
I'll be honest, I'm very new to php, but my syntax seems fine because I'm not dropping any error messages, and I know that the program runs successfully because I get the success function to run. Have I missed something glaringly obvious?
file.txt should be created, if calling your PHP-script directly. If not probably PHP is not allowed to create it. Unfortunately its not that easy to understand which user is used to run PHP, and this user must have the rights to write to the webroot-folder of the server. As far as I know this depends on how PHP is executed (module vs CGI).
I would give it a try to change the folders access rights to "777" (anyone is allowed to do anything).
The changeState function doesn't get called on success because you are passing the value returned by the changeState function not the function reference, should be:
<button type = "button" onclick = "getRequest('changeState.php', changeState, 0)"></button>
You can also check on the Network Tab on the Developers Tools to see if you actually sent the request to the URL. If you didn't, then there's something wrong with your URL or your server.

How to change emscripten browser input method from window.prompt to something more sensible?

I have a C++ function which once called consumes input from stdin. Exporting this function to javascript using emscripten causes calls to window.prompt.
Interacting with browser prompt is really tedious task. First of all you can paste only one line at time. Secondly the only way to indicate EOF is by pressing 'cancel'. Last but not least the only way (in case of my function) to make it stop asking user for input by window.prompt is by checking the checkbox preventing more prompts to pop up.
For me the best input method would be reading some blob. I know I can hack library.js but I see some problems:
Reading blob is asynchronous.
To read a blob, first you have to open a file user has to select first.
I don't really know how to prevent my function from reading this blob forever - there is no checkbox like with window.prompt and I'm not sure if spotting EOF will stop it if it didn't in window.prompt case (only checking a checkbox helped).
The best solution would be some kind of callback but I would like to see sime hints from more experienced users.
A way would be to use the Emscripten Filesystem API, for example by calling FS.init in the Module preRun function, passing a custom function as the standard input.
var Module = {
preRun: function() {
function stdin() {
// Return ASCII code of character, or null if no input
}
var stdout = null; // Keep as default
var stderr = null; // Keep as default
FS.init(stdin, stdout, stderr);
}
};
The function is quite low-level: is must deal with one character at a time. To read some data from a blob, you could do something like:
var data = new Int8Array([1,2,3,4,5]);
var blob = new Blob([array], {type: 'application/octet-binary'});
var reader = new FileReader();
var result;
reader.addEventListener("loadend", function() {
result = new Int8Array(reader.result);
});
var i = 0;
var Module = {
preRun: function() {
function stdin() {
if (if < result.byteLength {
var code = result[i];
++i;
return code;
} else {
return null;
}
}
var stdout = null; // Keep as default
var stderr = null; // Keep as default
FS.init(stdin, stdout, stderr);
}
};
Note (as you have hinted), due to the asynchronous nature of the reader, there could be a race condition: the reader must have loaded before you can expect the data at the standard input. You might need to implement some mechanism to avoid this in a real case. Depending on your exact requirements, you could make it so the Emscripten program doesn't actually call main() until you have the data:
var fileRead = false;
var initialised = false;
var result;
var array = new Int8Array([1,2,3,4,5]);
var blob = new Blob([array], {type: 'application/octet-binary'});
var reader = new FileReader();
reader.addEventListener("loadend", function() {
result = new Int8Array(reader.result);
fileRead = true;
runIfCan();
});
reader.readAsArrayBuffer(blob);
var i = 0;
var Module = {
preRun: function() {
function stdin() {
if (i < result.byteLength)
{
var code = result[i];
++i;
return code;
} else{
return null;
}
}
var stdout = null;
var stderr = null;
FS.init(stdin, stdout, stderr);
initialised = true;
runIfCan();
},
noInitialRun: true
};
function runIfCan() {
if (fileRead && initialised) {
// Module.run() doesn't seem to work here
Module.callMain();
}
}
Note: this is a version of my answer at Providing stdin to an emscripten HTML program? , but with focus on the standard input, and adding parts about passing data from a Blob.
From what I understand you could try the following:
Implement selecting a file in Javascript and access it via Javascript Blob interface.
Allocate some memory in Emscripten
var buf = Module._malloc( blob.size );
Write the content of your Blob into the returned memory location from Javascript.
Module.HEAPU8.set( new Uint8Array(blob), buf );
Pass that memory location to a second Emscripten compiled function, which then processes the file content and
Deallocate allocated memory.
Module._free( buf );
Best to read the wiki first.

Catch Facebook Access token on demand, but how?

I build a Firefox Extension and i'm using the graph api. At the moment i catch the access token of each user while starting the browser like:
https://stackoverflow.com/questions/10301146/facebook-login-within-a-firefox-add-on
This works fine but kind of stupid, because nobody will use the extension in each firefox session. So what i'm trying to do is, catch the access token or more accurately call the methode Wladimir Palant recommends on demand. My code looks like this, while getAccessToken() is the mentioned method.
onLoad: function (){
var NoteHandler = window.arguments[0];
var sjcl = NoteHandler.sjcl;
NoteHandler.getAccessToken();
decryptionDialog.noteHandler = NoteHandler;
decryptionDialog.sjcl = sjcl;
var currID = decryptionDialog.getID();
if(currID==""){
window.close();
return false;
}else{
http_request = new XMLHttpRequest();
http_request.open('Get', 'https://graph.facebook.com/'+currID+'/notes?access_token='+NoteHandler.token, false);
http_request.overrideMimeType("text/json");
http_request.send(null);
decryptionDialog.value = decryptionDialog.ResponseToArray(http_request.responseText);
....
But the problem is while getAccessToken() is still waiting for the access token, the onLoad()-Method won't wait and goes on. Therefore the NoteHandler.token is null while the request is send. Does anyone have an idea, because i'm relatively new to javascript.
You should rewrite this code to be asynchronous - it shouldn't assume that getAccessToken() will get the result immediately, there should be rather a callback parameter, a function to be called when the operation is done (can be a closure function). Something along these lines:
onLoad: function (){
var NoteHandler = window.arguments[0];
var sjcl = NoteHandler.sjcl;
NoteHandler.getAccessToken(function()
{
decryptionDialog.noteHandler = NoteHandler;
decryptionDialog.sjcl = sjcl;
...
http_request.open('Get', 'https://graph.facebook.com/'+currID+'/notes?access_token='+NoteHandler.token, false);
...
});
}
...
getAccessToken: function(callback) {
...
// All done - call the callback
callback();
}

Strange javascript behavior - multiple active XMLHttpRequests at once? Long running scripts?

I'm attempting to issue two concurrent AJAX requests.
The first call (/ajax_test1.php) takes a very long time to execute (5 seconds or so).
The second call (/ajax_test2.php) takes a very short time to execute.
The behavior I'm seeing is that I /ajax_test2.php returns and the handler gets called (updateTwo()) with the contents from /ajax_test2.php.
Then, 5 seconds later, /ajax_test1.php returns and the handler gets called (updateOne()) with the contents from /ajax_test2.php still!!!
Why is this happening?
Code is here: http://208.81.124.11/~consolibyte/tmp/ajax.html
This line:-
req = new XMLHttpRequest();
should be:-
var req = new XMLHttpRequest();
As AnthonyWJones stated, your javascript is declaring the second AJAX object which first overwrites the req variable (which is assumed global since there is no var) and you are also overwriting the ajax variable.
You should separate your code i.e:
function doOnChange()
{
var ajax1 = new AJAX('ajax_test1.php', 'one', updateOne);
var ajax2 = new AJAX('ajax_test2.php', 'two', updateTwo);
}
function AJAX(url, action, handler)
{
if (typeof XMLHttpRequest == "undefined")
{
XMLHttpRequest = function()
{
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {}
throw new Error( "This browser does not support XMLHttpRequest." )
};
}
url = url + '?action=' + action + '&rand=' + Math.random()
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 4)
{
if (req.status == 200)
{
alert('' + handler.name + '("' + req.responseText + '") ')
handler(req.responseText)
}
}
}
req.open("GET", url, true);
req.send(null);
}
Regards
Gavin
Diodeus and Mike Robinson:
You guys didn't read my post fully. I know that one of the pages takes longer to execute than the other. That is the expected behavior of each page.
HOWEVER if you read my original post, the problem is that the callback for both pages ends up getting called with the HTML contents of the first page only.
AnthonyWJones and Gavin:
Thanks guys! That works like a charm! I guess I need to brush up on my Javascript!

Categories

Resources