Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Data / System / Data / Common / DBConnectionString.cs / 1 / DBConnectionString.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// [....]
//-----------------------------------------------------------------------------
#if ORACLE
namespace System.Data.OracleClient {
#else
namespace System.Data.Common {
#endif
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
[Serializable] // MDAC 83147
internal sealed class DBConnectionString {
// instances of this class are intended to be immutable, i.e readonly
// used by permission classes so it is much easier to verify correctness
// when not worried about the class being modified during execution
private static class KEY {
internal const string Password = "password";
internal const string PersistSecurityInfo = "persist security info";
internal const string Pwd = "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;
// a linked list of key/value and their length in _encryptedUsersConnectionString
readonly private NameValuePair _keychain;
// track the existance of "password" or "pwd" in the connection string
// not used for anything anymore but must keep it set correct for V1.1 serialization
readonly private bool _hasPassword;
readonly private string[] _restrictionValues;
readonly private string _restrictions;
readonly private KeyRestrictionBehavior _behavior;
#pragma warning disable 169
// this field is no longer used, hence the warning was disabled
// however, it can not be removed or it will break serialization with V1.1
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)
{
// 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)
{
// used by DBDataPermission to convert from DbConnectionOptions to DBConnectionString
// since backward compatability requires Everett level classes
}
private DBConnectionString(DbConnectionOptions connectionOptions, string restrictions, KeyRestrictionBehavior behavior, Hashtable synonyms, bool mustCloneDictionary) { // used by DBDataPermission
Debug.Assert(null != connectionOptions, "null connectionOptions");
switch(behavior) {
case KeyRestrictionBehavior.PreventUsage:
case KeyRestrictionBehavior.AllowOnly:
_behavior = behavior;
break;
default:
throw ADP.InvalidKeyRestrictionBehavior(behavior);
}
// grab all the parsed details from DbConnectionOptions
_encryptedUsersConnectionString = connectionOptions.UsersConnectionString(false);
_hasPassword = connectionOptions.HasPasswordKeyword;
_parsetable = connectionOptions.Parsetable;
_keychain = connectionOptions.KeyChain;
// we do not want to serialize out user password unless directed so by "persist security info=true"
// otherwise all instances of user's password will be replaced with "*"
if (_hasPassword && !connectionOptions.HasPersistablePassword) {
if (mustCloneDictionary) {
// 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();
}
// different than Everett in that instead of removing password/pwd from
// the hashtable, we replace the value with '*'. This is okay since we
// serialize out with '*' so already knows what we do. Better this way
// than to treat password specially later on which causes problems.
const string star = "*";
if (_parsetable.ContainsKey(KEY.Password)) {
_parsetable[KEY.Password] = star;
}
if (_parsetable.ContainsKey(KEY.Pwd)) {
_parsetable[KEY.Pwd] = star;
}
// replace user's password/pwd value with "*" in the linked list and build a new string
_keychain = connectionOptions.ReplacePasswordPwd(out _encryptedUsersConnectionString, true);
}
if (!ADP.IsEmpty(restrictions)) {
_restrictionValues = ParseRestrictions(restrictions, synonyms);
_restrictions = restrictions;
}
}
private DBConnectionString(DBConnectionString connectionString, string[] restrictionValues, KeyRestrictionBehavior behavior) {
// used by intersect for two equal connection strings with different restrictions
_encryptedUsersConnectionString = connectionString._encryptedUsersConnectionString;
_parsetable = connectionString._parsetable;
_keychain = connectionString._keychain;
_hasPassword = connectionString._hasPassword;
_restrictionValues = restrictionValues;
_restrictions = null;
_behavior = behavior;
Verify(restrictionValues);
}
internal KeyRestrictionBehavior Behavior {
get { return _behavior; }
}
internal string ConnectionString {
get { return _encryptedUsersConnectionString; }
}
internal bool IsEmpty {
get { return (null == _keychain); }
}
internal NameValuePair KeyChain {
get { return _keychain; }
}
internal string Restrictions {
get {
string restrictions = _restrictions;
if (null == restrictions) {
string[] restrictionValues = _restrictionValues;
if ((null != restrictionValues) && (0 < restrictionValues.Length)) {
StringBuilder builder = new StringBuilder();
for(int i = 0; i < restrictionValues.Length; ++i) {
if (!ADP.IsEmpty(restrictionValues[i])) {
builder.Append(restrictionValues[i]);
builder.Append("=;");
}
#if DEBUG
else {
Debug.Assert(false, "empty restriction");
}
#endif
}
restrictions = builder.ToString();
}
}
return ((null != restrictions) ? restrictions: "");
}
}
internal string this[string keyword] {
get { return (string)_parsetable[keyword]; }
}
internal bool ContainsKey(string keyword) {
return _parsetable.ContainsKey(keyword);
}
internal DBConnectionString Intersect(DBConnectionString entry) {
KeyRestrictionBehavior behavior = _behavior;
string[] restrictionValues = null;
if (null == entry) {
//Debug.WriteLine("0 entry AllowNothing");
behavior = KeyRestrictionBehavior.AllowOnly;
}
else if (this._behavior != entry._behavior) { // subset of the AllowOnly array
behavior = KeyRestrictionBehavior.AllowOnly;
if (KeyRestrictionBehavior.AllowOnly == entry._behavior) { // this PreventUsage and entry AllowOnly
if (!ADP.IsEmptyArray(_restrictionValues)) {
if (!ADP.IsEmptyArray(entry._restrictionValues)) {
//Debug.WriteLine("1 this PreventUsage with restrictions and entry AllowOnly with restrictions");
restrictionValues = NewRestrictionAllowOnly(entry._restrictionValues, _restrictionValues);
}
else {
//Debug.WriteLine("2 this PreventUsage with restrictions and entry AllowOnly with no restrictions");
}
}
else {
//Debug.WriteLine("3/4 this PreventUsage with no restrictions and entry AllowOnly");
restrictionValues = entry._restrictionValues;
}
}
else if (!ADP.IsEmptyArray(_restrictionValues)) { // this AllowOnly and entry PreventUsage
if (!ADP.IsEmptyArray(entry._restrictionValues)) {
//Debug.WriteLine("5 this AllowOnly with restrictions and entry PreventUsage with restrictions");
restrictionValues = NewRestrictionAllowOnly(_restrictionValues, entry._restrictionValues);
}
else {
//Debug.WriteLine("6 this AllowOnly and entry PreventUsage with no restrictions");
restrictionValues = _restrictionValues;
}
}
else {
//Debug.WriteLine("7/8 this AllowOnly with no restrictions and entry PreventUsage");
}
}
else if (KeyRestrictionBehavior.PreventUsage == this._behavior) { // both PreventUsage
if (ADP.IsEmptyArray(_restrictionValues)) {
//Debug.WriteLine("9/10 both PreventUsage and this with no restrictions");
restrictionValues = entry._restrictionValues;
}
else if (ADP.IsEmptyArray(entry._restrictionValues)) {
//Debug.WriteLine("11 both PreventUsage and entry with no restrictions");
restrictionValues = _restrictionValues;
}
else {
//Debug.WriteLine("12 both PreventUsage with restrictions");
restrictionValues = NoDuplicateUnion(_restrictionValues, entry._restrictionValues);
}
}
else if (!ADP.IsEmptyArray(_restrictionValues) && !ADP.IsEmptyArray(entry._restrictionValues)) { // both AllowOnly with restrictions
if (this._restrictionValues.Length <= entry._restrictionValues.Length) {
//Debug.WriteLine("13a this AllowOnly with restrictions and entry AllowOnly with restrictions");
restrictionValues = NewRestrictionIntersect(_restrictionValues, entry._restrictionValues);
}
else {
//Debug.WriteLine("13b this AllowOnly with restrictions and entry AllowOnly with restrictions");
restrictionValues = NewRestrictionIntersect(entry._restrictionValues, _restrictionValues);
}
}
else { // both AllowOnly
//Debug.WriteLine("14/15/16 this AllowOnly and entry AllowOnly but no restrictions");
}
// verify _hasPassword & _parsetable are in [....] between Everett/Whidbey
Debug.Assert(!_hasPassword || ContainsKey(KEY.Password) || ContainsKey(KEY.Pwd), "OnDeserialized password mismatch this");
Debug.Assert(null == entry || !entry._hasPassword || entry.ContainsKey(KEY.Password) || entry.ContainsKey(KEY.Pwd), "OnDeserialized password mismatch entry");
DBConnectionString value = new DBConnectionString(this, restrictionValues, behavior);
Debug.Assert(value._hasPassword == (this._hasPassword && ((null != entry) && entry._hasPassword)), "password mismatch");
Debug.Assert(this.IsSupersetOf(value), "intersection is not a subset of original this");
Debug.Assert((null == entry) || entry.IsSupersetOf(value), "intersection is not a subset of original entry");
return value;
}
private bool IsRestrictedKeyword(string key) {
// restricted if not found
return ((null == _restrictionValues) || (0 > Array.BinarySearch(_restrictionValues, key, StringComparer.Ordinal)));
}
internal bool IsSupersetOf(DBConnectionString entry) {
Debug.Assert(!_hasPassword || ContainsKey(KEY.Password) || ContainsKey(KEY.Pwd), "OnDeserialized password mismatch this");
Debug.Assert(!entry._hasPassword || entry.ContainsKey(KEY.Password) || entry.ContainsKey(KEY.Pwd), "OnDeserialized password mismatch entry");
switch(_behavior) {
case KeyRestrictionBehavior.AllowOnly:
// every key must either be in the resticted connection string or in the allowed keywords
// keychain may contain duplicates, but it is better than GetEnumerator on _parsetable.Keys
for(NameValuePair current = entry.KeyChain; null != current; current = current.Next) {
if (!ContainsKey(current.Name) && IsRestrictedKeyword(current.Name)) {
#if DATAPERMIT
Debug.WriteLine("DBDataPermission failed AllowOnly");
#endif
return false;
}
}
break;
case KeyRestrictionBehavior.PreventUsage:
// every key can not be in the restricted keywords (even if in the restricted connection string)
if (null != _restrictionValues) {
foreach(string restriction in _restrictionValues) {
if (entry.ContainsKey(restriction)) {
#if DATAPERMIT
Debug.WriteLine("DBDataPermission failed PreventUsage");
#endif
return false;
}
}
}
break;
default:
Debug.Assert(false, "invalid KeyRestrictionBehavior");
throw ADP.InvalidKeyRestrictionBehavior(_behavior);
}
return true;
}
static private string[] NewRestrictionAllowOnly(string[] allowonly, string[] preventusage) {
List newlist = null;
for (int i = 0; i < allowonly.Length; ++i) {
if (0 > Array.BinarySearch(preventusage, allowonly[i], StringComparer.Ordinal)) {
if (null == newlist) {
newlist = new List();
}
newlist.Add(allowonly[i]);
}
}
string[] restrictionValues = null;
if (null != newlist) {
restrictionValues = newlist.ToArray();
}
Verify(restrictionValues);
return restrictionValues;
}
static private string[] NewRestrictionIntersect(string[] a, string[] b) {
List newlist = null;
for (int i = 0; i < a.Length; ++i) {
if (0 <= Array.BinarySearch(b, a[i], StringComparer.Ordinal)) {
if (null == newlist) {
newlist = new List();
}
newlist.Add(a[i]);
}
}
string[] restrictionValues = null;
if (newlist != null) {
restrictionValues = newlist.ToArray();
}
Verify(restrictionValues);
return restrictionValues;
}
static private string[] NoDuplicateUnion(string[] a, string[] b) {
#if DEBUG
Debug.Assert(null != a && 0 < a.Length, "empty a");
Debug.Assert(null != b && 0 < b.Length, "empty b");
Verify(a);
Verify(b);
#endif
List newlist = new List(a.Length + b.Length);
for(int i = 0; i < a.Length; ++i) {
newlist.Add(a[i]);
}
for(int i = 0; i < b.Length; ++i) { // find duplicates
if (0 > Array.BinarySearch(a, b[i], StringComparer.Ordinal)) {
newlist.Add(b[i]);
}
}
string[] restrictionValues = newlist.ToArray();
Array.Sort(restrictionValues, StringComparer.Ordinal);
Verify(restrictionValues);
return restrictionValues;
}
private static string[] ParseRestrictions(string restrictions, Hashtable synonyms) {
#if DEBUG
if (Bid.AdvancedOn) {
Bid.Trace(" Restrictions='%ls'\n", restrictions);
}
#endif
List restrictionValues = new List();
StringBuilder buffer = new StringBuilder(restrictions.Length);
int nextStartPosition = 0;
int endPosition = restrictions.Length;
while (nextStartPosition < endPosition) {
int startPosition = nextStartPosition;
string keyname, keyvalue; // since parsing restrictions ignores values, it doesn't matter if we use ODBC rules or OLEDB rules
nextStartPosition = DbConnectionOptions.GetKeyValuePair(restrictions, startPosition, buffer, false, out keyname, out keyvalue);
if (!ADP.IsEmpty(keyname)) {
#if DEBUG
if (Bid.AdvancedOn) {
Bid.Trace(" KeyName='%ls'\n", keyname);
}
#endif
string realkeyname = ((null != synonyms) ? (string)synonyms[keyname] : keyname); // MDAC 85144
if (ADP.IsEmpty(realkeyname)) {
throw ADP.KeywordNotSupported(keyname);
}
restrictionValues.Add(realkeyname);
}
}
return RemoveDuplicates(restrictionValues.ToArray());
}
static internal string[] RemoveDuplicates(string[] restrictions) {
int count = restrictions.Length;
if (0 < count) {
Array.Sort(restrictions, StringComparer.Ordinal);
for (int i = 1; i < restrictions.Length; ++i) {
string prev = restrictions[i-1];
if ((0 == prev.Length) || (prev == restrictions[i])) {
restrictions[i-1] = null;
count--;
}
}
if (0 == restrictions[restrictions.Length-1].Length) {
restrictions[restrictions.Length-1] = null;
count--;
}
if (count != restrictions.Length) {
string[] tmp = new String[count];
count = 0;
for (int i = 0; i < restrictions.Length; ++i) {
if (null != restrictions[i]) {
tmp[count++] = restrictions[i];
}
}
restrictions = tmp;
}
}
Verify(restrictions);
return restrictions;
}
[ConditionalAttribute("DEBUG")]
private static void Verify(string[] restrictionValues) {
if (null != restrictionValues) {
for (int i = 1; i < restrictionValues.Length; ++i) {
Debug.Assert(!ADP.IsEmpty(restrictionValues[i-1]), "empty restriction");
Debug.Assert(!ADP.IsEmpty(restrictionValues[i]), "empty restriction");
Debug.Assert(0 >= StringComparer.Ordinal.Compare(restrictionValues[i-1], restrictionValues[i]));
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// [....]
// [....]
//-----------------------------------------------------------------------------
#if ORACLE
namespace System.Data.OracleClient {
#else
namespace System.Data.Common {
#endif
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
[Serializable] // MDAC 83147
internal sealed class DBConnectionString {
// instances of this class are intended to be immutable, i.e readonly
// used by permission classes so it is much easier to verify correctness
// when not worried about the class being modified during execution
private static class KEY {
internal const string Password = "password";
internal const string PersistSecurityInfo = "persist security info";
internal const string Pwd = "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;
// a linked list of key/value and their length in _encryptedUsersConnectionString
readonly private NameValuePair _keychain;
// track the existance of "password" or "pwd" in the connection string
// not used for anything anymore but must keep it set correct for V1.1 serialization
readonly private bool _hasPassword;
readonly private string[] _restrictionValues;
readonly private string _restrictions;
readonly private KeyRestrictionBehavior _behavior;
#pragma warning disable 169
// this field is no longer used, hence the warning was disabled
// however, it can not be removed or it will break serialization with V1.1
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)
{
// 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)
{
// used by DBDataPermission to convert from DbConnectionOptions to DBConnectionString
// since backward compatability requires Everett level classes
}
private DBConnectionString(DbConnectionOptions connectionOptions, string restrictions, KeyRestrictionBehavior behavior, Hashtable synonyms, bool mustCloneDictionary) { // used by DBDataPermission
Debug.Assert(null != connectionOptions, "null connectionOptions");
switch(behavior) {
case KeyRestrictionBehavior.PreventUsage:
case KeyRestrictionBehavior.AllowOnly:
_behavior = behavior;
break;
default:
throw ADP.InvalidKeyRestrictionBehavior(behavior);
}
// grab all the parsed details from DbConnectionOptions
_encryptedUsersConnectionString = connectionOptions.UsersConnectionString(false);
_hasPassword = connectionOptions.HasPasswordKeyword;
_parsetable = connectionOptions.Parsetable;
_keychain = connectionOptions.KeyChain;
// we do not want to serialize out user password unless directed so by "persist security info=true"
// otherwise all instances of user's password will be replaced with "*"
if (_hasPassword && !connectionOptions.HasPersistablePassword) {
if (mustCloneDictionary) {
// 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();
}
// different than Everett in that instead of removing password/pwd from
// the hashtable, we replace the value with '*'. This is okay since we
// serialize out with '*' so already knows what we do. Better this way
// than to treat password specially later on which causes problems.
const string star = "*";
if (_parsetable.ContainsKey(KEY.Password)) {
_parsetable[KEY.Password] = star;
}
if (_parsetable.ContainsKey(KEY.Pwd)) {
_parsetable[KEY.Pwd] = star;
}
// replace user's password/pwd value with "*" in the linked list and build a new string
_keychain = connectionOptions.ReplacePasswordPwd(out _encryptedUsersConnectionString, true);
}
if (!ADP.IsEmpty(restrictions)) {
_restrictionValues = ParseRestrictions(restrictions, synonyms);
_restrictions = restrictions;
}
}
private DBConnectionString(DBConnectionString connectionString, string[] restrictionValues, KeyRestrictionBehavior behavior) {
// used by intersect for two equal connection strings with different restrictions
_encryptedUsersConnectionString = connectionString._encryptedUsersConnectionString;
_parsetable = connectionString._parsetable;
_keychain = connectionString._keychain;
_hasPassword = connectionString._hasPassword;
_restrictionValues = restrictionValues;
_restrictions = null;
_behavior = behavior;
Verify(restrictionValues);
}
internal KeyRestrictionBehavior Behavior {
get { return _behavior; }
}
internal string ConnectionString {
get { return _encryptedUsersConnectionString; }
}
internal bool IsEmpty {
get { return (null == _keychain); }
}
internal NameValuePair KeyChain {
get { return _keychain; }
}
internal string Restrictions {
get {
string restrictions = _restrictions;
if (null == restrictions) {
string[] restrictionValues = _restrictionValues;
if ((null != restrictionValues) && (0 < restrictionValues.Length)) {
StringBuilder builder = new StringBuilder();
for(int i = 0; i < restrictionValues.Length; ++i) {
if (!ADP.IsEmpty(restrictionValues[i])) {
builder.Append(restrictionValues[i]);
builder.Append("=;");
}
#if DEBUG
else {
Debug.Assert(false, "empty restriction");
}
#endif
}
restrictions = builder.ToString();
}
}
return ((null != restrictions) ? restrictions: "");
}
}
internal string this[string keyword] {
get { return (string)_parsetable[keyword]; }
}
internal bool ContainsKey(string keyword) {
return _parsetable.ContainsKey(keyword);
}
internal DBConnectionString Intersect(DBConnectionString entry) {
KeyRestrictionBehavior behavior = _behavior;
string[] restrictionValues = null;
if (null == entry) {
//Debug.WriteLine("0 entry AllowNothing");
behavior = KeyRestrictionBehavior.AllowOnly;
}
else if (this._behavior != entry._behavior) { // subset of the AllowOnly array
behavior = KeyRestrictionBehavior.AllowOnly;
if (KeyRestrictionBehavior.AllowOnly == entry._behavior) { // this PreventUsage and entry AllowOnly
if (!ADP.IsEmptyArray(_restrictionValues)) {
if (!ADP.IsEmptyArray(entry._restrictionValues)) {
//Debug.WriteLine("1 this PreventUsage with restrictions and entry AllowOnly with restrictions");
restrictionValues = NewRestrictionAllowOnly(entry._restrictionValues, _restrictionValues);
}
else {
//Debug.WriteLine("2 this PreventUsage with restrictions and entry AllowOnly with no restrictions");
}
}
else {
//Debug.WriteLine("3/4 this PreventUsage with no restrictions and entry AllowOnly");
restrictionValues = entry._restrictionValues;
}
}
else if (!ADP.IsEmptyArray(_restrictionValues)) { // this AllowOnly and entry PreventUsage
if (!ADP.IsEmptyArray(entry._restrictionValues)) {
//Debug.WriteLine("5 this AllowOnly with restrictions and entry PreventUsage with restrictions");
restrictionValues = NewRestrictionAllowOnly(_restrictionValues, entry._restrictionValues);
}
else {
//Debug.WriteLine("6 this AllowOnly and entry PreventUsage with no restrictions");
restrictionValues = _restrictionValues;
}
}
else {
//Debug.WriteLine("7/8 this AllowOnly with no restrictions and entry PreventUsage");
}
}
else if (KeyRestrictionBehavior.PreventUsage == this._behavior) { // both PreventUsage
if (ADP.IsEmptyArray(_restrictionValues)) {
//Debug.WriteLine("9/10 both PreventUsage and this with no restrictions");
restrictionValues = entry._restrictionValues;
}
else if (ADP.IsEmptyArray(entry._restrictionValues)) {
//Debug.WriteLine("11 both PreventUsage and entry with no restrictions");
restrictionValues = _restrictionValues;
}
else {
//Debug.WriteLine("12 both PreventUsage with restrictions");
restrictionValues = NoDuplicateUnion(_restrictionValues, entry._restrictionValues);
}
}
else if (!ADP.IsEmptyArray(_restrictionValues) && !ADP.IsEmptyArray(entry._restrictionValues)) { // both AllowOnly with restrictions
if (this._restrictionValues.Length <= entry._restrictionValues.Length) {
//Debug.WriteLine("13a this AllowOnly with restrictions and entry AllowOnly with restrictions");
restrictionValues = NewRestrictionIntersect(_restrictionValues, entry._restrictionValues);
}
else {
//Debug.WriteLine("13b this AllowOnly with restrictions and entry AllowOnly with restrictions");
restrictionValues = NewRestrictionIntersect(entry._restrictionValues, _restrictionValues);
}
}
else { // both AllowOnly
//Debug.WriteLine("14/15/16 this AllowOnly and entry AllowOnly but no restrictions");
}
// verify _hasPassword & _parsetable are in [....] between Everett/Whidbey
Debug.Assert(!_hasPassword || ContainsKey(KEY.Password) || ContainsKey(KEY.Pwd), "OnDeserialized password mismatch this");
Debug.Assert(null == entry || !entry._hasPassword || entry.ContainsKey(KEY.Password) || entry.ContainsKey(KEY.Pwd), "OnDeserialized password mismatch entry");
DBConnectionString value = new DBConnectionString(this, restrictionValues, behavior);
Debug.Assert(value._hasPassword == (this._hasPassword && ((null != entry) && entry._hasPassword)), "password mismatch");
Debug.Assert(this.IsSupersetOf(value), "intersection is not a subset of original this");
Debug.Assert((null == entry) || entry.IsSupersetOf(value), "intersection is not a subset of original entry");
return value;
}
private bool IsRestrictedKeyword(string key) {
// restricted if not found
return ((null == _restrictionValues) || (0 > Array.BinarySearch(_restrictionValues, key, StringComparer.Ordinal)));
}
internal bool IsSupersetOf(DBConnectionString entry) {
Debug.Assert(!_hasPassword || ContainsKey(KEY.Password) || ContainsKey(KEY.Pwd), "OnDeserialized password mismatch this");
Debug.Assert(!entry._hasPassword || entry.ContainsKey(KEY.Password) || entry.ContainsKey(KEY.Pwd), "OnDeserialized password mismatch entry");
switch(_behavior) {
case KeyRestrictionBehavior.AllowOnly:
// every key must either be in the resticted connection string or in the allowed keywords
// keychain may contain duplicates, but it is better than GetEnumerator on _parsetable.Keys
for(NameValuePair current = entry.KeyChain; null != current; current = current.Next) {
if (!ContainsKey(current.Name) && IsRestrictedKeyword(current.Name)) {
#if DATAPERMIT
Debug.WriteLine("DBDataPermission failed AllowOnly");
#endif
return false;
}
}
break;
case KeyRestrictionBehavior.PreventUsage:
// every key can not be in the restricted keywords (even if in the restricted connection string)
if (null != _restrictionValues) {
foreach(string restriction in _restrictionValues) {
if (entry.ContainsKey(restriction)) {
#if DATAPERMIT
Debug.WriteLine("DBDataPermission failed PreventUsage");
#endif
return false;
}
}
}
break;
default:
Debug.Assert(false, "invalid KeyRestrictionBehavior");
throw ADP.InvalidKeyRestrictionBehavior(_behavior);
}
return true;
}
static private string[] NewRestrictionAllowOnly(string[] allowonly, string[] preventusage) {
List newlist = null;
for (int i = 0; i < allowonly.Length; ++i) {
if (0 > Array.BinarySearch(preventusage, allowonly[i], StringComparer.Ordinal)) {
if (null == newlist) {
newlist = new List();
}
newlist.Add(allowonly[i]);
}
}
string[] restrictionValues = null;
if (null != newlist) {
restrictionValues = newlist.ToArray();
}
Verify(restrictionValues);
return restrictionValues;
}
static private string[] NewRestrictionIntersect(string[] a, string[] b) {
List newlist = null;
for (int i = 0; i < a.Length; ++i) {
if (0 <= Array.BinarySearch(b, a[i], StringComparer.Ordinal)) {
if (null == newlist) {
newlist = new List();
}
newlist.Add(a[i]);
}
}
string[] restrictionValues = null;
if (newlist != null) {
restrictionValues = newlist.ToArray();
}
Verify(restrictionValues);
return restrictionValues;
}
static private string[] NoDuplicateUnion(string[] a, string[] b) {
#if DEBUG
Debug.Assert(null != a && 0 < a.Length, "empty a");
Debug.Assert(null != b && 0 < b.Length, "empty b");
Verify(a);
Verify(b);
#endif
List newlist = new List(a.Length + b.Length);
for(int i = 0; i < a.Length; ++i) {
newlist.Add(a[i]);
}
for(int i = 0; i < b.Length; ++i) { // find duplicates
if (0 > Array.BinarySearch(a, b[i], StringComparer.Ordinal)) {
newlist.Add(b[i]);
}
}
string[] restrictionValues = newlist.ToArray();
Array.Sort(restrictionValues, StringComparer.Ordinal);
Verify(restrictionValues);
return restrictionValues;
}
private static string[] ParseRestrictions(string restrictions, Hashtable synonyms) {
#if DEBUG
if (Bid.AdvancedOn) {
Bid.Trace(" Restrictions='%ls'\n", restrictions);
}
#endif
List restrictionValues = new List();
StringBuilder buffer = new StringBuilder(restrictions.Length);
int nextStartPosition = 0;
int endPosition = restrictions.Length;
while (nextStartPosition < endPosition) {
int startPosition = nextStartPosition;
string keyname, keyvalue; // since parsing restrictions ignores values, it doesn't matter if we use ODBC rules or OLEDB rules
nextStartPosition = DbConnectionOptions.GetKeyValuePair(restrictions, startPosition, buffer, false, out keyname, out keyvalue);
if (!ADP.IsEmpty(keyname)) {
#if DEBUG
if (Bid.AdvancedOn) {
Bid.Trace(" KeyName='%ls'\n", keyname);
}
#endif
string realkeyname = ((null != synonyms) ? (string)synonyms[keyname] : keyname); // MDAC 85144
if (ADP.IsEmpty(realkeyname)) {
throw ADP.KeywordNotSupported(keyname);
}
restrictionValues.Add(realkeyname);
}
}
return RemoveDuplicates(restrictionValues.ToArray());
}
static internal string[] RemoveDuplicates(string[] restrictions) {
int count = restrictions.Length;
if (0 < count) {
Array.Sort(restrictions, StringComparer.Ordinal);
for (int i = 1; i < restrictions.Length; ++i) {
string prev = restrictions[i-1];
if ((0 == prev.Length) || (prev == restrictions[i])) {
restrictions[i-1] = null;
count--;
}
}
if (0 == restrictions[restrictions.Length-1].Length) {
restrictions[restrictions.Length-1] = null;
count--;
}
if (count != restrictions.Length) {
string[] tmp = new String[count];
count = 0;
for (int i = 0; i < restrictions.Length; ++i) {
if (null != restrictions[i]) {
tmp[count++] = restrictions[i];
}
}
restrictions = tmp;
}
}
Verify(restrictions);
return restrictions;
}
[ConditionalAttribute("DEBUG")]
private static void Verify(string[] restrictionValues) {
if (null != restrictionValues) {
for (int i = 1; i < restrictionValues.Length; ++i) {
Debug.Assert(!ADP.IsEmpty(restrictionValues[i-1]), "empty restriction");
Debug.Assert(!ADP.IsEmpty(restrictionValues[i]), "empty restriction");
Debug.Assert(0 >= StringComparer.Ordinal.Compare(restrictionValues[i-1], restrictionValues[i]));
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SkipStoryboardToFill.cs
- SqlGatherConsumedAliases.cs
- PrimitiveXmlSerializers.cs
- XmlChildEnumerator.cs
- AppModelKnownContentFactory.cs
- JapaneseCalendar.cs
- SmtpNegotiateAuthenticationModule.cs
- HttpConfigurationSystem.cs
- FilteredAttributeCollection.cs
- TemplatedEditableDesignerRegion.cs
- DescendantOverDescendantQuery.cs
- AutomationEvent.cs
- ObjectItemConventionAssemblyLoader.cs
- GroupItem.cs
- RegexStringValidator.cs
- RenamedEventArgs.cs
- ZoneButton.cs
- UmAlQuraCalendar.cs
- PathFigure.cs
- DefinitionBase.cs
- SystemResources.cs
- SelectedCellsCollection.cs
- BaseDataList.cs
- ApplicationException.cs
- CodeThrowExceptionStatement.cs
- CorrelationValidator.cs
- DecimalKeyFrameCollection.cs
- DispatcherHooks.cs
- Sql8ExpressionRewriter.cs
- PinnedBufferMemoryStream.cs
- RadioButton.cs
- WebEvents.cs
- Zone.cs
- XmlReaderDelegator.cs
- DbParameterCollectionHelper.cs
- CFStream.cs
- StrokeSerializer.cs
- WinCategoryAttribute.cs
- ValidationVisibilityAttribute.cs
- DrawingContext.cs
- Matrix3DConverter.cs
- RelationshipType.cs
- MemberRelationshipService.cs
- tibetanshape.cs
- ParameterCollection.cs
- EncoderReplacementFallback.cs
- UTF32Encoding.cs
- _AutoWebProxyScriptWrapper.cs
- EmptyEnumerator.cs
- cryptoapiTransform.cs
- CollectionConverter.cs
- SubMenuStyleCollection.cs
- StateItem.cs
- ResourceManager.cs
- UnsafeNativeMethods.cs
- StickyNoteHelper.cs
- PerformanceCounterScope.cs
- EventLogPermissionAttribute.cs
- documentsequencetextpointer.cs
- DetailsViewCommandEventArgs.cs
- PrintDocument.cs
- _NegotiateClient.cs
- JsonCollectionDataContract.cs
- SafeSecurityHelper.cs
- StringPropertyBuilder.cs
- DataGridSortCommandEventArgs.cs
- _LazyAsyncResult.cs
- SharedConnectionWorkflowTransactionService.cs
- LockedActivityGlyph.cs
- DynamicObjectAccessor.cs
- Signature.cs
- DecoderExceptionFallback.cs
- ObjectContextServiceProvider.cs
- LinqDataSourceContextEventArgs.cs
- NativeMethods.cs
- CodeExpressionCollection.cs
- MissingMemberException.cs
- SettingsProviderCollection.cs
- InvalidFilterCriteriaException.cs
- EntityViewGenerationConstants.cs
- QilChoice.cs
- TimeSpan.cs
- CatalogZone.cs
- Win32.cs
- TransformProviderWrapper.cs
- MergeFailedEvent.cs
- URLString.cs
- Block.cs
- ObjectSet.cs
- ResXResourceWriter.cs
- TextOutput.cs
- OAVariantLib.cs
- Deserializer.cs
- CheckBox.cs
- ConditionalExpression.cs
- FileNotFoundException.cs
- SiteMapDataSource.cs
- PointConverter.cs
- SqlDataSourceConfigureSelectPanel.cs
- WebServiceHost.cs