URL String validation in iOS using NSRegularExpression - ios

I would like to validate whether an NSString can be converted to a valid NSURL. I know that using URLWithString will make a URL, but it is not always valid. Additionally, I don't want to make a web call every time my user enters a string to verify the URL as that is not battery/data efficient, and it relies on having an active web connection which is not always the case. I came across this site various URLs, and I am now attempting to copy the regex they used and convert it to NSRegular Expression. I've been using this helpful cheatsheet to try and convert it, but to no avail. I stored the regex as a const like so:
static NSString * const urlPattern = #"_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?#)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS";
I have been attempting to convert this by adding escape characters in front of all special characters listed in the cheatsheet, but it doesn't seem to be working properly. Has anyone here has any luck getting #diegoperini's URL regex to work in Objective-C or Swift using NSRegularExpressions?

Related

Why Asp.Net Core QueryHelpers don't encode # (at) symbol?

Reading various resources on the internet, it seems, that we have to encode # sign in the query params of the URL (as well as in most of the other places of the URL).
I was trying to generate an URL in my ASP.NET Core app and found a way to do this using QueryHelpers.AddQueryString(...). But it seems not to be encoding # symbol, even though it is encoding all other symbols that I tested.
Question: Is there some particular reason for such behaviour, or is it just a bug?
My test that passes:
var url0 = QueryHelpers.AddQueryString("base", "field", "&?=čž/");
Assert.Equal("base?field=%26%3F%3D%C4%8D%C5%BE%2F", url0);
var url = QueryHelpers.AddQueryString("base", "field", "#");
Assert.Equal("base?field=#", url);
That's because, simply, # doesn't need to be encoded. It's not a character that means anything in the context of a URL, so it's fine as is. The characters like &, ? and = all have meaning in the context of a URL and thus must be encoded. As far as the unicode characters go, I believe these are encoded just for safety. Unicode is technically supported in URLs, but support for that is relatively recent, and may not be universally implemented. It's not going hurt to encode them, and that way it'll just work without issue.

NSURL "URLByAppendingPathExtension:" bug?

NSURL's URLByAppendingPathExtension: doesn't seem to be acting properly for me. I am trying to add a path to the end of an existing URL. For example:
[[NSURL URLWithString:#"https://www.example.com"] URLByAppendingPathExtension:#"/10392983/example"]
Should be returning an URL with http://www.example.com/10392983/example according to the documentation. Instead, it is escaping the slashes. I can achieve the same result converting to the URL to an absolute string and using regular NSString operations, but the above seems like it would be a lot more elegant. Any ideas as to which NSURL method to use to achieve this result or is this truly a bug?
For what you are trying to do, you should use:
URLByAppendingPathComponent
According to the docs, URLByAppendingPathExtension is for extensions like .html. It's a little vague, but from the docs:
If the original URL ends with one or more forward slashes, these are
removed from the returned URL. A period is inserted between the two
parts of the new URL.
This makes me think that this should only be used for appending things like .html and .php to URLs. Just use URLByAppendingPathComponent instead.
NSURLs can get confusing and weird.
Documentation for URLByAppendingPathExtension says that:
"If the original URL ends with one or more forward slashes, these are removed from the returned URL. A period is inserted between the two parts of the new URL."
"removed from the returned URL" implies that these '/' forward slash characters will be replaced with their escaped counterparts (that is a % sign for forward slashes).
UrlByAppendingPathComponent from #scott's answer does not appear to work in my tests? The method needs to be spelled 'URLByAppendingPathComponent' with a capitalized 'URL' and not the lowercase 'Url' .
Try this:
[NSURL URLWithString:[#"https://www.example.com" stringByAppendingPathComponent:#"/10392983/example"]]
That will produce the NSURL with a similar level of elegance-complexity. You can also tack on any number of "stringByAppendingPathComponent" methods to produce your NSURL.
Conversely here's an example of scott's code above:
NSURL*combined = [baseURL URLByAppendingPathComponent: stringPath];

AFNetworking and URL construction - can I change the behaviour?

I'm busy with web service and an iOS app. So far I haven't had that many issues. However, there is a web service that needs the final URL request to be in a certain format. Something along the lines of:
...?IncludedUserIds[]=1357213,286476&..
These parameters are constructed from an NSDictionary and NSString. Now when I add the comma - the end URL that makes the request ends up like this:
..?IncludedUserIds=%5B%5D1357213%2C286476&...
It seems that AFNetworking 2.0 has converted the square brackets into =%5B%5D and the comma into: %2C
Obviously, the web service has no idea what this means and fails.
Is there a way to keep the final Url as I need it to be? Why do these conversions happen and where can I learn more about this sort of thing?
AFNetworking keep the final url encoded, that is the best way, since you could have special characters in you query string that could break all. Instead, you should decode the url server side, for example in PHP you have methods, like urldecode or rawurldecode (eg: 'foo%20bar%40baz' ->'foo bar#baz'), or in ASP it should be kept automatically.
Hope it helps

Storing URL string with special characters in NSString in Objective-C

I am trying to use Freebase in an iOS app, and queries are constructed using URL's. The URL's contain multiple special characters ({}, :) but I would like to be able to use the URL strings so I can download the data from Freebase.
https://www.googleapis.com/freebase/v1/mqlread?query=[{"type":"/music/album","name":null,"artist":{"id":"/en/bob_dylan"},"limit":3}]&cursor
When loading the URL in Safari, the browser actually converts that string to this: https://www.googleapis.com/freebase/v1/mqlread?query=%5B%7B%22type%22:%22/music/album%22,%22name%22:null,%22artist%22:%7B%22id%22:%22/en/bob_dylan%22%7D,%22limit%22:3%7D%5D&cursor
Any help would be greatly appreciated.
You can use this method on an NSString to add the percent escapes for you.
- (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding

Some values not able to send by nsurl?

I have a very strange phenomenon going on with my script. When they are manually made in the script, everything works. When I upload it by iOS, however, it appears that a few of my strings prevent it from sending (when I remove those variables, it sends and executes the insert commands fine again with only the values sent). What I mean by prevent is it fails to send the request at all and I get no insert (the script is designed to insert whatever it gets). Even crazier, is that I nsslog is showing the proper values in those positions just before executing the nsurl. Therefore, I was curious if it is possible for nsurl to be blocked by some of its own values? The values that block it are two of my six text fields and one of two nsstrings passed from another view controller. I have given an example of my format here.
NSString *urlString = [NSString stringWithFormat:#"http://(mywebsite)?string=%#&text=%#", string, textfield.text];
If you're text contains unescaped characters like #, ?, ' or " for example, then yes, the content of your url will cause issues. For example, if i enter "'abcd'&x=50" into your textfield, then your web string will suddenly have an x parameter. Or, you can add in stuff like colons, backslashes etc.
If you correctly escape your string, you should be able to build URL's that way.

Resources