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.

  • Participants
  • Parent commits abde32e

Comments (0)

Files changed (3)

File KeeOtp.csproj

     <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>

File KeeOtpExt.cs

 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();

File OtpAuthData.cs

 
         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('&');