Skip to content

Commit

Permalink
First
Browse files Browse the repository at this point in the history
  • Loading branch information
DavoudEshtehari committed Sep 22, 2021
1 parent aea4bbe commit 4bc6b4c
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 1,236 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
<Compile Include="..\..\src\Microsoft\Data\Common\NameValuePair.cs">
<Link>Microsoft\Data\Common\NameValuePair.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\Common\DbConnectionOptions.Common.cs">
<Link>Microsoft\Data\Common\DbConnectionOptions.Common.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\DataClassification\SensitivityClassification.cs">
<Link>Microsoft\Data\SqlClient\DataClassification\SensitivityClassification.cs</Link>
</Compile>
Expand Down Expand Up @@ -431,9 +434,6 @@
</Compile>
<Compile Include="Microsoft\Data\Common\AdapterUtil.SqlClient.cs" />
<Compile Include="Microsoft\Data\Common\DbConnectionOptions.cs" />
<Compile Include="$(CommonPath)\Microsoft\Data\Common\DbConnectionOptions.Common.cs">
<Link>Microsoft\Data\Common\DbConnectionOptions.Common.cs</Link>
</Compile>
<Compile Include="Microsoft\Data\Common\DbConnectionStringCommon.cs" />
<Compile Include="$(CommonPath)\Microsoft\Data\ProviderBase\DbConnectionInternal.cs">
<Link>Common\Microsoft\Data\ProviderBase\DbConnectionInternal.cs</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,113 +3,31 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;

namespace Microsoft.Data.Common
{
internal partial class DbConnectionOptions
{
// instances of this class are intended to be immutable, i.e readonly
// used by pooling classes so it is much easier to verify correctness
// when not worried about the class being modified during execution

public DbConnectionOptions(string connectionString, Dictionary<string, string> synonyms)
{
_parsetable = new Dictionary<string, string>();
_usersConnectionString = ((null != connectionString) ? connectionString : "");

// first pass on parsing, initial syntax check
if (0 < _usersConnectionString.Length)
{
_keyChain = ParseInternal(_parsetable, _usersConnectionString, true, synonyms, false);
HasPasswordKeyword = (_parsetable.ContainsKey(KEY.Password) || _parsetable.ContainsKey(SYNONYM.Pwd));
HasUserIdKeyword = (_parsetable.ContainsKey(KEY.User_ID) || _parsetable.ContainsKey(SYNONYM.UID));
}
}

protected DbConnectionOptions(DbConnectionOptions connectionOptions)
{ // Clone used by SqlConnectionString
_usersConnectionString = connectionOptions._usersConnectionString;
_parsetable = connectionOptions._parsetable;
_keyChain = connectionOptions._keyChain;
HasPasswordKeyword = connectionOptions.HasPasswordKeyword;
HasUserIdKeyword = connectionOptions.HasUserIdKeyword;
}

public bool IsEmpty => _keyChain == null;

internal bool TryGetParsetableValue(string key, out string value) => _parsetable.TryGetValue(key, out value);

// same as Boolean, but with SSPI thrown in as valid yes
public bool ConvertValueToIntegratedSecurity()
internal string ExpandAttachDbFileName(string replacementValue)
{
string value;
return _parsetable.TryGetValue(KEY.Integrated_Security, out value) && value != null ?
ConvertValueToIntegratedSecurityInternal(value) :
false;
}
int copyPosition = 0;

internal bool ConvertValueToIntegratedSecurityInternal(string stringValue)
{
if (CompareInsensitiveInvariant(stringValue, "sspi") || CompareInsensitiveInvariant(stringValue, "true") || CompareInsensitiveInvariant(stringValue, "yes"))
return true;
else if (CompareInsensitiveInvariant(stringValue, "false") || CompareInsensitiveInvariant(stringValue, "no"))
return false;
else
System.Text.StringBuilder builder = new(_usersConnectionString.Length);
for (NameValuePair current = KeyChain; null != current; current = current.Next)
{
string tmp = stringValue.Trim(); // Remove leading & trailing whitespace.
if (CompareInsensitiveInvariant(tmp, "sspi") || CompareInsensitiveInvariant(tmp, "true") || CompareInsensitiveInvariant(tmp, "yes"))
return true;
else if (CompareInsensitiveInvariant(tmp, "false") || CompareInsensitiveInvariant(tmp, "no"))
return false;
if (string.Equals(current.Name, DbConnectionStringKeywords.AttachDBFilename, StringComparison.InvariantCultureIgnoreCase))
{
builder.Append($"{current.Name}={replacementValue};");
}
else
{
throw ADP.InvalidConnectionOptionValue(KEY.Integrated_Security);
builder.Append(_usersConnectionString, copyPosition, current.Length);
}
copyPosition += current.Length;
}
}

public int ConvertValueToInt32(string keyName, int defaultValue)
{
string value;
return _parsetable.TryGetValue(keyName, out value) && value != null ?
ConvertToInt32Internal(keyName, value) :
defaultValue;
}

internal static int ConvertToInt32Internal(string keyname, string stringValue)
{
try
{
return int.Parse(stringValue, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (FormatException e)
{
throw ADP.InvalidConnectionOptionValue(keyname, e);
}
catch (OverflowException e)
{
throw ADP.InvalidConnectionOptionValue(keyname, e);
}
}

public string ConvertValueToString(string keyName, string defaultValue)
{
string value;
return _parsetable.TryGetValue(keyName, out value) && value != null ? value : defaultValue;
}

public bool ContainsKey(string keyword)
{
return _parsetable.ContainsKey(keyword);
}

protected internal virtual string Expand()
{
return _usersConnectionString;
return builder.ToString();
}

// SxS notes:
Expand Down Expand Up @@ -151,25 +69,5 @@ internal static string ExpandDataDirectory(string keyword, string value)
return fullPath;
}

internal string ExpandAttachDbFileName(string replacementValue)
{
int copyPosition = 0;

StringBuilder builder = new StringBuilder(_usersConnectionString.Length);
for (NameValuePair current = _keyChain; null != current; current = current.Next)
{
if (current.Name == KEY.AttachDBFileName)
{
builder.Append($"{KEY.AttachDBFileName}={replacementValue};");
}
else
{
builder.Append(_usersConnectionString, copyPosition, current.Length);
}
copyPosition += current.Length;
}

return builder.ToString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
<Compile Include="..\..\src\Microsoft\Data\Common\NameValuePair.cs">
<Link>Microsoft\Data\Common\NameValuePair.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\Common\DbConnectionOptions.Common.cs">
<Link>Microsoft\Data\Common\DbConnectionOptions.Common.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\Sql\SqlNotificationRequest.cs">
<Link>Microsoft\Data\Sql\SqlNotificationRequest.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ internal sealed class DBConnectionString

private static class KEY
{
internal const string Password = "password";
internal const string PersistSecurityInfo = "persist security info";
internal const string Pwd = "pwd";
internal const string Password = DbConnectionStringKeywords.Password;
internal const string PersistSecurityInfo = DbConnectionStringKeywords.PersistSecurityInfo;
internal const string Pwd = DbConnectionStringSynonyms.Pwd;
};

// this class is serializable with Everett, so ugly field names can't be changed
readonly private string _encryptedUsersConnectionString;

// hash of unique keys to values
readonly private Hashtable _parsetable;
readonly private Dictionary<string, string> _parsetable;

// a linked list of key/value and their length in _encryptedUsersConnectionString
readonly private NameValuePair _keychain;
Expand All @@ -52,21 +52,21 @@ private static class KEY
readonly private string _encryptedActualConnectionString;
#pragma warning restore 169

internal DBConnectionString(string value, string restrictions, KeyRestrictionBehavior behavior, Hashtable synonyms, bool useOdbcRules)
: this(new DbConnectionOptions(value, synonyms, useOdbcRules), restrictions, behavior, synonyms, false)
internal DBConnectionString(string value, string restrictions, KeyRestrictionBehavior behavior, Dictionary<string, string> synonyms, bool useOdbcRules)
: this(new DbConnectionOptions(value, synonyms), restrictions, behavior, synonyms, false)
{
// useOdbcRules is only used to parse the connection string, not to parse restrictions because values don't apply there
// the hashtable doesn't need clone since it isn't shared with anything else
}

internal DBConnectionString(DbConnectionOptions connectionOptions)
: this(connectionOptions, (string)null, KeyRestrictionBehavior.AllowOnly, (Hashtable)null, true)
: this(connectionOptions, (string)null, KeyRestrictionBehavior.AllowOnly, null, true)
{
// used by DBDataPermission to convert from DbConnectionOptions to DBConnectionString
// since backward compatibility requires Everett level classes
}

private DBConnectionString(DbConnectionOptions connectionOptions, string restrictions, KeyRestrictionBehavior behavior, Hashtable synonyms, bool mustCloneDictionary)
private DBConnectionString(DbConnectionOptions connectionOptions, string restrictions, KeyRestrictionBehavior behavior, Dictionary<string, string> synonyms, bool mustCloneDictionary)
{ // used by DBDataPermission
Debug.Assert(null != connectionOptions, "null connectionOptions");
switch (behavior)
Expand Down Expand Up @@ -94,7 +94,7 @@ private DBConnectionString(DbConnectionOptions connectionOptions, string restric
{
// clone the hashtable to replace user's password/pwd value with "*"
// we only need to clone if coming from DbConnectionOptions and password exists
_parsetable = (Hashtable)_parsetable.Clone();
_parsetable = new Dictionary<string, string>(_parsetable, _parsetable.Comparer);
}

// different than Everett in that instead of removing password/pwd from
Expand Down Expand Up @@ -467,7 +467,7 @@ static private string[] NoDuplicateUnion(string[] a, string[] b)
return restrictionValues;
}

private static string[] ParseRestrictions(string restrictions, Hashtable synonyms)
private static string[] ParseRestrictions(string restrictions, Dictionary<string, string> synonyms)
{
#if DEBUG
SqlClientEventSource.Log.TryAdvancedTraceEvent("<comm.DBConnectionString|INFO|ADV> Restrictions='{0}'", restrictions);
Expand Down
Loading

0 comments on commit 4bc6b4c

Please sign in to comment.