Esempio n. 1
0
        /// <summary>
        /// Gets a long filename value and displays an error for an illegal long filename value.
        /// </summary>
        /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
        /// <param name="attribute">The attribute containing the value to get.</param>
        /// <returns>The attribute's long filename value.</returns>
        public string GetAttributeLongFilename(SourceLineNumberCollection sourceLineNumbers, XmlAttribute attribute)
        {
            string value = this.GetAttributeValue(sourceLineNumbers, attribute);

            if (IllegalEmptyAttributeValue != value)
            {
                if (!CompilerCore.LegalLongFilename.IsMatch(value) && !CompilerCore.IsValidLocIdentifier(value))
                {
                    this.OnMessage(WixErrors.IllegalLongFilename(sourceLineNumbers, attribute.OwnerElement.Name, attribute.Name, value));
                }
                else if (CompilerCore.IsAmbiguousFilename(value))
                {
                    this.OnMessage(WixWarnings.AmbiguousFileOrDirectoryName(sourceLineNumbers, attribute.OwnerElement.Name, attribute.Name, value));
                }
            }

            return(value);
        }
Esempio n. 2
0
        /// <summary>
        /// Gets the modularized version of the field data.
        /// </summary>
        /// <param name="field">The field to modularize.</param>
        /// <param name="modularizationGuid">String containing the GUID of the Merge Module to append the the field value, if appropriate.</param>
        /// <param name="suppressModularizationIdentifiers">Optional collection of identifiers that should not be modularized.</param>
        /// <remarks>moduleGuid is expected to be null when not being used to compile a Merge Module.</remarks>
        /// <returns>The modularized version of the field data.</returns>
        internal string GetModularizedValue(Field field, string modularizationGuid, Hashtable suppressModularizationIdentifiers)
        {
            Debug.Assert(null != field.Data && 0 < ((string)field.Data).Length);
            string fieldData = Convert.ToString(field.Data, CultureInfo.InvariantCulture);

            if (null != modularizationGuid && ColumnModularizeType.None != field.Column.ModularizeType && !(Util.IsStandardAction(fieldData) || Util.IsStandardProperty(fieldData)))
            {
                StringBuilder        sb;
                int                  start;
                ColumnModularizeType modularizeType = field.Column.ModularizeType;

                // special logic for the ControlEvent table's Argument column
                // this column requires different modularization methods depending upon the value of the Event column
                if (ColumnModularizeType.ControlEventArgument == field.Column.ModularizeType)
                {
                    switch (this[2].ToString())
                    {
                    case "CheckExistingTargetPath": // redirectable property name
                    case "CheckTargetPath":
                    case "DoAction":                // custom action name
                    case "NewDialog":               // dialog name
                    case "SelectionBrowse":
                    case "SetTargetPath":
                    case "SpawnDialog":
                    case "SpawnWaitDialog":
                        if (CompilerCore.IsIdentifier(fieldData))
                        {
                            modularizeType = ColumnModularizeType.Column;
                        }
                        else
                        {
                            modularizeType = ColumnModularizeType.Property;
                        }
                        break;

                    default:     // formatted
                        modularizeType = ColumnModularizeType.Property;
                        break;
                    }
                }
                else if (ColumnModularizeType.ControlText == field.Column.ModularizeType)
                {
                    // icons are stored in the Binary table, so they get column-type modularization
                    if (("Bitmap" == this[2].ToString() || "Icon" == this[2].ToString()) && CompilerCore.IsIdentifier(fieldData))
                    {
                        modularizeType = ColumnModularizeType.Column;
                    }
                    else
                    {
                        modularizeType = ColumnModularizeType.Property;
                    }
                }

                switch (modularizeType)
                {
                case ColumnModularizeType.Column:
                    // ensure the value is an identifier (otherwise it shouldn't be modularized this way)
                    if (!CompilerCore.IsIdentifier(fieldData))
                    {
                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_CannotModularizeIllegalID, fieldData));
                    }

                    // if we're not supposed to suppress modularization of this identifier
                    if (null == suppressModularizationIdentifiers || !suppressModularizationIdentifiers.Contains(fieldData))
                    {
                        fieldData = String.Concat(fieldData, ".", modularizationGuid);
                    }
                    break;

                case ColumnModularizeType.Property:
                case ColumnModularizeType.Condition:
                    Regex regex;
                    if (ColumnModularizeType.Property == modularizeType)
                    {
                        regex = new Regex(@"\[(?<identifier>[#$!]?[a-zA-Z_][a-zA-Z0-9_\.]*)]", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                    }
                    else
                    {
                        Debug.Assert(ColumnModularizeType.Condition == modularizeType);

                        // This heinous looking regular expression is actually quite an elegant way
                        // to shred the entire condition into the identifiers that need to be
                        // modularized.  Let's break it down piece by piece:
                        //
                        // 1. Look for the operators: NOT, EQV, XOR, OR, AND, IMP (plus a space).  Note that the
                        //    regular expression is case insensitive so we don't have to worry about
                        //    all the permutations of these strings.
                        // 2. Look for quoted strings.  Quoted strings are just text and are ignored
                        //    outright.
                        // 3. Look for environment variables.  These look like identifiers we might
                        //    otherwise be interested in but start with a percent sign.  Like quoted
                        //    strings these enviroment variable references are ignored outright.
                        // 4. Match all identifiers that are things that need to be modularized.  Note
                        //    the special characters (!, $, ?, &) that denote Component and Feature states.
                        regex = new Regex(@"NOT\s|EQV\s|XOR\s|OR\s|AND\s|IMP\s|"".*?""|%[a-zA-Z_][a-zA-Z0-9_\.]*|(?<identifier>[!$\?&]?[a-zA-Z_][a-zA-Z0-9_\.]*)", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);

                        // less performant version of the above with captures showing where everything lives
                        // regex = new Regex(@"(?<operator>NOT|EQV|XOR|OR|AND|IMP)|(?<string>"".*?"")|(?<environment>%[a-zA-Z_][a-zA-Z0-9_\.]*)|(?<identifier>[!$\?&]?[a-zA-Z_][a-zA-Z0-9_\.]*)",RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
                    }

                    MatchCollection matches = regex.Matches(fieldData);

                    sb = new StringBuilder(fieldData);

                    // notice how this code walks backward through the list
                    // because it modifies the string as we through it
                    for (int i = matches.Count - 1; 0 <= i; i--)
                    {
                        Group group = matches[i].Groups["identifier"];
                        if (group.Success)
                        {
                            string identifier = group.Value;
                            if (!Util.IsStandardProperty(identifier) && (null == suppressModularizationIdentifiers || !suppressModularizationIdentifiers.Contains(identifier)))
                            {
                                sb.Insert(group.Index + group.Length, '.');
                                sb.Insert(group.Index + group.Length + 1, modularizationGuid);
                            }
                        }
                    }

                    fieldData = sb.ToString();
                    break;

                case ColumnModularizeType.CompanionFile:
                    // if we're not supposed to ignore this identifier and the value does not start with
                    // a digit, we must have a companion file so modularize it
                    if ((null == suppressModularizationIdentifiers || !suppressModularizationIdentifiers.Contains(fieldData)) &&
                        0 < fieldData.Length && !Char.IsDigit(fieldData, 0))
                    {
                        fieldData = String.Concat(fieldData, ".", modularizationGuid);
                    }
                    break;

                case ColumnModularizeType.Icon:
                    if (null == suppressModularizationIdentifiers || !suppressModularizationIdentifiers.Contains(fieldData))
                    {
                        start = fieldData.LastIndexOf(".", StringComparison.Ordinal);
                        if (-1 == start)
                        {
                            fieldData = String.Concat(fieldData, ".", modularizationGuid);
                        }
                        else
                        {
                            fieldData = String.Concat(fieldData.Substring(0, start), ".", modularizationGuid, fieldData.Substring(start));
                        }
                    }
                    break;

                case ColumnModularizeType.SemicolonDelimited:
                    string[] keys = fieldData.Split(';');
                    for (int i = 0; i < keys.Length; ++i)
                    {
                        keys[i] = String.Concat(keys[i], ".", modularizationGuid);
                    }
                    fieldData = String.Join(";", keys);
                    break;
                }
            }

            return(fieldData);
        }
Esempio n. 3
0
        /// <summary>
        /// Returns the field data in a format usable in IDT files.
        /// </summary>
        /// <param name="field">The field to modularize.</param>
        /// <param name="moduleGuid">String containing the GUID of the Merge Module to append the the field value, if appropriate.</param>
        /// <param name="ignoreModularizations">Optional collection of identifers that should not be modularized.</param>
        /// <remarks>moduleGuid is expected to be null when not being used to compile a Merge Module.</remarks>
        /// <returns>Field data in string IDT format.</returns>
        public string GetIdtValue(Field field, string moduleGuid, IgnoreModularizationCollection ignoreModularizations)
        {
            if (field.Column.IsUnreal)
            {
                return(null);
            }
            if (null == field.Data)
            {
                return(String.Empty);
            }

            string fieldData = Convert.ToString(field.Data);

            // special idt-specific escaping
            if (field.Column.EscapeIdtCharacters)
            {
                fieldData = fieldData.Replace('\t', '\x10');
                fieldData = fieldData.Replace('\r', '\x11');
                fieldData = fieldData.Replace('\n', '\x19');
            }

            string idtValue;

            if (null != moduleGuid && ColumnModularizeType.None != field.Column.ModularizeType && !Common.IsExcludedFromModularization(fieldData))
            {
                StringBuilder        sb;
                int                  start;
                ColumnModularizeType modularizeType = field.Column.ModularizeType;

                // special logic for the ControlEvent table's Argument column
                // this column requires different modularization methods depending upon the value of the Event column
                if (ColumnModularizeType.ControlEventArgument == field.Column.ModularizeType)
                {
                    switch (this.row[2].ToString())
                    {
                    case "CheckExistingTargetPath": // redirectable property name
                    case "CheckTargetPath":
                    case "DoAction":                // custom action name
                    case "NewDialog":               // dialog name
                    case "SelectionBrowse":
                    case "SetTargetPath":
                    case "SpawnDialog":
                    case "SpawnWaitDialog":
                        if (CompilerCore.IsIdentifier(fieldData))
                        {
                            modularizeType = ColumnModularizeType.Column;
                        }
                        else
                        {
                            modularizeType = ColumnModularizeType.Property;
                        }
                        break;

                    default:     // formatted
                        modularizeType = ColumnModularizeType.Property;
                        break;
                    }
                }

                switch (modularizeType)
                {
                case ColumnModularizeType.Column:
                    // ensure the value is an identifier (otherwise it shouldn't be modularized this way)
                    if (!CompilerCore.IsIdentifier(fieldData))
                    {
                        throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "The value '{0}' is not a legal identifier and therefore cannot be modularized.", fieldData));
                    }

                    // if we're not supposed to ignore this identifier
                    if (null == ignoreModularizations || !ignoreModularizations.ShouldIgnoreModularization(fieldData))
                    {
                        idtValue = String.Concat(fieldData, ".", moduleGuid);
                    }
                    else
                    {
                        idtValue = fieldData;
                    }
                    break;

                case ColumnModularizeType.Property:
                case ColumnModularizeType.Condition:
                    Regex regex;
                    if (ColumnModularizeType.Property == modularizeType)
                    {
                        regex = new Regex(@"\[(?<identifier>[#$!]?[a-zA-Z_][a-zA-Z0-9_\.]*)]", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                    }
                    else
                    {
                        Debug.Assert(ColumnModularizeType.Condition == modularizeType);

                        // This heinous looking regular expression is actually quite an elegant way
                        // to shred the entire condition into the identifiers that need to be
                        // modularized.  Let's break it down piece by piece:
                        //
                        // 1. Look for the operators: NOT, EQV, XOR, OR, AND, IMP.  Note that the
                        //    regular expression is case insensitive so we don't have to worry about
                        //    all the permutations of these strings.
                        // 2. Look for quoted strings.  Quoted strings are just text and are ignored
                        //    outright.
                        // 3. Look for environment variables.  These look like identifiers we might
                        //    otherwise be interested in but start with a percent sign.  Like quoted
                        //    strings these enviroment variable references are ignored outright.
                        // 4. Match all identifiers that are things that need to be modularized.  Note
                        //    the special characters (!, $, ?, &) that denote Component and Feature states.
                        regex = new Regex(@"NOT|EQV|XOR|OR|AND|IMP|"".*?""|%[a-zA-Z_][a-zA-Z0-9_\.]*|(?<identifier>[!$\?&]?[a-zA-Z_][a-zA-Z0-9_\.]*)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);

                        // less performant version of the above with captures showing where everything lives
                        // regex = new Regex(@"(?<operator>NOT|EQV|XOR|OR|AND|IMP)|(?<string>"".*?"")|(?<environment>%[a-zA-Z_][a-zA-Z0-9_\.]*)|(?<identifier>[!$\?&]?[a-zA-Z_][a-zA-Z0-9_\.]*)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
                    }

                    MatchCollection matches = regex.Matches(fieldData);

                    sb = new StringBuilder(fieldData);

                    // notice how this code walks backward through the list
                    // because it modifies the string as we through it
                    for (int i = matches.Count - 1; 0 <= i; i--)
                    {
                        Group group = matches[i].Groups["identifier"];
                        if (group.Success)
                        {
                            string identifier = group.Value;
                            if (!Common.IsStandardProperty(identifier) && (null == ignoreModularizations || !ignoreModularizations.ShouldIgnoreModularization(identifier)))
                            {
                                sb.Insert(group.Index + group.Length, '.');
                                sb.Insert(group.Index + group.Length + 1, moduleGuid);
                            }
                        }
                    }

                    idtValue = sb.ToString();
                    break;

                case ColumnModularizeType.CompanionFile:
                    // if we're not supposed to ignore this identifier and the value does not start with
                    // a digit, we must have a companion file so modularize it
                    if ((null == ignoreModularizations || !ignoreModularizations.ShouldIgnoreModularization(fieldData)) &&
                        0 < fieldData.Length && !Char.IsDigit(fieldData, 0))
                    {
                        idtValue = String.Concat(fieldData, ".", moduleGuid);
                    }
                    else
                    {
                        idtValue = fieldData;
                    }
                    break;

                case ColumnModularizeType.Icon:
                    if (null == ignoreModularizations || !ignoreModularizations.ShouldIgnoreModularization(fieldData))
                    {
                        start = fieldData.LastIndexOf(".");
                        if (-1 == start)
                        {
                            idtValue = String.Concat(fieldData, ".", moduleGuid);
                        }
                        else
                        {
                            idtValue = String.Concat(fieldData.Substring(0, start), ".", moduleGuid, fieldData.Substring(start));
                        }
                    }
                    else
                    {
                        idtValue = fieldData;
                    }
                    break;

                case ColumnModularizeType.SemicolonDelimited:
                    string[] keys = fieldData.Split(";".ToCharArray());
                    for (int i = 0; i < keys.Length; ++i)
                    {
                        keys[i] = String.Concat(keys[i], ".", moduleGuid);
                    }
                    idtValue = String.Join(";", keys);
                    break;

                default:
                    idtValue = fieldData;
                    break;
                }
            }
            else // no modularization necessary, just use the field data
            {
                idtValue = fieldData;
            }

            return(idtValue);
        }
Esempio n. 4
0
        public Intermediate Compile(XmlDocument source)
        {
            if (null == source)
            {
                throw new ArgumentNullException("source");
            }

            bool encounteredError = false;

            // create the intermediate
            Intermediate target = new Intermediate();

            // try to compile it
            try
            {
                this.core = new CompilerCore(target, this.tableDefinitions, this.extensions, this.Message, this.schema);
                this.core.ShowPedanticMessages = this.showPedanticMessages;
                this.core.CurrentPlatform = this.currentPlatform;
                this.core.FipsCompliant = this.fipsCompliant;

                foreach (CompilerExtension extension in this.extensions.Values)
                {
                    extension.Core = this.core;
                    extension.InitializeCompile();
                }

                // parse the document
                SourceLineNumberCollection sourceLineNumbers = Preprocessor.GetSourceLineNumbers(source.DocumentElement);
                if ("Wix" == source.DocumentElement.LocalName)
                {
                    if (this.schema.TargetNamespace == source.DocumentElement.NamespaceURI)
                    {
                        this.ParseWixElement(source.DocumentElement);
                    }
                    else // invalid or missing namespace
                    {
                        if (0 == source.DocumentElement.NamespaceURI.Length)
                        {
                            this.core.OnMessage(WixErrors.InvalidWixXmlNamespace(sourceLineNumbers, "Wix", this.schema.TargetNamespace));
                        }
                        else
                        {
                            this.core.OnMessage(WixErrors.InvalidWixXmlNamespace(sourceLineNumbers, "Wix", source.DocumentElement.NamespaceURI, this.schema.TargetNamespace));
                        }
                    }
                }
                else
                {
                    this.core.OnMessage(WixErrors.InvalidDocumentElement(sourceLineNumbers, source.DocumentElement.Name, "source", "Wix"));
                }

                // perform schema validation if there were no errors and validation isn't suppressed
                if (!this.core.EncounteredError && !this.suppressValidation)
                {
                    this.ValidateDocument(source);
                }

                // inspect the document
                InspectorCore inspectorCore = new InspectorCore(this.Message);
                foreach (InspectorExtension inspectorExtension in this.inspectorExtensions)
                {
                    inspectorExtension.Core = inspectorCore;
                    inspectorExtension.InspectIntermediate(target);

                    // reset
                    inspectorExtension.Core = null;
                }

                if (inspectorCore.EncounteredError)
                {
                    encounteredError = true;
                }
            }
            finally
            {
                if (this.core.EncounteredError)
                {
                    encounteredError = true;
                }

                foreach (CompilerExtension extension in this.extensions.Values)
                {
                    extension.FinalizeCompile();
                    extension.Core = null;
                }
                this.core = null;
            }

            // return the compiled intermediate only if it completed successfully
            return (encounteredError ? null : target);
        }
Esempio n. 5
0
        /// <summary>
        /// Compiles the provided Xml document into an intermediate object
        /// </summary>
        /// <param name="source">Source xml document to compile.</param>
        /// <param name="sourcePath">Optional original path to xml document on disk.</param>
        /// <returns>Intermediate object representing compiled source document.</returns>
        /// <remarks>This method is not thread-safe.</remarks>
        public Intermediate Compile(XmlDocument source, string sourcePath)
        {
            if (null == source)
            {
                throw new ArgumentNullException("source");
            }

            bool encounteredError = true; // assume we'll hit an error

            // create the intermediate
            Intermediate target = new Intermediate();
            target.SourcePath = sourcePath;

            // try to compile it
            try
            {
                this.core = new CompilerCore(target, this.tableDefinitions, this.Message);
                this.core.PedanticLevel = this.pedanticLevel;
                this.extensionMessages = new ExtensionMessages(this.core);

                foreach (CompilerExtension extension in this.extensions.Values)
                {
                    extension.Core = this.core;
                    extension.Messages = this.extensionMessages;
                    extension.InitializeCompile();
                }

                // parse the document
                if ("Wix" == source.DocumentElement.LocalName)
                {
                    this.ParseWixElement(source.DocumentElement);
                }
                else
                {
                    this.core.OnMessage(WixErrors.InvalidDocumentElement(null, source.DocumentElement.Name, "source", "Wix"));
                }

                // perform schema validation if there were no errors and validation isn't suppressed
                if (!this.core.EncounteredError && !this.suppressValidation)
                {
                    this.ValidateDocument(source);
                }
            }
            finally
            {
                encounteredError = this.core.EncounteredError;

                foreach (CompilerExtension extension in this.extensions.Values)
                {
                    extension.FinalizeCompile();
                    extension.Core = null;
                }
                this.core = null;
            }

            // return the compiled intermediate only if it completed successfully
            return (encounteredError ? null : target);
        }