Commits

Devin Martin committed 14ee058

Removed all dependencies on System.Web. This means that the standard UrlEncode
and QueryString parsing that are baked into .net had to be partially re-implemented.
This won't hold up with anything complicated but should be able to encode and
decode the values required to store the TOTP information in the KeePass DB.

Comments (0)

Files changed (3)

     <Reference Include="System" />
     <Reference Include="System.Data" />
     <Reference Include="System.Drawing" />
-    <Reference Include="System.Web" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Xml" />
   </ItemGroup>
 using System;
-using System.Diagnostics;
 using System.Windows.Forms;
 using KeePass.Plugins;
 using KeePass.Util;
 
         public override bool Initialize(IPluginHost host)
         {
-            Debug.Assert(host != null);
-            if (host == null) return false;
+            if (host == null)
+                return false;
             this.host = host;
 
             this.otpSeperatorToolStripItem = new ToolStripSeparator();
 
         public static OtpAuthData FromString(string data)
         {
-            var parameters = HttpUtility.ParseQueryString(data);
+            NameValueCollection parameters = ParseQueryString(data);
 
             if (parameters[keyParameter] == null)
                 throw new ArgumentException("Must have a key in the data");
             return otpData;
         }
 
+        /// <remarks>
+        /// Hacky query string parsing.  This was done due to reports
+        /// of people with just a 3.5 or 4.0 client profile getting errors
+        /// as the System.Web assembly where .net's implementation of
+        /// Url encoding and query string parsing is locate.
+        /// 
+        /// This should be fine since the only thing stored in the string
+        /// that needs to be encoded or decoded is the '=' sign.
+        /// </remarks>
+        private static NameValueCollection ParseQueryString(string data)
+        {
+            var collection = new NameValueCollection();
+
+            var parameters = data.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
+            foreach (var parameter in parameters)
+            {
+                if (parameter.Contains("="))
+                {
+                    var pieces = parameter.Split('=');
+                    if (pieces.Length != 2)
+                        continue;
+
+                    collection.Add(pieces[0], pieces[1].Replace("%3d", "="));
+                }
+            }
+
+            return collection;
+        }
+
         private static int GetIntOrDefault(NameValueCollection parameters, string parameterKey, int defaultValue)
         {
             if (parameters[parameterKey] != null)
             get
             {
                 NameValueCollection collection = new NameValueCollection();
-                collection.Add(keyParameter, Base32.Encode(this.Key));
+                collection.Add(keyParameter, Base32.Encode(this.Key).Replace("=", "%3d"));
 
                 if (this.Type != KeeOtp.OtpType.Totp)
                     collection.Add(typeParameter, this.Type.ToString());
                 string data = string.Empty;
                 foreach (var key in collection.AllKeys)
                 {
-                    data += string.Format("{0}={1}&", key, HttpUtility.UrlEncode(collection[key]));
+                    data += string.Format("{0}={1}&", key, collection[key]);
                 }
 
                 return data.TrimEnd('&');