Why is split and join doing this? - javascript

I'm getting some very weird behaviour that I don't understand using JavaScript split and join. I'm sending names with spaces in an API call but using %3 as the delimiter for spaces, as in, if I'm sending "Ammar Ahmed", the API call would look like: api/v1?q=Ammar%3Ahmed. In the server code, when I split it up again with q.split("%3").join(" ") because the database contains names with spaces, for one name in particular: "Ashwini Bettahalsoor", I'm getting "Ashwini;ettahalsoor". I'm very confused why its doing this, its splitting it including the B and joining it with a ; but it works perfectly normal for all names that the last name does not start with B. I'm sure it has something to do with the letter B but first of all I'm curious as to why this is happening and secondly, I'm wondering what I should use instead of %3 for spaces in the API call.

%3 is not the correct encoding for a space. You're getting ; because %3B is the encoding for that character. URI encoding always uses 2 hex digits.
You should use encodeURICompnent() to generate the correct encoding.
let url = 'api/v1?q=' + encodeURIComponent('Ashwini Bettahalsoor');
And on the server you should use middleware that decodes the query parameters for you, rather than using split() and join() explicitly.

Related

Convert invalid JSON (having equal sign instead of colon, no quotes etc) to valid JSON

I am getting data from Cardstream payment gateway android sdk (in native module) to react native but the data is not a valid JSON:
'{ __wafRequestID=2021-06-16T08:02:14Z|0e2314f32f|115.186.169.10|gk0GHP1i4V, action=SALE, addressCheckPref=not known,not checked,matched,not matched,partially matched, amount=14, amountRetained=0, avscv2CheckEnabled=Y, caEnabled=Y, cardCVVMandatory=Y, cardExpiryDate=0322, cardFlags=8323072, cardIssuer=UNKNOWN, cardIssuerCountry=United Kingdom, cardIssuerCountryCode=GBR, cardNumberMask=424242******4242, cardNumberValid=Y, cardScheme=Visa, cardSchemeCode=VC, cardType=Visa Credit, cardTypeCode=VC, cftEnabled=N, countryCode=826, currencyCode=826, currencyExponent=2, customerName=fgg, customerReceiptsRequired=Y, cv2CheckPref=not known,not checked,matched,not matched,partially matched, eReceiptsEnabled=N, merchantAlias=100001, merchantID=100001, merchantID2=100001, paymentMethod=card, postcodeCheckPref=not known,not checked,matched,not matched,partially matched, processMerchantID=100001, requestID=60c9b007225c7, requestMerchantID=100001, responseCode=65566, responseMessage=Disallowed cardnumber, responseStatus=2, riskCheckEnabled=Y, riskCheckPref=not known=continue,not checked=continue,approve=continue,decline=decline1,review=authonly,escalate=authonly, riskProcessorID=41, riskProcessorName=Kount, rtsEnabled=Y, scaExemption=lowvalue,trusted, state=finished, surchargeEnabled=Y, surchargeRequired=Y, threeDSCheckPref=authenticated, threeDSEnabled=N, timestamp=2021-06-16 09:02:16, transactionID=112446674, type=1, vcsResponseCode=0, vcsResponseMessage=Success, xref=21061609KX02TQ16YP35TTD}'
How to convert it to valid JSON so that I can parse it? I have tried few regex replacements but some values also have colons which is messing it up.
If you wanted to try an parse this with regex then this might work:
[{,] (?<key>[a-zA-Z0-9_]+)=(?<value>.*?(?=, [a-zA-Z0-9_]+=|\}$))
https://regex101.com/r/Fk7NvR/1
Just loop through the matches and access the captured groups named key and value respectively. The value for riskCheckPref seems suspect but I have no clue about their parsing rules.
An alternate idea would be to remove the outer curly braces, trim white space, split on , (comma space), and split again on the first =.
I converted response to JSON in android and then passed it to react-native instead of passing response to react-native (which gets passed in this invalid format) and then banging my head to convert it to JSON. My bad. Thanks all

NodeJS escaping back slash

I am facing some issues with escaping of back slash, below is the code snippet I have tried. Issues is how to assign a variable with escaped slash to another variable.
var s = 'domain\\username';
var options = {
user : ''
};
options.user = s;
console.log(s); // Output : domain\username - CORRECT
console.log(options); // Output : { user: 'domain\\username' } - WRONG
Why when I am printing options object both slashes are coming?
I had feeling that I am doing something really/badly wrong here, which may be basics.
Update:
When I am using this object options the value is passing as it is (with double slashes), and I am using this with my SOAP services, and getting 401 error due to invalid user property value.
But when I tried the same with PHP code using same user value its giving proper response, in PHP also we are escaping the value with two slashes.
When you console.log() an object, it is first converted to string using util.inspect(). util.inspect() formats string property values as literals (much like if you were to JSON.stringify(s)) to more easily/accurately display strings (that may contain control characters such as \n). In doing so, it has to escape certain characters in strings so that they are valid Javascript strings, which is why you see the backslash escaped as it is in your code.
The output is correct.
When you set the variable, the escaped backslash is interpreted into a single codepoint.
However, options is an object which, when logged, appears as a JSON blob. The backslash is re-escaped at this point, as this is the only way the backslash can appear validly as a string value within the JSON output.
If you re-read the JSON output from console.log(options) into javascript (using JSON.parse() or similar) and then output the user key, only one backslash will show.
(Following question edit:)
It is possible that for your data to be accepted by the SOAP consuming service, the data needs to be explicitly escaped in-band. In this case, you will need to double-escape it when assigning the value:
var s = 'domain\\\\user'
To definitively determine whether you need to do this or not, I'd suggest you put a proxy between your working PHP app and the SOAP app, and inspect the traffic.

Regex javascript to only return a value and not full match

How do we do look behind in java script like we can in java or php?
RegEx works for php parser using lookbehind
Here is the working Regex using php parser.
(?<=MakeName=)(.*?)([^\s]+)
This produces the value
(MakeName=)(.*?)([^\s]+)
this produces the match + value
xml response to extract value from.
<ModelName="Tacoma" MakeName="Tundra" Year="2015">
I just need the value
There is no look-behind in JavaScript.
If you are sure the attribute MakeName is present in the input, then you could use this regular expression:
/[^"]*(?!.*\sMakeName\s*=)(?="([^"]*"[^"]*")*[^"]*$)/
It grabs the first series of characters that do not contain a double quote and have a double quote immediately following it, with an even number of double quotes following after that until the end of the input (to make sure we are matching inside a quoted string), but MakeName= should not occur anywhere after the match.
This is of course still not bullet proof, as it will fail for some boundary cases, like with single quoted values.:
<ModelName="Tacoma" MakeName='Tundra' Year="2015">
You could resolve that, if needed, by repeating the same pattern, but then based on single quotes, and combining the two with an OR (|).
Demo:
var s = '<ModelName="Tacoma" MakeName="Tundra" Year="2015">';
result = s.match(/[^"]*(?!.*\sMakeName\s*=)(?="([^"]*"[^"]*")*[^"]*$)/);
console.log(result[0]);

AngularJS $location search confused

This is my url with params look like:
http://localhost:8000/search?city=uk&cat=Sightseeing%20&%20Tours
But when I try to capture the cat params using:
var test2 = $location.search().cat;
it only return Sightseeing. How can I resolve this issues? Thanks!!
The ampersand (&) is the delimiter for URL parameters. This means that the cat parameter ends after Sightseeing%20. (The %20 is probably automatically converted to a space, rendering it invisible.)
There is a simple solution though; just percent-encode the ampersand; use %26. Note most programming languages provide some function to automatically percent-encode strings, in PHP for example it would be urlencode().
For more information, see https://en.wikipedia.org/wiki/Percent-encoding. It talks about reserved and unreserved characters in URLs, which is exactly what's causing your problem; the ampersand is a reserved character.

correct way to exclude certain characters from crypto.randomBytes

i have the following code, based on http://nodejs.org/docs/v0.6.9/api/crypto.html#randomBytes
crypto.randomBytes 32, (ex, buf) ->
user.tokenString = buf.toString("hex")
user.tokenExpires = Date.now() + TOKEN_TIME
next()
i am using this to generate a tokenString to use for a node.js/express user validation.
in some cases the tokenString generated includes '/' forward slash character, and this breaks my routes, for example, tokenString if the tokenString is like '$2a$10$OYJn2r/Ts.guyWqx7iJTwO8cij80m.uIQV9nJgTt18nqu8lT8OqPe' it can't find /user/activate/$2a$10$OYJn2r and i get an 404 error
is there a more direct way to exclude certain characters from being included when generating the crypto.randomBytes?
Crypto.randomBytes generates random bytes . That has nothing to do with characters, characters are determined by the way we look at the bytes.
For example:
user.tokenString = buf.toString("hex")
Would convert the buffer to a string (where two characters represent each byte), in the character range 0-9a-f
Another (might be more suiting approach is to use a more compact encoding. Base64Url is an encoding that provides string encoding that is URL/Filename safe
user.tokenString = base64url(buf)
Here is an NPM package you can use for it.
Other than that, your code seems fine. If you were to call .toString() without specifying "hex" or specifying something like "ascii" for example, it would break just like in your question description.

Categories