Is string a valid url? lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- rgh · 2019-10-28 19:49 Is there some class I can use to test if a string is a syntactically valid url? What I'm trying to do at the moment is use one of the (breathtakingly complicated) regex patterns a google search reveals, such as: https://stackoverflow.com/questions/161738/what-is-the-best-regular- expression-to-check-if-a-string-is-a-valid-url replacing all the single quotes in it with double quotes, until I get a valid pascal string, and using it with TRegExpr. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode OBJFPC}{$H+} program regextest;uses RegExpr;var  re : TRegExpr;  expression : String = '/^[a-z](?:[-a-z0-9\+\.])*:(?:\/\/(?:(?:%[0-9a- f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}- \x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}- \x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}- \x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}- \x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}- \x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}- \x{EFFFD}!\$&''\(\)\*\+,;=:])*@)?(?:\[(?:(?:(?:[0-9a- f]{1,4}:){6}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0- 9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0- 4][0-9]|25[0-5])){3})|::(?:[0-9a-f]{1,4}:){5}(?:[0-9a-f]{1,4}:[0-9a- f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0- 5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0- 5])){3})|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}(?:[0-9a-f]{1,4}:[0- 9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0- 5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0- 5])){3})|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a- f]{1,4}:){3}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0- 9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0- 4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a- f]{1,4})?::(?:[0-9a-f]{1,4}:){2}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0- 9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0- 9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,3}[0- 9a-f]{1,4})?::[0-9a-f]{1,4}:(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0- 9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0- 9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,4}[0- 9a-f]{1,4})?::(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:[0-9]|[1-9][0-9]|1[0- 9][0-9]|2[0-4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0- 4][0-9]|25[0-5])){3})|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0- 9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|v[0-9a-f]+\.[- a-z0-9\._~!\$&''\(\)\*\+,;=:]+)\]|(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0- 4][0-9]|25[0-5])(?:\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0- 5])){3}|(?:%[0-9a-f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}- \x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}- \x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}- \x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}- \x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}- \x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}- \x{EFFFD}!\$&''\(\)\*\+,;=])*)(?::[0-9]*)?(?:\/(?:(?:%[0-9a-f][0-9a- f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}- \x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}- \x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}- \x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}- \x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}- \x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}- \x{EFFFD}!\$&''\(\)\*\+,;=:@]))*)*|\/(?:(?:(?:(?:%[0-9a-f][0-9a-f]|[- a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}- \x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}- \x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}- \x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}- \x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}- \x{DFFFD}\x{E1000}-\x{EFFFD}!\$&''\(\)\*\+,;=:@]))+)(?:\/(?:(?:%[0-9a- f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}- \x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}- \x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}- \x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}- \x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}- \x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}- \x{EFFFD}!\$&''\(\)\*\+,;=:@]))*)*)?|(?:(?:(?:%[0-9a-f][0-9a-f]|[-a- z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}- \x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}- \x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}- \x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}- \x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}- \x{DFFFD}\x{E1000}-\x{EFFFD}!\$&''\(\)\*\+,;=:@]))+)(?:\/(?:(?:%[0-9a- f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}- \x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}- \x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}- \x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}- \x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}- \x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}- \x{EFFFD}!\$&''\(\)\*\+,;=:@]))*)*|(?!(?:%[0-9a-f][0-9a-f]|[-a-z0- 9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}- \x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}- \x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}- \x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}- \x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}- \x{DFFFD}\x{E1000}-\x{EFFFD}!\$&''\(\)\*\+,;=:@])))(?:\?(?:(?:%[0-9a- f][0-9a-f]|[-a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}- \x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}- \x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}- \x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}- \x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}- \x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}- \x{EFFFD}!\$&''\(\)\*\+,;=:@])|[\x{E000}-\x{F8FF}\x{F0000}- \x{FFFFD}\x{100000}-\x{10FFFD}\/\?])*)?(?:\#(?:(?:%[0-9a-f][0-9a-f]|[- a-z0-9\._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}- \x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}- \x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}- \x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}- \x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}- \x{DFFFD}\x{E1000}- \x{EFFFD}!\$&''\(\)\*\+,;=:@])|[\/\?])*)?$/i'; begin  re := TRegExpr.Create(expression);  WriteLn(re.Exec('http://www.google.com'));   re.Free;end.  Unsurprisingly, although it compiles, it doesn't work. Code: [Select]rgh@HP-ProBook-450-G2:~/projects/fpc/regex$ ./regextest An unhandled exception occurred at $000000000042B898: ERegExpr: TRegExpr(comp): Urecognized Modifier (pos 23)   $000000000042B898   $0000000000426CDC rgh@HP-ProBook-450-G2:~/projects/fpc/regex$ Is there some class I can just use, without needing to become a regex guru in the process? ---------------------------------------------------------------------- fmc · 2019-10-28 20:25 If you're looking for invalid URL chars, then maybe this will help. It has a small footprint and checks e-mail entries to make sure they contain at least one '.' and one '@'. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   a:= someEmailEntry;  if (pos('@',a) = 0) or (pos('.',a) = 0) then    MessageDlg('Warning', a + ' is not a valid email address.', mtError,[mbOK],0); For you, maybe some of this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   a:= myURL;  if (pos('\',a) <> 0) or (pos('!',a) <> 0) then    MessageDlg('Warning', a + '  is not a valid URL.', mtError,[mbOK],0); I don't know all of the invalid chars for URLs. But if you do, then this cld get you away from the RegEx stuff. Just an idea. Good luck. ---------------------------------------------------------------------- winni · 2019-10-28 21:19 Hi! RegEx is for real problems. This is not one. Allowed chars are A..Z a..z 0..9 -._~:/#[]@!$&'()*+,;=. Build a set of this chars as constant. Look for every char in the string if he is in the set. If not: not valid if all in set : valid Just one simple loop Winni ---------------------------------------------------------------------- ASBzone · 2019-10-28 23:23 Quote from: winni on October 28, 2019, 10:19:05 pmHi! RegEx is for real problems. This is not one. Allowed chars are A..Z a..z 0..9 -._~:/#[]@!$&'()*+,;=. Build a set of this chars as constant. Look for every char in the string if he is in the set. If not: not valid if all in set : valid Just one simple loop Winni Um... But that would not guarantee a value URL ".&.?abcd" doesn't have any invalid characters, yet is not a valid URL ---------------------------------------------------------------------- 440bx · 2019-10-29 00:09 Quote from: rgh on October 28, 2019, 08:49:57 pmIs there some class I can use to test if a string is a syntactically valid url? If there is one, I am not aware of it. Quote from: rgh on October 28, 2019, 08:49:57 pmWhat I'm trying to do at the moment is use one of the (breathtakingly complicated) regex patterns a google search reveals, such as: https://stackoverflow.com/questions/161738/what-is-the-best-regular- expression-to-check-if-a-string-is-a-valid-url it is stuff like that, that proves that very smart people have the ability to take binary garbage to new heights. As far as using Regex to validate a URL, I suggest reading the article at: https://thedailywtf.com/articles/how-to-validate-a-url common sense is such a nice thing, too bad it's not all that common. Quote from: rgh on October 28, 2019, 08:49:57 pmUnsurprisingly, although it compiles, it doesn't work. That's actually very good news, If it worked it would be harder to justify putting that code where it legitimately belongs: the trash can. Quote from: rgh on October 28, 2019, 08:49:57 pmIs there some class I can just use, without needing to become a regex guru in the process? You don't need to become a regex guru.  The best, not to mention correct, approach to solving that problem is to write a parser that can validate the subset of URLs you want your program to be able to handle.  Learning to write a basic parser is a valuable, not to mention often very useful, skill. Quote from: ASBzone on October 29, 2019, 12:23:13 amUm... But that would not guarantee a value URL ".&.?abcd" doesn't have any invalid characters, yet is not a valid URL You got that right.  Another instance that proves Einstein was right when he saidQuoteEverything should be made as simple as possible, but no simpler ---------------------------------------------------------------------- Thaddy · 2019-10-29 06:14 Quote from: 440bx on October 29, 2019, 01:09:35 amQuote from: rgh on October 28, 2019, 08:49:57 pmIs there some class I can use to test if a string is a syntactically valid url? If there is one, I am not aware of it. TidURI from the Indy package. Synapse has URI validation too. A further in-depth analyses on why not to use a regexpr is here: https://mathiasbynens.be/demo/url-regex Noone pass all, although the one from Diego Perini comes close but is dead slow. ---------------------------------------------------------------------- 440bx · 2019-10-29 07:06 Quote from: Thaddy on October 29, 2019, 07:14:46 amTidURI from the Indy package. Synapse has URI validation too. Thank you Thaddy.  That information may come in handy someday. Quote from: Thaddy on October 29, 2019, 07:14:46 amA further in-depth analyses on why not to use a regexpr is here: https://mathiasbynens.be/demo/url-regex Noone pass all, although the one from Diego Perini comes close but is dead slow. And aside from those problems many are not what I'd consider a pleasure to read/decipher. ---------------------------------------------------------------------- zamronypj · 2019-10-29 07:08 I also use regex mentioned in https://mathiasbynens.be/demo/url-regex But they seem to fail with TRegExpr. Then I found https://blogs.lse.ac.uk/lti/2008/04/23/a-regular-expression-to-match- any-url which for me is good enough. Here is implementation of that regex for URL validation in Fano Framework https://github.com/fanoframework/fano/blob/master/src/Security/Validat ion/Validators/UrlValidatorImpl.pas ---------------------------------------------------------------------- Thaddy · 2019-10-29 07:47 No mail support there, otherwise reasonable, but not flawless Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$mode delphi}{$H+}uses classes,regexpr;var re:TRegExpr; l:Tstrings; s:string;begin  l:=tstringlist.create;  try    l.add('https://thaddy.com');    l.add('//thaddy.com'); // PRL fails    l.add('http://例子.卷筒纸'); // fails    l.add('http://xn--fsqu00a.xn--3lr804guic/'); // same as above, internationalized, passes    l.add('ftp://ftp.thaddy.com');   l.add('mailto:thaddy4@thaddy.com'); // fails    l.add('http://ip.thaddy.com');    l.add('https://192.168.178.1');    l.add('http://localhost:32000/?ch=1');    l.add('http://www.google.com<');    l.add('http://www.flickr.com/photos/27703312@N04/');    l.add('http:// i88.photobucket.com/albums/k163/thien0211photo/hinh%20chuyen%20de%20up /KienG20cau20Xeobuom20copy.jpg');    re:= TRegExpr.Create('([A-Za- z]{3,9})://([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((/[- \+~%/\.\w]+)?\??([-\+=&;%@\.\w]+)#?([\w]+)?)?');    try       for s in l do        if re.exec(s) then writeln(s);    finally      re.free;  end;  finally    l.free;  end;end. ---------------------------------------------------------------------- Ally · 2019-10-29 08:36 I created the following unit to check selected text, in my text editor, for its validity as a website URL. Protocols like ftp or mailto are not supported. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit rhsIsValidWebsiteURL; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, StrUtils; function IsValidWebsiteURL(const sURL: String): Boolean; implementation function IsValidWebsiteURL(const sURL: String): Boolean;var  i: Integer;  x: Integer;  PartList: TStringArray;  sAdress: String = '';  sProtocol: String = '';  sForbidden: String = ' :#[]@!$&()*+,;=.' + #39;const  ProtocolList: array[0..4] of String = ('https://www.', 'http://www.', 'https://', 'http://', 'www.');begin  Result := False;   // sURL darf keine Zeichen < #33 enthalten, oder mit einem reservierten Zeichen enden.  if (PosSet([#0..#32], sURL) > 0) or (Pos(RightStr(sURL, 1), sForbidden) > 0) then    Exit(False);   // sURL muss mit einem der definierten Protokolle beginnen.  for i := 0 to 4 do  begin    if Pos(ProtocolList[i], Lowercase(sURL)) = 1 then    begin      sProtocol := ProtocolList[i];      Break;    end;  end;  if sProtocol.IsEmpty then    Exit(False);   // Die Adresse darf incl. Protokoll maximal 255 Zeichen lang sein.  sAdress := sURL.Substring(sProtocol.Length, 255 - sProtocol.Length);   // Nur die Zeichen vor dem ersten Pfadtrenner gehören zur Adresse.  i := sAdress.IndexOf('/');  if i > -1 then    sAdress := LeftStr(sAdress, i);   // Auf Portnummer prüfen (http://www.domain.de:8080)  i := sAdress.LastIndexOf(':');  if i > -1 then  begin    if not TryStrToInt(RightStr(sAdress, sAdress.Length - i - 1), x) then      Exit(False);    sAdress := LeftStr(sAdress, i);  end;   // Adresse in Subdomain(s), Second-Level-Domain und Top-Level- Domain aufteilen.  PartList := sAdress.Split('.');   // Die Adresse muss aus mindestens zwei Teilen bestehen (Second-Level-Domain und Top- Level-Domain).  if High(PartList) < 1 then    Exit(False);   // Die Adressteile dürfen nicht leer sein oder reservierte Zeichen enthalten.  for i := 0 to High(PartList) do    if (PartList[i].IsEmpty) or (PosSet(sForbidden, PartList[i]) > 0) then    Exit(False);   Result := True;end; end. ---------------------------------------------------------------------- Thaddy · 2019-10-29 08:41 This is completely wrong:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  ProtocolList: array[0..4] of String = ('https://www.', 'http://www.', 'https://', 'http://', 'www.');ftp is missing, mail is missing more is missing and www is technically a subdomain. Furthermore all non-western languages would fail. That evaluation is not even remotely complete..... The focus in this discussion is to have URL validation for all protocols available. Your example lacks more than half... What it should do is here: https://en.wikipedia.org/wiki/URL or in the official RFC's  Start here  https://tools.ietf.org/html/rfc1738 What @zamronypj wrote (and I subsequently demo'd that it also fails) is way more complete. ---------------------------------------------------------------------- Ally · 2019-10-29 10:13 Hello Thaddy, as I wrote in my post: my unit checks the validity of website URLs. Similar to Firefox. If you have Firefox try this: Highlight one of the following URLs and right-click on it. If the selected text is the address of a website, you will find a menu item in the pop-up menu for opening the page. https://thaddy.com //thaddy.com http://例子.卷筒纸 http://xn--fsqu00a.xn--3lr804guic/ ftp://ftp.thaddy.com mailto:thaddy4@thaddy.com http://ip.thaddy.com https://192.168.178.1 http://localhost:32000/?ch=1 http://www.google.com< http://www.flickr.com/photos/27703312@N04/ Incidentally, the Chinese URL is also recognized by my unit. A solution that really covers all URL definitions becomes a bit more involved. The question is, why does one need such an all-encompassing solution? Are not tailor-made solutions more compact and faster? ---------------------------------------------------------------------- rgh · 2019-11-02 18:57 Thanks to all for your help on this thread. I initially asked if there was some class that could check for valid URLs,  because I thought somebody had probably written one. Maybe, given the huge diversity of schemes, many with different syntax, that's too broad a thing to ask for. All I'm immediately wanting to do is check URLs where the scheme is http or https. A couple of the suggestions above look like they would do a reasonable job at that. Quote from: Thaddy on October 29, 2019, 07:14:46 amSynapse has URI validation too. Looking through the Synapse source, all I can find is Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {:Parses a URL to its various components.}function ParseURL(URL: string; var Prot, User, Pass, Host, Port, Path,  Para: string): string;     in the synautil unit. It splits a given alleged url into it's component parts, but I don't think it checks if it's valid. Never mind. I've been given quite a few techniques to consider.