I'm using the window.atob('string') function to decode a string from base64 to a string. Now I wonder, is there any way to check that 'string' is actually valid base64? I would like to be notified if the string is not base64 so I can perform a different action.
If you want to check whether it can be decoded or not, you can simply try decoding it and see whether it failed:
try {
window.atob(str);
} catch(e) {
// something failed
// if you want to be specific and only catch the error which means
// the base 64 was invalid, then check for 'e.code === 5'.
// (because 'DOMException.INVALID_CHARACTER_ERR === 5')
}
Building on #anders-marzi-tornblad's answer, using the regex to make a simple true/false test for base64 validity is as easy as follows:
var base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
base64regex.test("SomeStringObviouslyNotBase64Encoded..."); // FALSE
base64regex.test("U29tZVN0cmluZ09idmlvdXNseU5vdEJhc2U2NEVuY29kZWQ="); // TRUE
Update 2021
Following the comments below it transpires this regex-based solution provides a more accurate check than simply try`ing atob because the latter doesn't check for =-padding. According to RFC4648 =-padding may only be ignored for base16-encoding or if the data length is known implicitely.
Regex-based solution also seems to be the fastest as hinted by kai. As jsperf seems flaky atm i made a new test on jsbench which confirms this.
This should do the trick.
function isBase64(str) {
if (str ==='' || str.trim() ===''){ return false; }
try {
return btoa(atob(str)) == str;
} catch (err) {
return false;
}
}
If "valid" means "only has base64 chars in it" then check against /[A-Za-z0-9+/=]/.
If "valid" means a "legal" base64-encoded string then you should check for the = at the end.
If "valid" means it's something reasonable after decoding then it requires domain knowledge.
I would use a regular expression for that. Try this one:
/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/
Explanation:
^ # Start of input
([0-9a-zA-Z+/]{4})* # Groups of 4 valid characters decode
# to 24 bits of data for each group
( # Either ending with:
([0-9a-zA-Z+/]{2}==) # two valid characters followed by ==
| # , or
([0-9a-zA-Z+/]{3}=) # three valid characters followed by =
)? # , or nothing
$ # End of input
This method attempts to decode then encode and compare to the original. Could also be combined with the other answers for environments that throw on parsing errors. Its also possible to have a string that looks like valid base64 from a regex point of view but is not actual base64.
if(btoa(atob(str))==str){
//...
}
This is how it's done in one of my favorite validation libs:
const notBase64 = /[^A-Z0-9+\/=]/i;
export default function isBase64(str) {
assertString(str); // remove this line and make sure you pass in a string
const len = str.length;
if (!len || len % 4 !== 0 || notBase64.test(str)) {
return false;
}
const firstPaddingChar = str.indexOf('=');
return firstPaddingChar === -1 ||
firstPaddingChar === len - 1 ||
(firstPaddingChar === len - 2 && str[len - 1] === '=');
}
https://github.com/chriso/validator.js/blob/master/src/lib/isBase64.js
For me, a string is likely an encoded base64 if:
its length is divisible by 4
uses A-Z a-z 0-9 +/=
only uses = in the end (0-2 chars)
so the code would be
function isBase64(str)
{
return str.length % 4 == 0 && /^[A-Za-z0-9+/]+[=]{0,2}$/.test(str);
}
Implementation in nodejs (validates not just allowed chars but base64 string at all)
const validateBase64 = function(encoded1) {
var decoded1 = Buffer.from(encoded1, 'base64').toString('utf8');
var encoded2 = Buffer.from(decoded1, 'binary').toString('base64');
return encoded1 == encoded2;
}
I have tried the below answers but there are some issues.
var base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
base64regex.test(value)
when using this it will be true with "BBBBB" capital letters. and also it will be true with "4444".
I added some code to work correctly for me.
function (value) {
var base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
if (base64regex.test(value) && isNaN(value) && !/^[a-zA-Z]+$/.test(value)) {
return decodeURIComponent(escape(window.atob(value)));
}
Throwing my results into the fray here.
In my case, there was a string that was not base64 but was valid base64 so it was getting decoded into gibberish. (i.e. yyyyyyyy is valid base64 according to the usual regex)
My testing resulted in checking first if the string was a valid base64 string using the regex others shared here and then decrypting it and testing if it was a valid ascii string since (in my case) I should only get ascii characters back. (This can probably be extended to include other characters that may not fall into ascii ranges.)
This is a bit of a mix of multiple answers.
let base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
function isBase64(str) {
if (str ==='' || str.trim() ===''){ return false; }
try {
if (base64regex.test(str)) {
return /^[\x00-\x7F]*$/.test(atob(str));
} else {
return false
}
} catch (err) {
// catch
}
}
As always with my JavaScript answers, I have no idea what I am doing. So there might be a better way to write this out. But it works for my needs and covers the case when you have a string that isn't supposed to be base64 but is valid and still decrypts as base64.
I know its late, but I tried to make it simple here;
function isBase64(encodedString) {
var regexBase64 = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
return regexBase64.test(encodedString); // return TRUE if its base64 string.
}
Related
Well, I'm trying to pass a simple if statement to a process.stdin readable stream in NodeJS. But it doesn't seem working. Here's the code :
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null && chunk == 'foo') {
process.stdout.write('true\n');
} else if (chunk !== null) {
process.stdout.write('false\n');
}
Does anyone know, what am I doing wrong here? I also tried chunk == 'foo\n' but, had no luck. The only time it works is when I set chunk value to a number, like chunk == 10.
#Siam the issue here is that the chunk is of Buffer type, and not a string. You can use chunk.toString() to make it a string, and then compare it with "foo\n" and it would work
So your code would look something like this:
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null && chunk.toString() == 'foo\n') {
process.stdout.write('true\n');
} else if (chunk !== null) {
process.stdout.write('false\n');
}
});
EDIT 1:
Make sure that you are using compare string same as the input. for e.g in the above case, New line character can be CRLF or \r\n on windows based systems, while on Unix based systems its LF or \n. Hence, try using "foo\r\n" for comparison, if on windows
You can use the .prompt() (example) method
I am looking for a function that can tell me to which data type a string might be converted.
Examples:
"28.98" results in float (. as separator)
"44.332,95" results in float (, as separator)
"29/04/14" results in date (should work internationally -> different date formats)
"34.524" results in int (. as delimited)
"all the rest" results in string
Ideally also (these are subclasses of string):
"something#example.com" results in e-mail
"+49/2234/234567" results in phone
Is there a (open source) libary can can do such thing?
Thanks!
There you have it. Not a library, unhealthy amount of regular expressions, but it works with your examples. If you need other things to be matched, please add more examples. Open to critique or requirements in the comments.
function getType(str){
if (typeof str !== 'string') str = str.toString();
var nan = isNaN(Number(str));
var isfloat = /^\d*(\.|,)\d*$/;
var commaFloat = /^(\d{0,3}(,)?)+\.\d*$/;
var dotFloat = /^(\d{0,3}(\.)?)+,\d*$/;
var date = /^\d{0,4}(\.|\/)\d{0,4}(\.|\/)\d{0,4}$/;
var email = /^[A-za-z0-9._-]*#[A-za-z0-9_-]*\.[A-Za-z0-9.]*$/;
var phone = /^\+\d{2}\/\d{4}\/\d{6}$/g;
if (!nan){
if (parseFloat(str) === parseInt(str)) return "integer";
else return "float";
}
else if (isfloat.test(str) || commaFloat.test(str) || dotFloat.test(str)) return "float";
else if (date.test(str)) return "date";
else {
if (email.test(str)) return "e-mail";
else if (phone.test(str)) return "phone";
else return "string";
}
}
Has been a while since I worked with JavaScript frameworks, but what you are working on is rather simple. You can do it yourself, by checking if the logical differences exist in your string, the way you are presenting them here. For example, you can use the indexOf() JavaScript function to check if an # sign exists in your string. If you have both a dot and a comma, means that you get a floating point number. Lastly, the difference you want between 28.98 and 34.524 cannot be presented in any way, since the . is always a floating point mark for numbers, meaning that 34.524 is a float for both human and computer.
Hope it helps - probably not with the library you were asking for though!
indexOf() function in w3schools.com
Thanks to some of the answers on this site, I built a function to validate an integer inside a prompt in javascript. I found out how to use isNaN and the result of % in order to meet my needs, but there must be something wrong, because is still not working: This function for validation needs to accept only integers, and as extra bonus, it will also accept a special keyword used for a different purpose later on in the program.
So, previously I had defined:
var value = prompt("Type an integer");
So after that, I made a call for the validation function, and that included three conditions: The validation warning would jump if:
1) The string is not a number
2) The string % 1 is not 0 (means is not an integer)
3) The string is not the special keyword ("extra") which is also valid as input.
The function needs to loop and keep showing the prompt until a valid data is written.
while (isNaN(value) == true && value % 1 != 0 && value != "extra") {
alert("Please, type an integer");
var value = prompt("Type an integer");
}
What am I doing wrong? Thank you so much for any ideas. I know the integer validation has been asked many times here, and here I got a few ideas, but I might be missing something...
You might be complicating things too much... A quick regular expression will do the trick.
while (!/^(\d+|extra)$/i.test(value)) {
...
}
You typed only one equal at
isNaN(value) = true
jsFiddle example
var int = 10;
var str = "10";
var isInt = function(value) {
return (str === 'extra' || !isNaN(parseInt(value, 16)) || /^\d+$/.test(value));
};
var isIntStrict = function(value) {
return (isInt(value) && typeof value !== 'string');
}
console.log('false', isInt('kirk'));
console.log('true', isInt(int));
console.log('true', isInt(str));
console.log('true', 'strict - int', isIntStrict(int));
console.log('false','strict - string', isIntStrict(str));
console.log('false','strict - string', isIntStrict('0x04'));
console.log('true','strict - string', isIntStrict(0x04));
I assume that for your purposes #elclanrs' answer is all you need here, and is the simplest and most straightforward, but just for completeness and dubious laughs, I'm pretty sure that the following would also do what you're looking for:
function isAnIntOrExtra(v) {
if (parseInt(+v) === +v && v !== '') {
return parseInt(+v);
}
else if (v === 'extra') {
return v;
}
else {
return false;
}
}
Fiddle here
These should all pass and return an integer in decimal notation:
'387' returns 387
'-4' returns -4
'0' returns 0
'2.4e3' returns 2400
'0xf4' returns 244
while these should all fail:
'4.5' returns false
'2.4e-3' returns false
'0xgc' returns false
'' returns false
'seven' returns false
And the magic-word 'extra' returns 'extra'
Of course, it'll "fail" miserably with values like '1,345', and will probably roll right over octal notation, treating it as though it were decimal notation (depending on the JavaScript engine?), but it could be tweaked to handle those situations as well, but really, you're better off with the regex.
Goal:
I dont wanna retrieving any data if the input data contain any alphabet.
Problem:
If I have input data "23w" in variable ddd, the process on convertion is accceptable to be "23" in the variable currentvalue.
I don't want it to be converted into number if the input data contain
any alphabet.
The sourcecode is writtin in jQuery and if possible it would be great to retreive the new solution in jQuery.
// Fullmetalboy
var ddd = $('#field_hourInput').val();
var currentValue = parseInt(ddd);
// Validating message
if(currentValue <= 0)
{
alert("Value must be positiv");
nonError = false;
}
else if( (isNaN(currentValue)) && (ddd != "") )
{
alert("value must contain numbers");
nonError = false;
}
else if( (isNaN(currentValue)) && (ddd == "") )
{
alert("value must contain value in the textbox");
nonError = false;
}
parseint() will return a number if the string begins with one, even if there is non-numbers following it. For example: http://jsfiddle.net/uQztw/
Probably better to use a regex. Something like
http://jsfiddle.net/uQztw/1/
You can use regex to validate that. Using regex with jquery. And using regex
[\d]
which will match any digit should do the trick.
Another way to convert string to int is Number(ddd), it does what you expect. But you could also check ddd through a regular expression, which feels better to me.
regexp-test: /^\d+$/.test(ddd)
I am trying to validate a string as a phone number (digits and certain special characters). I used a existing code snippet from here: http://snippets.dzone.com/posts/show/597 which seems to be correct. But everytime string.match(format) returns null, which causes to show the error message.
var format = /^(\+\d)*\s*(\(\d{3}\)\s*)*\d{3}(-{0,1}|\s{0,1})\d{2}(-{0,1}|\s{0,1})\d{2}$/;
var string = jQuery(".validate_phone").val();
if (string.match(format) != true) {
// some error message
}
I checked already, string is filled which the expected value.
The following values should match:
339-4248
339-42-48
339 42 48
339 4248
3394248
(095) 3394248
(095)3394248
+7 (095) 3394248
+7 (095)3394248
+7(095) 3394248
+7(095)3394248
Everything else should show the error message.
What is wrong with this code? Thanks in advance!
Update: Here is a test case http://labuschin.com/material/phone
A friend over at Facebook helped me out successfully:
var format = /(\+\d)*\s*(\(\d{3}\)\s*)*\d{3}(-{0,1}|\s{0,1})\d{2}(-{0,1}|\s{0,1})\d{2}/;
var nr= prompt("Phone number", "");
if (nr.match(format) == null) {
alert ("incorrect");
} else {
alert ("correct");
}
Changed if-clause and and removed the ^ at the beginning and the $ at the end. Works here: http://labuschin.com/material/phone
A valid regex for that would be: (\+\d\s*)?(\(\s*\d{3}\s*\)\s*)?\d{3}([- ]?\d{2}){2}.
However, match() returns null on non-matches and an array of captured values on matches - it will never return true. You are probably more interested in search() which returns the match position or -1 if the regex didn't match. E.g.:
var format = /^(\+\d\s*)?(\(\s*\d{3}\s*\)\s*)?\d{3}([- ]?\d{2}){2}$/;
var string = jQuery(".validate_phone").val();
if (string.search(format) == -1) {
// some error message
}
Maybe... you should not use "string" as var name.
var format = /^(\+\d)*\s*(\(\d{3}\)\s*)*\d{3}(-{0,1}|\s{0,1})\d{2}(-{0,1}|\s{0,1})\d{2}$/;
var nr= prompt("Phone number", "");
if (!nr.match(format)) {
alert ("incorrect");
} else {
alert ("correct");
}
works for me.