enum GopherType { Text, Directory, Error, Search, Url, Image, } class GopherPath { String _selector; GopherType _type; GopherPath(String path) { if (path.substring(0,1) != "/") throw "Path does not start with /"; switch (path.substring(1,2)) { case "0": _type = GopherType.Text; break; case "1": _type = GopherType.Directory; break; case "3": _type = GopherType.Error; break; case "7": _type = GopherType.Search; break; case "h": _type = GopherType.Url; break; case "g": case "G": case "i": case "I": case "p": // this isn't in the RFC, what's going on?? case "P": _type = GopherType.Image; break; default: throw "Unknown type {path.substring(1,2)} encountered"; } if (path.length > 2) _selector = path.substring(2); else _selector = ""; } String get selector => _selector; GopherType get type => _type; } String generateGopherTitle(Uri uri) { var path = GopherPath(uri.path); return (path.selector.length != 0 ? "${path.selector} @ " : "") + uri.host + (uri.port != 70 && uri.port != 0 ? ":${uri.port}" : ""); } Uri parseWeakInput(String s) { var uri = Uri.parse(s); if (!uri.hasScheme) { uri = Uri.parse("gopher://" + s); } if (uri.path.isEmpty) { uri = uri.replace(path: "/1"); } if (uri.port == 0) uri = uri.replace(port: 70); return uri; }