182 lines
5.4 KiB
Text
182 lines
5.4 KiB
Text
|
|
Type URL
|
||
|
|
scheme As String * 16
|
||
|
|
username As String * 64
|
||
|
|
host As String * 64
|
||
|
|
port As Uinteger
|
||
|
|
path As String * 128
|
||
|
|
query As String * 128
|
||
|
|
frag As String * 64
|
||
|
|
End Type
|
||
|
|
|
||
|
|
Function getDefaultPort(scheme As String) As Uinteger
|
||
|
|
Select Case Lcase(scheme)
|
||
|
|
Case "http" : Return 80
|
||
|
|
Case "https": Return 443
|
||
|
|
Case "ftp" : Return 21
|
||
|
|
Case "ssh" : Return 22
|
||
|
|
Case "ldap" : Return 389
|
||
|
|
Case "news" : Return 119
|
||
|
|
Case Else : Return 0
|
||
|
|
End Select
|
||
|
|
End Function
|
||
|
|
|
||
|
|
Function uri_unescape(s As String) As String
|
||
|
|
Dim As String result = ""
|
||
|
|
Dim hex_ As String * 2
|
||
|
|
Dim As Integer val_, i = 1
|
||
|
|
|
||
|
|
While i <= Len(s)
|
||
|
|
If Mid(s, i, 1) = "%" And i + 2 <= Len(s) Then
|
||
|
|
hex_ = Mid(s, i + 1, 2)
|
||
|
|
val_ = Val("&h" + hex_)
|
||
|
|
result &= Chr(val_)
|
||
|
|
i += 3
|
||
|
|
Else
|
||
|
|
result &= Mid(s, i, 1)
|
||
|
|
i += 1
|
||
|
|
End If
|
||
|
|
Wend
|
||
|
|
Return result
|
||
|
|
End Function
|
||
|
|
|
||
|
|
Sub parse_uri(u As String, Byref uri As URL)
|
||
|
|
Dim posic As Integer
|
||
|
|
Dim hasIPv6 As Boolean = False
|
||
|
|
|
||
|
|
' Reset
|
||
|
|
uri.scheme = "": uri.host = "": uri.port = 0
|
||
|
|
uri.path = "": uri.query = "": uri.frag = ""
|
||
|
|
|
||
|
|
' Special case jdbc:mysql://
|
||
|
|
If Instr(u, "jdbc:mysql://") = 1 Then
|
||
|
|
uri.scheme = "jdbc"
|
||
|
|
posic = Instr(u, "?")
|
||
|
|
If posic > 0 Then
|
||
|
|
uri.path = Mid(u, 13, posic - 13)
|
||
|
|
uri.query = Mid(u, posic + 1)
|
||
|
|
Else
|
||
|
|
uri.path = Mid(u, 13)
|
||
|
|
End If
|
||
|
|
Return
|
||
|
|
End If
|
||
|
|
|
||
|
|
' Scheme normal
|
||
|
|
posic = Instr(u, "://")
|
||
|
|
If posic > 0 Then
|
||
|
|
uri.scheme = Left(u, posic - 1)
|
||
|
|
u = Mid(u, posic + 3)
|
||
|
|
|
||
|
|
' Authority up to "/" or end
|
||
|
|
posic = Instr(u, "/")
|
||
|
|
Dim authority As String = ""
|
||
|
|
If posic > 0 Then
|
||
|
|
authority = Left(u, posic - 1)
|
||
|
|
u = Mid(u, posic)
|
||
|
|
Else
|
||
|
|
authority = u
|
||
|
|
u = ""
|
||
|
|
End If
|
||
|
|
|
||
|
|
' Parse authority: [user:pass@]host[:port]
|
||
|
|
If Len(authority) > 0 Then
|
||
|
|
' Remove user:pass@
|
||
|
|
Dim atPos As Integer = Instrrev(authority, "@")
|
||
|
|
If atPos > 0 Then
|
||
|
|
Dim userpass As String = Left(authority, atPos - 1)
|
||
|
|
authority = Mid(authority, atPos + 1)
|
||
|
|
' user:pass -> just username for simplicity
|
||
|
|
posic = Instr(userpass, ":")
|
||
|
|
If posic > 0 Then
|
||
|
|
uri.username = Left(userpass, posic - 1)
|
||
|
|
Else
|
||
|
|
uri.username = userpass
|
||
|
|
End If
|
||
|
|
End If
|
||
|
|
|
||
|
|
' IPv6 [host]
|
||
|
|
If Left(authority, 1) = "[" Then
|
||
|
|
hasIPv6 = True
|
||
|
|
posic = Instr(authority, "]")
|
||
|
|
If posic > 0 Then
|
||
|
|
uri.host = Left(authority, posic)
|
||
|
|
Dim restPort As String = Mid(authority, posic + 1)
|
||
|
|
If Left(restPort, 1) = ":" Then uri.port = Val(Mid(restPort, 2))
|
||
|
|
End If
|
||
|
|
Else
|
||
|
|
' host:port normal
|
||
|
|
posic = Instrrev(authority, ":")
|
||
|
|
If posic > 0 And posic < Len(authority) Then
|
||
|
|
uri.host = Left(authority, posic - 1)
|
||
|
|
uri.port = Val(Mid(authority, posic + 1))
|
||
|
|
Else
|
||
|
|
uri.host = authority
|
||
|
|
End If
|
||
|
|
End If
|
||
|
|
End If
|
||
|
|
Else
|
||
|
|
' WITHOUT "/" -> scheme:path
|
||
|
|
posic = Instr(u, ":")
|
||
|
|
If posic > 0 Then
|
||
|
|
uri.scheme = Left(u, posic - 1)
|
||
|
|
u = Mid(u, posic + 1)
|
||
|
|
End If
|
||
|
|
End If
|
||
|
|
|
||
|
|
'ParsePath:
|
||
|
|
If uri.port = 0 Then uri.port = getDefaultPort(uri.scheme)
|
||
|
|
|
||
|
|
' Path/query/frag
|
||
|
|
posic = Instr(u, "?")
|
||
|
|
If posic > 0 Then
|
||
|
|
uri.path = Left(u, posic - 1)
|
||
|
|
Dim qfrag As String = Mid(u, posic + 1)
|
||
|
|
posic = Instr(qfrag, "#")
|
||
|
|
If posic > 0 Then
|
||
|
|
uri.query = Left(qfrag, posic - 1)
|
||
|
|
uri.frag = Mid(qfrag, posic + 1)
|
||
|
|
Else
|
||
|
|
uri.query = qfrag
|
||
|
|
End If
|
||
|
|
Else
|
||
|
|
posic = Instr(u, "#")
|
||
|
|
If posic > 0 Then
|
||
|
|
uri.path = Left(u, posic - 1)
|
||
|
|
uri.frag = Mid(u, posic + 1)
|
||
|
|
Else
|
||
|
|
uri.path = u
|
||
|
|
End If
|
||
|
|
End If
|
||
|
|
End Sub
|
||
|
|
|
||
|
|
' Test data
|
||
|
|
Dim As String uris(13)
|
||
|
|
uris(0) = "foo://example.com:8042/over/there?name=ferret#nose"
|
||
|
|
uris(1) = "urn:example:animal:ferret:nose"
|
||
|
|
uris(2) = "jdbc:mysql://test_user:ouupppssss@localhost:3306/sakila?profileSQL=true"
|
||
|
|
uris(3) = "ftp://ftp.is.co.za/rfc/rfc1808.txt"
|
||
|
|
uris(4) = "http://www.ietf.org/rfc/rfc2396.txt#header1"
|
||
|
|
uris(5) = "ldap://[2001:db8::7]/c=GB?objectClass?one"
|
||
|
|
uris(6) = "mailto:John.Doe@example.com"
|
||
|
|
uris(7) = "news:comp.infosystems.www.servers.unix"
|
||
|
|
uris(8) = "tel:+1-816-555-1212"
|
||
|
|
uris(9) = "telnet://192.0.2.16:80/"
|
||
|
|
uris(10) = "urn:oasis:names:specification:docbook:dtd:xml:4.1.2"
|
||
|
|
uris(11) = "ssh://alice@example.com"
|
||
|
|
uris(12) = "https://bob:pass@example.com/place"
|
||
|
|
uris(13) = "http://example.com/?a=1&b=2+2&c=3&c=4&d=%65%6e%63%6f%64%65%64"
|
||
|
|
|
||
|
|
Dim u As URL
|
||
|
|
For i As Integer = 0 To Ubound(uris)
|
||
|
|
Print "URL: " & uris(i)
|
||
|
|
parse_uri(uris(i), u)
|
||
|
|
Print " scheme: " & Trim(u.scheme)
|
||
|
|
If Trim(u.host) <> "" Then Print " host: " & uri_unescape(Trim(u.host))
|
||
|
|
If u.port > 0 Then Print " port: " & u.port
|
||
|
|
Print " path: " & uri_unescape(Trim(u.path))
|
||
|
|
If Trim(u.query) <> "" Then Print " query: " & uri_unescape(Trim(u.query))
|
||
|
|
If Trim(u.frag) <> "" Then Print "fragment: " & uri_unescape(Trim(u.frag))
|
||
|
|
Print
|
||
|
|
Next
|
||
|
|
|
||
|
|
Sleep
|