Skip to content

Commit

Permalink
Merge pull request #237 from VBA-tools/cookie-encoding
Browse files Browse the repository at this point in the history
Update Cookie Encoding
  • Loading branch information
timhall authored Jun 10, 2016
2 parents d356e07 + 288e58f commit 57735ec
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 28 deletions.
27 changes: 17 additions & 10 deletions specs/Specs_WebHelpers.bas
Original file line number Diff line number Diff line change
Expand Up @@ -311,30 +311,37 @@ Public Function Specs() As SpecSuite
.Expect(WebHelpers.UrlEncode("_", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "_"
.Expect(WebHelpers.UrlEncode("~", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "~"

' Note: "%" is allowed in spec, but is currently excluded due to parsing issues
.Expect(WebHelpers.UrlEncode("%", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%25"

.Expect(WebHelpers.UrlEncode("""", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%22"
.Expect(WebHelpers.UrlEncode(" ", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%20"

.Expect(WebHelpers.UrlEncode("!", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "!"
.Expect(WebHelpers.UrlEncode("#", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "#"
.Expect(WebHelpers.UrlEncode("$", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "$"
.Expect(WebHelpers.UrlEncode("&", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "&"
.Expect(WebHelpers.UrlEncode("'", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "'"
.Expect(WebHelpers.UrlEncode("(", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%28"
.Expect(WebHelpers.UrlEncode(")", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%29"
.Expect(WebHelpers.UrlEncode("(", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "("
.Expect(WebHelpers.UrlEncode(")", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual ")"
.Expect(WebHelpers.UrlEncode("*", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "*"
.Expect(WebHelpers.UrlEncode("+", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "+"
.Expect(WebHelpers.UrlEncode(",", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%2C"
.Expect(WebHelpers.UrlEncode("/", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%2F"
.Expect(WebHelpers.UrlEncode(":", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%3A"
.Expect(WebHelpers.UrlEncode("/", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "/"
.Expect(WebHelpers.UrlEncode(":", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual ":"
.Expect(WebHelpers.UrlEncode(";", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%3B"
.Expect(WebHelpers.UrlEncode("=", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%3D"
.Expect(WebHelpers.UrlEncode("?", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%3F"
.Expect(WebHelpers.UrlEncode("@", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%40"
.Expect(WebHelpers.UrlEncode("[", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%5B"
.Expect(WebHelpers.UrlEncode("]", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "%5D"
.Expect(WebHelpers.UrlEncode("<", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "<"
.Expect(WebHelpers.UrlEncode("=", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "="
.Expect(WebHelpers.UrlEncode(">", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual ">"
.Expect(WebHelpers.UrlEncode("?", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "?"
.Expect(WebHelpers.UrlEncode("@", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "@"
.Expect(WebHelpers.UrlEncode("[", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "["
.Expect(WebHelpers.UrlEncode("]", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "]"
.Expect(WebHelpers.UrlEncode("^", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "^"
.Expect(WebHelpers.UrlEncode("`", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "`"
.Expect(WebHelpers.UrlEncode("{", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "{"
.Expect(WebHelpers.UrlEncode("|", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "|"
.Expect(WebHelpers.UrlEncode("}", EncodingMode:=UrlEncodingMode.CookieUrlEncoding)).ToEqual "}"
End With

With Specs.It("should url-encode (PathUrlEncoding)")
Expand Down
4 changes: 2 additions & 2 deletions specs/Specs_WebRequest.bas
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,11 @@ Public Function Specs() As SpecSuite
With Specs.It("should AddCookie")
Set Request = New WebRequest

Request.AddCookie "A", "cookie"
Request.AddCookie "A[1]", "cookie"
Request.AddCookie "B", "cookie 2"

.Expect(Request.Cookies.Count).ToEqual 2
.Expect(Request.Cookies(1)("Key")).ToEqual "A"
.Expect(Request.Cookies(1)("Key")).ToEqual "A%5B1%5D"
.Expect(Request.Cookies(2)("Value")).ToEqual "cookie%202"
End With

Expand Down
38 changes: 23 additions & 15 deletions src/WebHelpers.bas
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,8 @@ End Enum
' @param FormUrlEncoding ALPHA / DIGIT / "-" / "." / "_" / "*", (space) -> "+", &...; UTF-8 encoding
' @param QueryUrlEncoding Subset of strict and form that should be suitable for non-form-urlencoded query strings
' ALPHA / DIGIT / "-" / "." / "_"
' @param CookieUrlEncoding strict / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "^" / "`" / "|"
' @param CookieUrlEncoding strict / "!" / "#" / "$" / "&" / "'" / "(" / ")" / "*" / "+" /
' "/" / ":" / "<" / "=" / ">" / "?" / "@" / "[" / "]" / "^" / "`" / "{" / "|" / "}"
' @param PathUrlEncoding strict / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" / ":" / "@"
''
Public Enum UrlEncodingMode
Expand Down Expand Up @@ -833,6 +834,7 @@ End Function
' - form-urlencoded encoding algorithm,
' https://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
' - RFC 6265 (Cookies), https://tools.ietf.org/html/rfc6265
' Note: "%" is allowed in spec, but is currently excluded due to parsing issues
'
' @method UrlEncode
' @param {Variant} Text Text to encode
Expand Down Expand Up @@ -875,7 +877,8 @@ Public Function UrlEncode(Text As Variant, _
' StrictUrlEncoding - ALPHA / DIGIT / "-" / "." / "_" / "~"
' FormUrlEncoding - ALPHA / DIGIT / "-" / "." / "_" / "*" / (space) -> "+"
' QueryUrlEncoding - ALPHA / DIGIT / "-" / "." / "_"
' CookieUrlEncoding - strict / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "^" / "`" / "|"
' CookieUrlEncoding - strict / "!" / "#" / "$" / "&" / "'" / "(" / ")" / "*" / "+" /
' "/" / ":" / "<" / "=" / ">" / "?" / "@" / "[" / "]" / "^" / "`" / "{" / "|" / "}"
' PathUrlEncoding - strict / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" / ":" / "@"

' Set space value
Expand Down Expand Up @@ -908,33 +911,26 @@ Public Function UrlEncode(Text As Variant, _
' Else -> "%20"
web_Result(web_i) = web_Space

Case 33, 36, 38, 39, 43
' "!" / "$" / "&" / "'" / "+"
Case 33, 36, 38, 39, 40, 41, 43, 58, 61, 64
' "!" / "$" / "&" / "'" / "(" / ")" / "+" / ":" / "=" / "@"
' PathUrlEncoding, CookieUrlEncoding -> Unencoded
' Else -> Percent-encoded
If EncodingMode = UrlEncodingMode.PathUrlEncoding Or EncodingMode = UrlEncodingMode.CookieUrlEncoding Then
web_Result(web_i) = web_Char
Else
web_Result(web_i) = "%" & VBA.Hex(web_CharCode)
End If
Case 35, 94, 96, 124
' "#" / "^" / "`" / "|"

Case 35, 45, 46, 47, 60, 62, 63, 91, 93, 94, 95, 96, 123, 124, 125
' "#" / "-" / "." / "/" / "<" / ">" / "?" / "[" / "]" / "^" / "_" / "`" / "{" / "|" / "}"
' CookieUrlEncoding -> Unencoded
' Else -> Percent-encoded
If EncodingMode = UrlEncodingMode.CookieUrlEncoding Then
web_Result(web_i) = web_Char
Else
web_Result(web_i) = "%" & VBA.Hex(web_CharCode)
End If
Case 40, 41, 44, 58, 59, 61, 64
' "(" / ")" / "," / ":" / ";" / "=" / "@"
' PathUrlEncoding -> Unencoded
' Else -> Percent-encoded
If EncodingMode = UrlEncodingMode.PathUrlEncoding Then
web_Result(web_i) = web_Char
Else
web_Result(web_i) = "%" & VBA.Hex(web_CharCode)
End If

Case 42
' "*"
' FormUrlEncoding, PathUrlEncoding, CookieUrlEncoding -> "*"
Expand All @@ -947,6 +943,17 @@ Public Function UrlEncode(Text As Variant, _
Else
web_Result(web_i) = "%" & VBA.Hex(web_CharCode)
End If

Case 44, 59
' "," / ";"
' PathUrlEncoding -> Unencoded
' Else -> Percent-encoded
If EncodingMode = UrlEncodingMode.PathUrlEncoding Then
web_Result(web_i) = web_Char
Else
web_Result(web_i) = "%" & VBA.Hex(web_CharCode)
End If

Case 126
' "~"
' FormUrlEncoding, QueryUrlEncoding -> "%7E"
Expand All @@ -956,6 +963,7 @@ Public Function UrlEncode(Text As Variant, _
Else
web_Result(web_i) = web_Char
End If

Case 0 To 15
web_Result(web_i) = "%0" & VBA.Hex(web_CharCode)
Case Else
Expand Down
51 changes: 50 additions & 1 deletion src/WebRequest.cls
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ End Sub
''
Public Sub AddCookie(Key As String, Value As Variant)
Me.Cookies.Add WebHelpers.CreateKeyValue( _
WebHelpers.UrlEncode(Key, EncodingMode:=UrlEncodingMode.CookieUrlEncoding), _
web_EncodeCookieName(Key), _
WebHelpers.UrlEncode(Value, EncodingMode:=UrlEncodingMode.CookieUrlEncoding) _
)
End Sub
Expand Down Expand Up @@ -810,6 +810,55 @@ End Sub
' Private Functions
' ============================================= '

' Encode cookie name
'
' References:
' - RFC 6265 https://tools.ietf.org/html/rfc6265
Private Function web_EncodeCookieName(web_CookieName As Variant) As String
Dim web_CookieVal As String
Dim web_StringLen As Long

web_CookieVal = VBA.CStr(web_CookieName)
web_StringLen = VBA.Len(web_CookieVal)

If web_StringLen > 0 Then
Dim web_Result() As String
Dim web_i As Long
Dim web_CharCode As Integer
Dim web_Char As String
ReDim web_Result(web_StringLen)

' ALPHA / DIGIT / "!" / "#" / "$" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
' Note: "%" is allowed in spec, but is currently excluded due to parsing issues

' Loop through string characters
For web_i = 1 To web_StringLen
' Get character and ascii code
web_Char = VBA.Mid$(web_CookieVal, web_i, 1)
web_CharCode = VBA.Asc(web_Char)

Select Case web_CharCode
Case 65 To 90, 97 To 122
' ALPHA
web_Result(web_i) = web_Char
Case 48 To 57
' DIGIT
web_Result(web_i) = web_Char
Case 33, 35, 36, 38, 39, 42, 43, 45, 46, 94, 95, 96, 124, 126
' "!" / "#" / "$" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
web_Result(web_i) = web_Char

Case 0 To 15
web_Result(web_i) = "%0" & VBA.Hex(web_CharCode)
Case Else
web_Result(web_i) = "%" & VBA.Hex(web_CharCode)
End Select
Next web_i

web_EncodeCookieName = VBA.Join$(web_Result, "")
End If
End Function

Private Sub Class_Initialize()
' Set default values
Me.RequestFormat = WebFormat.Json
Expand Down

0 comments on commit 57735ec

Please sign in to comment.