77
88using System . Net ;
99using System . Net . NetworkInformation ;
10-
10+ using System . Collections . Specialized ;
1111using UnityEngine ;
1212
1313using Newtonsoft . Json . Linq ;
@@ -82,6 +82,64 @@ static HttpListener BindLocalHostFirstAvailablePort()
8282 } ) . FirstOrDefault ( ( listener ) => listener != null ) ;
8383 }
8484
85+ public static NameValueCollection ParseQueryString ( string query )
86+ {
87+ var nvc = new NameValueCollection ( ) ;
88+
89+ if ( string . IsNullOrEmpty ( query ) )
90+ {
91+ return nvc ;
92+ }
93+
94+ // Remove leading '?' if it's a full URL query string
95+ if ( query . StartsWith ( "?" ) )
96+ {
97+ query = query . Substring ( 1 ) ;
98+ }
99+
100+ // Split by '&' to get individual key-value pairs
101+ string [ ] pairs = query . Split ( '&' ) ;
102+
103+ foreach ( string pair in pairs )
104+ {
105+ if ( string . IsNullOrEmpty ( pair ) )
106+ {
107+ continue ; // Skip empty pairs (e.g., "a=1&&b=2")
108+ }
109+
110+ // Find the first '='
111+ int indexOfEquals = pair . IndexOf ( '=' ) ;
112+
113+ string key ;
114+ string value ;
115+
116+ if ( indexOfEquals == - 1 )
117+ {
118+ // No '=' found, treat the whole segment as a key with an empty value
119+ // Example: "param_without_value" -> param_without_value=""
120+ key = pair ;
121+ value = string . Empty ;
122+ }
123+ else
124+ {
125+ // Split key and value based on the first '='
126+ key = pair . Substring ( 0 , indexOfEquals ) ;
127+ value = pair . Substring ( indexOfEquals + 1 ) ;
128+ }
129+
130+ // URL-decode both key and value
131+ // WebUtility.UrlDecode handles %xx decoding and converting '+' to space.
132+ key = WebUtility . UrlDecode ( key ) ;
133+ value = WebUtility . UrlDecode ( value ) ;
134+
135+ // Add to the NameValueCollection.
136+ // NameValueCollection automatically handles multiple values for the same key.
137+ nvc . Add ( key , value ) ;
138+ }
139+
140+ return nvc ;
141+ }
142+
85143 void SigningIn ( )
86144 {
87145 Pending = true ;
@@ -105,7 +163,7 @@ void SigningIn()
105163 Debug . Log ( task ) ;
106164 var context = task . Result ;
107165 var queryString = context . Request . Url . Query ;
108- var queryDictionary = System . Web . HttpUtility . ParseQueryString ( queryString ) ;
166+ var queryDictionary = ParseQueryString ( queryString ) ;
109167 if ( queryDictionary == null || queryDictionary . Get ( "code" ) is not string code || string . IsNullOrEmpty ( code ) )
110168 {
111169 Status = GoogleSignInStatusCode . INVALID_ACCOUNT ;
@@ -208,4 +266,4 @@ public static async Task<string> GetResponseAsStringAsync(this HttpWebRequest re
208266 public static void Write ( this Stream stream , byte [ ] data ) => stream . Write ( data , 0 , data . Length ) ;
209267 }
210268}
211- #endif
269+ #endif
0 commit comments