Esempio n. 1
0
        /// <summary>
        /// Adds instances of %XX in the input string where the char to be escaped appears
        /// XX is the hex value of the ASCII code for the char.  Caches if requested.
        /// </summary>
        /// <param name="unescapedString">The string to escape.</param>
        /// <param name="cache">
        /// True if the cache should be checked, and if the resultant string
        /// should be cached.
        /// </param>
        private static string EscapeWithOptionalCaching(string unescapedString, bool cache)
        {
            // If there are no special chars, just return the original string immediately.
            // Don't even instantiate the StringBuilder.
            if (String.IsNullOrEmpty(unescapedString) || !ContainsReservedCharacters(unescapedString))
            {
                return(unescapedString);
            }

            // next, if we're caching, check to see if it's already there.
            if (cache)
            {
                string cachedEscapedString = null;
                lock (s_unescapedToEscapedStrings)
                {
                    if (s_unescapedToEscapedStrings.TryGetValue(unescapedString, out cachedEscapedString))
                    {
                        return(cachedEscapedString);
                    }
                }
            }

            // This is where we're going to build up the final string to return to the caller.
            StringBuilder escapedStringBuilder = StringBuilderCache.Acquire(unescapedString.Length * 2);

            AppendEscapedString(escapedStringBuilder, unescapedString);

            if (!cache)
            {
                return(StringBuilderCache.GetStringAndRelease(escapedStringBuilder));
            }

            string escapedString = OpportunisticIntern.StringBuilderToString(escapedStringBuilder);

            StringBuilderCache.Release(escapedStringBuilder);

            lock (s_unescapedToEscapedStrings)
            {
                s_unescapedToEscapedStrings[unescapedString] = escapedString;
            }

            return(escapedString);
        }
Esempio n. 2
0
        /// <summary>
        /// Given a string of semi-colon delimited name=value pairs, this method parses it and creates
        /// a hash table containing the property names as keys and the property values as values.
        /// This method escapes any special characters found in the property values, in case they
        /// are going to be passed to a method (such as that expects the appropriate escaping to have happened
        /// already.
        /// </summary>
        /// <returns>true on success, false on failure.</returns>
        internal static bool GetTableWithEscaping(TaskLoggingHelper log, string parameterName, string syntaxName, string[] propertyNameValueStrings, out Dictionary <string, string> finalPropertiesTable)
        {
            finalPropertiesTable = null;

            if (propertyNameValueStrings != null)
            {
                finalPropertiesTable = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                var finalPropertiesList = new List <PropertyNameValuePair>();

                // Loop through the array.  Each string in the array should be of the form:
                //          MyPropName=MyPropValue
                foreach (string propertyNameValueString in propertyNameValueStrings)
                {
                    // Find the first '=' sign in the string.
                    int indexOfEqualsSign = propertyNameValueString.IndexOf('=');

                    if (indexOfEqualsSign != -1)
                    {
                        // If we found one, then grab the stuff before it and put it into "propertyName",
                        // and grab the stuff after it and put it into "propertyValue".  But trim the
                        // whitespace from beginning and end of both name and value.  (When authoring a
                        // project/targets file, people like to use whitespace and newlines to pretty up
                        // the file format.)
                        string propertyName  = propertyNameValueString.Substring(0, indexOfEqualsSign).Trim();
                        string propertyValue = EscapingUtilities.Escape(propertyNameValueString.Substring(indexOfEqualsSign + 1).Trim());

                        // Make sure we have a property name and property value (though the value is allowed to be blank).
                        if (propertyName.Length == 0)
                        {
                            // No property name?  That's no good to us.
                            log?.LogErrorWithCodeFromResources("General.InvalidPropertyError", syntaxName, propertyNameValueString);

                            return(false);
                        }

                        // Store the property in our list.
                        finalPropertiesList.Add(new PropertyNameValuePair(propertyName, propertyValue));
                    }
                    else
                    {
                        // There's no '=' sign in the string.  When this happens, we treat this string as basically
                        // an appendage on the value of the previous property.  For example, if the project file contains
                        //
                        //      <PropertyGroup>
                        //          <WarningsAsErrors>1234;5678;9999</WarningsAsErrors>
                        //      </PropertyGroup>
                        //      <Target Name="Build">
                        //          <MSBuild Projects="ConsoleApplication1.csproj"
                        //                   Properties="WarningsAsErrors=$(WarningsAsErrors)"/>
                        //      </Target>
                        //
                        // , then this method (GetTableWithEscaping) will see this:
                        //
                        //      propertyNameValueStrings[0] = "WarningsAsErrors=1234"
                        //      propertyNameValueStrings[1] = "5678"
                        //      propertyNameValueStrings[2] = "9999"
                        //
                        // And what we actually want to end up with in our final hashtable is this:
                        //
                        //      NAME                    VALUE
                        //      ===================     ================================
                        //      WarningsAsErrors        1234;5678;9999
                        //
                        if (finalPropertiesList.Count > 0)
                        {
                            // There was a property definition previous to this one.  Append the current string
                            // to that previous value, using semicolon as a separator.
                            string propertyValue = EscapingUtilities.Escape(propertyNameValueString.Trim());
                            finalPropertiesList[finalPropertiesList.Count - 1].Value.Append(';');
                            finalPropertiesList[finalPropertiesList.Count - 1].Value.Append(propertyValue);
                        }
                        else
                        {
                            // No equals sign in the very first property?  That's a problem.
                            log?.LogErrorWithCodeFromResources("General.InvalidPropertyError", syntaxName, propertyNameValueString);

                            return(false);
                        }
                    }
                }

                // Convert the data in the List to a Hashtable, because that's what the MSBuild task eventually
                // needs to pass onto the engine.
                log?.LogMessageFromText(parameterName, MessageImportance.Low);

                foreach (PropertyNameValuePair propertyNameValuePair in finalPropertiesList)
                {
                    string propertyValue = OpportunisticIntern.StringBuilderToString(propertyNameValuePair.Value);
                    finalPropertiesTable[propertyNameValuePair.Name] = propertyValue;
                    log?.LogMessageFromText(
                        $"  {propertyNameValuePair.Name}={propertyValue}",
                        MessageImportance.Low);
                }
            }

            return(true);
        }