//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- namespace System.Data.EntityClient { using System.Collections; using System.Diagnostics; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; /// /// Copied from System.Data.dll /// internal 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 #if DEBUG private const string ConnectionStringPattern = // may not contain embedded null except trailing last value "([\\s;]*" // leading whitespace and extra semicolons + "(?![\\s;])" // key does not start with space or semicolon + "(?([^=\\s\\p{Cc}]|\\s+[^=\\s\\p{Cc}]|\\s+==|==)+)" // allow any visible character for keyname except '=' which must quoted as '==' + "\\s*=(?!=)\\s*" // the equal sign divides the key and value parts + "(?" + "(\"([^\"\u0000]|\"\")*\")" // double quoted string, " must be quoted as "" + "|" + "('([^'\u0000]|'')*')" // single quoted string, ' must be quoted as '' + "|" + "((?![\"'\\s])" // unquoted value must not start with " or ' or space, would also like = but too late to change + "([^;\\s\\p{Cc}]|\\s+[^;\\s\\p{Cc}])*" // control characters must be quoted + "(?([^=\\s\\p{Cc}]|\\s+[^=\\s\\p{Cc}]|\\s+==|==)+) if ('=' == currentChar) { parserState = ParserState.KeyEqual; continue; } if (Char.IsWhiteSpace(currentChar)) { break; } if (Char.IsControl(currentChar)) { throw EntityUtil.ConnectionStringSyntax(startposition); } break; case ParserState.KeyEqual: // \\s*=(?!=)\\s* if ('=' == currentChar) { parserState = ParserState.Key; break; } keyname = GetKeyName(buffer); if (string.IsNullOrEmpty(keyname)) { throw EntityUtil.ConnectionStringSyntax(startposition); } buffer.Length = 0; parserState = ParserState.KeyEnd; goto case ParserState.KeyEnd; case ParserState.KeyEnd: if (Char.IsWhiteSpace(currentChar)) { continue; } if ('\'' == currentChar) { parserState = ParserState.SingleQuoteValue; continue; } if ('"' == currentChar) { parserState = ParserState.DoubleQuoteValue; continue; } if (';' == currentChar) { goto ParserExit; } if ('\0' == currentChar) { goto ParserExit; } if (Char.IsControl(currentChar)) { throw EntityUtil.ConnectionStringSyntax(startposition); } parserState = ParserState.UnquotedValue; break; case ParserState.UnquotedValue: // "((?![\"'\\s])" + "([^;\\s\\p{Cc}]|\\s+[^;\\s\\p{Cc}])*" + "(?"); Debug.Assert(value1 == value2, "ParseInternal code vs. regex mismatch keyvalue <" + value1 + "> <" + value2 + ">"); } } catch (ArgumentException f) { if (null != e) { string msg1 = e.Message; string msg2 = f.Message; if (msg1.StartsWith("Keyword not supported:", StringComparison.Ordinal) && msg2.StartsWith("Format of the initialization string", StringComparison.Ordinal)) { } else { // Does not always hold. Debug.Assert(msg1 == msg2, "ParseInternal code vs regex message mismatch: <" + msg1 + "> <" + msg2 + ">"); } } else { Debug.Assert(false, "ParseInternal code vs regex throw mismatch " + f.Message); } e = null; } if (null != e) { Debug.Assert(false, "ParseInternal code threw exception vs regex mismatch"); } } #endif private static NameValuePair ParseInternal(Hashtable parsetable, string connectionString, Hashtable synonyms) { Debug.Assert(null != connectionString, "null connectionstring"); StringBuilder buffer = new StringBuilder(); NameValuePair localKeychain = null, keychain = null; #if DEBUG try { #endif int nextStartPosition = 0; int endPosition = connectionString.Length; while (nextStartPosition < endPosition) { int startPosition = nextStartPosition; string keyname, keyvalue; nextStartPosition = GetKeyValuePair(connectionString, startPosition, buffer, out keyname, out keyvalue); if (string.IsNullOrEmpty(keyname)) { // if (nextStartPosition != endPosition) { throw; } break; } #if DEBUG Debug.Assert(IsKeyNameValid(keyname), "ParseFailure, invalid keyname"); Debug.Assert(IsValueValidInternal(keyvalue), "parse failure, invalid keyvalue"); #endif string realkeyname = ((null != synonyms) ? (string)synonyms[keyname] : keyname); if (!IsKeyNameValid(realkeyname)) { throw EntityUtil.ADP_KeywordNotSupported(keyname); } parsetable[realkeyname] = keyvalue; // last key-value pair wins (or first) if (null != localKeychain) { localKeychain = localKeychain.Next = new NameValuePair(realkeyname, keyvalue, nextStartPosition - startPosition); } else { // first time only - don't contain modified chain from UDL file keychain = localKeychain = new NameValuePair(realkeyname, keyvalue, nextStartPosition - startPosition); } } #if DEBUG } catch (ArgumentException e) { ParseComparision(parsetable, connectionString, synonyms, e); throw; } ParseComparision(parsetable, connectionString, synonyms, null); #endif return keychain; } } }