Is this JavaScript code safe? - javascript

I have found the following JS on the web.
It is a function to get url params values.
function get_url_param(param) {
param = param.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+param+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec(window.location.href);
if( results == null )
return '';
else
return results[1];
}
However always when I see a exec() function I think: Eeek!
So my question is: is it safe?
Side bet: If you think this function sucks and have a better option don't hesitate to share :)
The above function uses the real url but I only need to parse a string which contains an URL.

The .exec() you see in your function is not of the window but of the RegExp object.
So it is perfectly fine to use.

I wouldn't confuse a Regexp exec with an eval. A little clunky but it should work.

Regexp#exec is safe, albeit not a very nice interface.
Side bet: If you think this function sucks and have a better option don't hesitate to share :)
yeeep :-)
param = param.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
This doesn't use a global regexp so you are only replacing one instance of each bracket; field[][] wouldn't work. Also you don't need the character group... param.replace(/\[/g, '\\[') would have worked. Or, the non-regexp replacement idiom, param.split('[').join('\\[').
Then:
var regexS = "[\\?&]"+param+"=([^&#]*)";
you're not escaping nearly enough characters to be able to drop them into a regexp and have them mean their literal selves. See this question for a more watertight alternative.
Anyway this kind of regex hacking still isn't a good way of parsing URLs/query strings. This doesn't deal properly with ; or %-encoding, or + for space, and it may trip on parameter lookalikes elsewhere in the URL.
Instead, let's first get the query string on its own. If you have a link or location object, you can get it from the the .search property . If you only have a string URL, you can turn it into a link object to get this reliably:
function getQueryString(url) {
var a= document.createElement('a');
a.href= url;
return a.search;
}
Now you can parse it into by dropping the leading ?, splitting on & or ;, then dropping the URL-decoded results into a JS Object:
function parseQuery(query) {
var lookup= {};
var params= query.slice(1).split(/[&;]/);
for (var i= 0; i<params.length; i++) {
var ix= params[i].indexOf('=');
if (ix!==-1) {
var name= decodeURIComponent(params[i].slice(0, ix));
var value= decodeURIComponent(params[i].slice(ix+1));
if (!(name in lookup))
lookup[name]= [];
lookup[name].push(value);
}
}
return lookup;
}
This makes it easy to look up parameters:
var url= 'http://www.example.com/?a=b&c=d&c=%65;f[]=g#h=i';
var pars= parseQuery(getQueryString(url));
alert(pars.a); // ['b']
alert(pars.c); // ['d', 'e']
alert(pars['f[]']); // ['g']
alert('h' in pars); // false
If you don't need to read multiple values for a parameter, you could just do lookup[name]= value instead of the if...[]...push dance, to return single string values in the lookup instead of lists.

Related

Using Variable in Regex Character Set

i'm trying to use a variable (save) as a regex character set but keep getting null
function mutation(arr) {
var save = arr[1];
var rgx = /[save]/gi;
return arr[0].match(rgx).join('') == arr[0];
}
mutation(["Mary", "Army"]);
Goal of the function is to see if all the letters of arr[1] are contained in arr[0] by returning true or false. Function does work as i want it to when i manually put arr[1] into the character set (returns true in this situation), just cant get it to work with the variable.
Your exact current approach won't work (I think) due to it not being possible to build a regex pattern using /.../ notation with a variable. But, we can still use RegExp to build the pattern. For the sample data you showed us, here is a regex pattern which would work:
^(?!.*[^Mary]).*$`
In other words, we can assert, on the second string Army, that all its characters can be found in the first string Mary.
function mutation(arr) {
var save = arr[1];
var rgx = "^(?!.*[^" + save + "]).*$";
var re = new RegExp(rgx, "gi");
return re.test(arr[0]);
}
console.log(mutation(["Mary", "Army"]));
console.log(mutation(["Jon Skeet", "Tim Biegeleisen"]));

How to build regex OR option from an Array

I am pretty new to Regex and what I want to do is the following.
Say I have a keyword array:
// the kwd is changed dynamically
var kwd = ["key1", "key2", "key3", "key4"];
I need to build a Regex to test if a string contains any of the keywords in that array. I wonder how can I generate that Regex expression dynamically?
Probably a function:
function RegexBuilder(kwd){
// I know I can use brutal force to search one by one,
// but I just need to know how to generate that regex?
return regex_expression;
}
This should do it. The constructor for the RegExp object can be used to build a RegExp from a string instead of a literal.
function RegexBuilder(kwd){
kwd.forEach(function(e,i,a){
a[i] = e.replace(/[()^|$[\]*.\\?{}]/g, "\\$&");
});
regex_expression = new RegExp(kwd.join('|'));
return regex_expression;
}
https://regex101.com/r/vE0cI0/1
I assume there shouldn't be any special chars inside key which will make this a more complex solution.
function RegexBuilder(kwd){
var regex_expression = '(' + kwd.join('|').replace(/([^\w\d\s|])/gm,'\\$1') + ')';
return regex_expression;
}
You can use it this way
var regex = new RegExp(RegexBuilder(kwd));
if(mytext.match(regex)) // do something

With JavaScript, I need help concatenating a variable into a regular expression

I'm writing a JavaScript function to extract a segment out of a URL that appears to the right of a designated segment.
For instance, if this is my URL ...
mysite.com/cat/12/dog/34?test=123
... I would like to be able to pass 'cat' to the function and get 12, and later pass 'dog' to the function and have it return 34. I found this answer on StackOverflow to extract the URL segment, but it uses a string literal. And I'm having difficulty concatenating a passed in value.
jQuery to parse our a part of a url path
Here is my code. In this, rather than hard coding 'cat' into the pattern match, I would like to pass 'cat' into the segmentName parameter and have the regular expression match on that.
var url = "www.mysite.com/cat/12/dog/34?test=123";
alert(getNextSegmentAfterSegmentName(url, 'cat'));
function getNextSegmentAfterSegmentName(currentPath, segmentName) {
var nextSegment = "";
segmentName = segmentName.toLowerCase();
//var currentPath = window.location.pathname.toLowerCase();
if (currentPath.indexOf(segmentName) >= 0) {
var path = currentPath.split('?')[0]; // Strip querystring
// How do I concatenate segmentName into this?
var matches = path.match(/\/cat\/([^\/]+)/);
if (matches) {
nextSegment = matches[1];
}
}
return nextSegment;
}
Here is a jsfiddle example:
http://jsfiddle.net/Stormjack/2Ebsv/
Thanks for your help!
You need to create a RegExp object if you want to create regex using some string variable:
path.match(new RegExp("\/" + segmentName + "\/([^\/]+)"));

Javascript to extract *.com

I am looking for a javascript function/regex to extract *.com from a URI... (to be done on client side)
It should work for the following cases:
siphone.com = siphone.com
qwr.siphone.com = siphone.com
www.qwr.siphone.com = siphone.com
qw.rock.siphone.com = siphone.com
<http://www.qwr.siphone.com> = siphone.com
Much appreciated!
Edit: Sorry, I missed a case:
http://www.qwr.siphone.com/default.htm = siphone.com
I guess this regex should work for a few cases:
/[\w]+\.(com|ca|org|net)/
I'm not good with JavaScript, but there should be a library for splitting URIs out there, right?
According to that link, here's a "strict" regex:
/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:#]*)(?::([^:#]*))?)?#)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/
As you can see, you're better off just using the "library". :)
This should do it. I added a few cases for some nonmatches.
var cases = [
"siphone.com",
"qwr.siphone.com",
"www.qwr.siphone.com",
"qw.rock.siphone.com",
"<http://www.qwr.siphone.com>",
"hamstar.corm",
"cheese.net",
"bro.at.me.come",
"http://www.qwr.siphone.com/default.htm"];
var grabCom = function(str) {
var result = str.match("(\\w+\\.com)\\W?|$");
if(result !== null)
return result[1];
return null;
};
for(var i = 0; i < cases.length; i++) {
console.log(grabCom(cases[i]));
}
var myStrings = [
'siphone.com',
'qwr.siphone.com',
'www.qwr.siphone.com',
'qw.rock.siphone.com',
'<http://www.qwr.siphone.com>'
];
for (var i = 0; i < myStrings.length; i++) {
document.write( myStrings[i] + '=' + myStrings[i].match(/[\w]+\.(com)/gi) + '<br><br>');
}
I've placed given demo strings to the myStrings array.
i - is index to iterate through this array. The following line does the matching trick:
myStrings[i].match(/[\w]+\.(com)/gi)
and returns the value of siphone.com. If you'd like to match .net and etc. - add (com|net|other) instead of just (com).
Also you may find the following link useful: Regular expressions Cheat Sheet
update: missed case works too %)
You could split the string then search for the .com string like so
var url = 'music.google.com'
var parts = url.split('.');
for(part in parts) {
if(part == 'com') {
return true;
}
{
uri = "foo.bar.baz.com"
uri.split(".").slice(-2).join(".") // returns baz.com
This assumes that you want just the hostname and tld. It also assumes that there is no path information either.
Updated now that you also need to handle uris with paths you could do:
uri.split(".").slice(-2).join(".").split("/")[0]
Use regexp to do that. This way modifications to the detections are quite easy.
var url = 'www.siphone.com';
var domain = url.match(/[^.]\.com/i)[0];
If you use url.match(/(([^.]+)\.com)[^a-z]/i)[1] instead. You can assure that the ".com" is not followed by any other characters.

RegExp to match words wrapped in braces

In javascript, I've got a block of HTML like this:
<h2>{title}</h2>
<p>{content}</p>
And I'm trying use regex "match" to spit out an array of all the {item}'s. So my output should look like:
['title', 'url', 'content']
I've gotten as far as:
var pattern = new RegExp("\{[a-zA-Z]+\}+");
var match = pattern.exec("{Sample} bob {text}");
But it's only returning the first tag.
This is just beyond my regex skills. Can anyone help?
Cheers!
You need to create a pattern with the global flag:
var pattern = new RegExp("\{[a-zA-Z]+\}", "g");
or:
var pattern = /\{[a-zA-Z]+\}/g;
Then you can call the match() method on your string to get a list of matches:
var matches = "{Sample} bob {text}".match(pattern);
I think you want:
var pattern = new RegExp("\{[a-zA-Z]+\}+", "g");
The second option is a flag telling it to search the entire string and return all matches.
See: http://www.evolt.org/article/Regular_Expressions_in_JavaScript/17/36435/ for more details.
Have you tried this yet?
<script>
var text = '<h2>{title}</h2>\n<p>{content}</p>';
var regex = /\{[a-z]+\}/ig;
var result = text.match(regex);
for (var i = 0; i < result.length; i++) {
console.debug(i + ". " + result[i]);
}
/*
gives:
0. {title}
1. {test}
2. {url}
3. {content}
*/
</script>
Much as I like to roll my own RegExp (and you really just need the global flag), have you looked at prototype templates, Trimpath JST or anything like that?
Because possibly rolling your own won't be as efficient for reuse as the above examples. EG:
String.prototype.template = function (obj) {
return this.replace(/{([^{}]+)}/g,
function (full, word) {
return((typeof obj[word]==='string'||typeof obj[word]==='number')?obj[word]:full);
}
);
};
"The {adj1} {adj2} {noun}.".template({adj1: 'lazy',adj2: 'brown', noun: 'dog'})
==> "The lazy brown dog."
This runs your regex each time, while I believe the prototype templates basically does it once.
I got off path by using exec for testing.

Categories

Resources