internal FilteredAttributeDictionary(ParsedAttributeCollection owner, string filter) { this._filter = filter; this._owner = owner; this._data = new ListDictionary(StringComparer.OrdinalIgnoreCase); }
// Used for updatable deployment precompilation void CreateModifiedMainDirectiveFileIfNeeded(string text, Match match, ParsedAttributeCollection mainDirective, Encoding fileEncoding) { TextWriter precompTargetWriter = BuildManager.GetUpdatableDeploymentTargetWriter(CurrentVirtualPath, fileEncoding); // If we're not precompiling for deployment, there is nothing to do here if (precompTargetWriter == null) return; using (precompTargetWriter) { // Write out everything up to the main directive precompTargetWriter.Write(text.Substring(0, match.Index)); precompTargetWriter.Write("<%@ " + DefaultDirectiveName); // Go through all the attributes on the main directive foreach (DictionaryEntry entry in mainDirective) { string attribName = (string) entry.Key; string attribValue = (string) entry.Value; // Remove the codefile and CodeFileBaseClass attributes if (StringUtil.EqualsIgnoreCase(attribName, "codefile")) continue; if (StringUtil.EqualsIgnoreCase(attribName, CodeFileBaseClassAttributeName)) continue; // Write out a special token for the inherits attribute. It will later be replaced by // the full type later in the precompilation. We can't do it here because we don't know // the assembly name yet (VSWhidbey 467936) if (StringUtil.EqualsIgnoreCase(attribName, "inherits")) { attribValue = BuildManager.UpdatableInheritReplacementToken; } precompTargetWriter.Write(" "); precompTargetWriter.Write(attribName); precompTargetWriter.Write("=\""); precompTargetWriter.Write(attribValue); precompTargetWriter.Write("\""); } precompTargetWriter.Write(" %>"); // Write out everything after the main directive precompTargetWriter.Write(text.Substring(match.Index+match.Length)); } }
/* * Adds attributes and their values to the attribs * Sets the _id and isServerTag data members as appropriate. * If fDirective is true, we are being called for a <%@ %> block, in * which case the name of the directive is returned (e.g. "page") */ private string ProcessAttributes(string text, Match match, out ParsedAttributeCollection attribs, bool fDirective, out string duplicateAttribute) { string directiveName = String.Empty; attribs = CreateEmptyAttributeBag();; CaptureCollection attrnames = match.Groups["attrname"].Captures; CaptureCollection attrvalues = match.Groups["attrval"].Captures; CaptureCollection equalsign = null; if (fDirective) equalsign = match.Groups["equal"].Captures; flags[isServerTag] = false; _id = null; duplicateAttribute = null; for (int i = 0; i < attrnames.Count; i++) { string attribName = attrnames[i].ToString(); // If processing a directive, set the attribute name to lower case for easier processing later if (fDirective) attribName = attribName.ToLower(CultureInfo.InvariantCulture); Capture attrValue = attrvalues[i]; string attribValue = attrValue.ToString(); // Any of the attributes could be filtered string realAttributeName = String.Empty; string filter = Util.ParsePropertyDeviceFilter(attribName, out realAttributeName); // Always HTML decode all attributes (ASURT 54544) attribValue = HttpUtility.HtmlDecode(attribValue); // If we're parsing a directive, check if there is an equal sign. bool fHasEqual = false; if (fDirective) fHasEqual = (equalsign[i].ToString().Length > 0); // If this is a server ID, remember it // if (StringUtil.EqualsIgnoreCase(realAttributeName, "id")) { _id = attribValue; } else if (StringUtil.EqualsIgnoreCase(realAttributeName, "runat")) { // Make sure no device filter or resource expression was specified (VSWhidbey 85325) ValidateBuiltInAttribute(filter, realAttributeName, attribValue); // Only runat=server is valid if (!StringUtil.EqualsIgnoreCase(attribValue, "server")) { ProcessError(SR.GetString(SR.Runat_can_only_be_server)); } // Set a flag if we see runat=server flags[isServerTag] = true; attribName = null; // Don't put it in attribute bag } else if (FInDesigner && StringUtil.EqualsIgnoreCase(realAttributeName, "ignoreParentFrozen")) { // VSWhidbey 537398: "ignoreParentFrozen" is a special expando used in Venus. Ideally // Venus would hide the expando altogether but that's not practical in Whidbey. attribName = null; } if (attribName != null) { // A <%@ %> block can have two formats: // <%@ directive foo=1 bar=hello %> // <%@ foo=1 bar=hello %> // Check if we have the first format if (fDirective && !fHasEqual && i==0) { directiveName = attribName; if (string.Compare(directiveName, DefaultDirectiveName, StringComparison.OrdinalIgnoreCase) == 0) { directiveName = String.Empty; } continue; } try { // Don't allow filters in directive other than the main one if (fDirective && directiveName.Length > 0 && filter.Length > 0) { ProcessError(SR.GetString(SR.Device_unsupported_in_directive, directiveName)); continue; } attribs.AddFilteredAttribute(filter, realAttributeName, attribValue); //Since the attribute column values are only used for generating line pragmas at design time for intellisense to work, //we populate that only at design time so that runtime memory usage is not affected. if (BuildManagerHost.InClientBuildManager) { //Linenumber = Linenumber of tag beginning + new lines between tag beginning and attribute value beginning. //Column = number of characters from the last new line (before the attrValue in the entire Text) till attrValue. int lineNumber = _lineNumber + Util.LineCount(text, match.Index, attrValue.Index); int column = attrValue.Index - text.LastIndexOfAny(s_newlineChars, attrValue.Index - 1); attribs.AddAttributeValuePositionInformation(realAttributeName, lineNumber, column); } } catch (ArgumentException) { // Duplicate attribute. We can't throw until we find out if // it's a server side tag (ASURT 51273) duplicateAttribute = attribName; } catch (Exception ex) { ProcessException(ex); } } } if (duplicateAttribute != null && fDirective) { ProcessError(SR.GetString(SR.Duplicate_attr_in_directive, duplicateAttribute)); } return directiveName; }
/// <devdoc> /// Preprocess all the attributes at parse time, so that we'll be left /// with as little work as possible when we build the control. /// </devdoc> private void PreprocessAttributes(ParsedAttributeCollection attribs) { ProcessImplicitResources(attribs); //Since the attribute column values are only used for generating line pragmas at design time for intellisense to work, //we populate that only at design time so that runtime memory usage is not affected. bool isDesignerMode = BuildManagerHost.InClientBuildManager; IDictionary<String, Pair> attributeValuePositions = null; if (isDesignerMode) { //This dictionary indicates the column values at which the attribute value expressions begin and //that is used for generating line pragmas at design time for intellisense. attributeValuePositions = attribs.AttributeValuePositionsDictionary; } // Preprocess all the attributes foreach (FilteredAttributeDictionary filteredAttributes in attribs.GetFilteredAttributeDictionaries()) { string filter = filteredAttributes.Filter; foreach (DictionaryEntry attribute in filteredAttributes) { string name = attribute.Key.ToString(); string value = attribute.Value.ToString(); int column = 0; int line = 0; if (isDesignerMode && attributeValuePositions.ContainsKey(name)) { line = (int)attributeValuePositions[name].First; column = (int)attributeValuePositions[name].Second; } PreprocessAttribute(filter, name, value, false, line, column); } } }
internal FilteredAttributeDictionary(ParsedAttributeCollection owner, string filter) { _filter = filter; _owner = owner; _data = new ListDictionary(StringComparer.OrdinalIgnoreCase); }
internal static ParsedAttributeCollection ConvertDictionaryToParsedAttributeCollection(IDictionary attribs) { if (attribs is ParsedAttributeCollection) { return (ParsedAttributeCollection)attribs; } // Assert here so we know our own code is never passing in a plain IDictionary // System.Web.Mobile does this, so we don't assert // Debug.Assert(false); ParsedAttributeCollection newAttribs = new ParsedAttributeCollection(); foreach (DictionaryEntry entry in attribs) { newAttribs.AddFilteredAttribute(String.Empty, entry.Key.ToString(), entry.Value.ToString()); } return newAttribs; }
/// <devdoc> /// Process implicit resources if the control has a meta:resourcekey attribute /// </devdoc> internal void ProcessImplicitResources(ParsedAttributeCollection attribs) { // Check if meta:localize="false" was specified. Always do this since we need it at design-time string localize = (string)((IDictionary)attribs)["meta:localize"]; if (localize != null) { // Depending on the control type, don't allow meta:localize (e.g. ITemplate case) (VSWhidbey 276398, 454894) if (!IsValidForImplicitLocalization()) { throw new InvalidOperationException(SR.GetString(SR.meta_localize_notallowed, TagName)); } bool parseResult; if (!Boolean.TryParse(localize, out parseResult)) { throw new HttpException(SR.GetString(SR.ControlBuilder_InvalidLocalizeValue, localize)); } ParseTimeData.Localize = parseResult; } else { ParseTimeData.Localize = true; } // Check whether a resource key was specified string keyPrefix = (string) ((IDictionary)attribs)["meta:resourcekey"]; // Remove all meta attributes from the collection (VSWhidbey 230192) attribs.ClearFilter("meta"); if (keyPrefix == null) return; // Depending on the control type, don't allow meta:reskey (e.g. ITemplate case) (VSWhidbey 276398, 454894) if (!IsValidForImplicitLocalization()) { throw new InvalidOperationException(SR.GetString(SR.meta_reskey_notallowed, TagName)); } Debug.Assert(_controlType != null, "If we get here then the tag type must be either an ICollection or a Control, so how can it be null?"); // Restrict resource keys the same way as we restrict ID's (VSWhidbey 256438) if (!System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(keyPrefix)) { throw new HttpException(SR.GetString(SR.Invalid_resourcekey, keyPrefix)); } if (!ParseTimeData.Localize) { // If we have a key prefix (from meta:resourcekey) but we also have // meta:localize=false, we throw. throw new HttpException(SR.GetString(SR.meta_localize_error)); } ParseTimeData.ResourceKeyPrefix = keyPrefix; // Try to get the implicit resources for this specific Page IImplicitResourceProvider implicitResourceProvider; if (Parser.FInDesigner && Parser.DesignerHost != null) { implicitResourceProvider = (IImplicitResourceProvider)Parser.DesignerHost.GetService(typeof(IImplicitResourceProvider)); } else { implicitResourceProvider = Parser.GetImplicitResourceProvider(); } // If the Page has resources, get the specific ones for this meta:resourcekey ICollection tagResources = null; if (implicitResourceProvider != null) tagResources = implicitResourceProvider.GetImplicitResourceKeys(keyPrefix); if (tagResources != null) { // Get the IDesignerHost in case we need it to find ExpressionBuilders IDesignerHost host = DesignerHost; // Note: this code expect that the "resources" expression builder be // registered in config. If the user removes it, they will get an error. ExpressionBuilder resourcesExpressionBuilder = ExpressionBuilder.GetExpressionBuilder("resources", Parser.CurrentVirtualPath, host); bool usingStandardResources = typeof(ResourceExpressionBuilder) == resourcesExpressionBuilder.GetType(); foreach (ImplicitResourceKey entry in tagResources) { // Put together the complete resource key, as would appear in an explicit resource string fullResourceKey = keyPrefix + "." + entry.Property; if (entry.Filter.Length > 0) fullResourceKey = entry.Filter + ':' + fullResourceKey; // Replace '.' with '-', since that's what AddBoundProperty expects string property = entry.Property.Replace('.', '-'); object parsedExpressionData = null; string expression; if (usingStandardResources) { // If we're using the standard System.Web.Compilation.ResourceExpressionBuilder // we can optimized the parsed data. parsedExpressionData = ResourceExpressionBuilder.ParseExpression(fullResourceKey); expression = String.Empty; } else { expression = fullResourceKey; } AddBoundProperty(entry.Filter, property, "resources", expression, resourcesExpressionBuilder, parsedExpressionData, true, String.Empty, String.Empty, false, encode:false); } } }
/// <devdoc> /// /// </devdoc> public virtual void AppendSubBuilder(ControlBuilder subBuilder) { // Tell the sub builder that it's about to be appended to its parent subBuilder.OnAppendToParentBuilder(this); if (FChildrenAsProperties) { // Don't allow code blocks when properties are expected (ASURT 97838) if (subBuilder is CodeBlockBuilder) { throw new HttpException(SR.GetString(SR.Code_not_supported_on_not_controls)); } // If there is a default property, delegate to its builder if (DefaultPropertyBuilder != null) { DefaultPropertyBuilder.AppendSubBuilder(subBuilder); return; } // The tagname is the property name string propName = subBuilder.TagName; if (subBuilder is TemplateBuilder) { TemplateBuilder tplBuilder = (TemplateBuilder)subBuilder; AddTemplateProperty(tplBuilder.Filter, propName, tplBuilder); } else if (subBuilder is CollectionBuilder) { // If there are items in the collection, add them if ((subBuilder.SubBuilders != null) && (subBuilder.SubBuilders.Count > 0)) { IEnumerator subBuilders = subBuilder.SubBuilders.GetEnumerator(); while (subBuilders.MoveNext()) { ControlBuilder builder = (ControlBuilder)subBuilders.Current; subBuilder.AddCollectionItem(builder); } subBuilder.SubBuilders.Clear(); AddComplexProperty(subBuilder.Filter, propName, subBuilder); } } else if (subBuilder is StringPropertyBuilder) { // Trim this so whitespace doesn't matter inside a tag? string text = ((StringPropertyBuilder)subBuilder).Text.Trim(); if (!String.IsNullOrEmpty(text)) { // Make sure we haven't set this property in the attributes already (special case for TextBox and similar things) AddComplexProperty(subBuilder.Filter, propName, subBuilder); } } else { AddComplexProperty(subBuilder.Filter, propName, subBuilder); } return; } CodeBlockBuilder codeBlockBuilder = subBuilder as CodeBlockBuilder; if (codeBlockBuilder != null) { // Don't allow code blocks inside non-control tags (ASURT 76719) if (ControlType != null && !flags[controlTypeIsControl]) { throw new HttpException(SR.GetString(SR.Code_not_supported_on_not_controls)); } // Is it a databinding expression? <%# ... %> if (codeBlockBuilder.BlockType == CodeBlockType.DataBinding) { // Bind statements are not allowed as DataBoundLiterals inside any template. // Outside a template, they should be treated as calls to page code. Match match; if ((match = bindExpressionRegex.Match(codeBlockBuilder.Content, 0)).Success || (match = bindItemExpressionRegex.Match(codeBlockBuilder.Content, 0)).Success) { ControlBuilder currentBuilder = this; while (currentBuilder != null && !(currentBuilder is TemplateBuilder)) { currentBuilder = currentBuilder.ParentBuilder; } if (currentBuilder != null && currentBuilder.ParentBuilder != null && currentBuilder is TemplateBuilder) { throw new HttpException(SR.GetString(SR.DataBoundLiterals_cant_bind)); } } if (InDesigner) { // In the designer, don't use the fancy multipart DataBoundLiteralControl, // which breaks a number of things (ASURT 82925,86738). Instead, use the // simpler DesignerDataBoundLiteralControl, and do standard databinding // on its Text property. IDictionary attribs = new ParsedAttributeCollection(); attribs.Add("Text", "<%#" + codeBlockBuilder.Content + "%>"); subBuilder = CreateBuilderFromType(Parser, this, typeof(DesignerDataBoundLiteralControl), null, null, attribs, codeBlockBuilder.Line, codeBlockBuilder.PageVirtualPath); } else { // Get the last builder, and check if it's a DataBoundLiteralControlBuilder object lastBuilder = GetLastBuilder(); DataBoundLiteralControlBuilder dataBoundBuilder = lastBuilder as DataBoundLiteralControlBuilder; // If not, then we need to create one. Otherwise, just append to the // existing one bool fNewDataBoundLiteralControl = false; if (dataBoundBuilder == null) { dataBoundBuilder = new DataBoundLiteralControlBuilder(); dataBoundBuilder.Init(Parser, this, typeof(DataBoundLiteralControl), null, null, null); dataBoundBuilder.Line = codeBlockBuilder.Line; dataBoundBuilder.VirtualPath = codeBlockBuilder.VirtualPath; fNewDataBoundLiteralControl = true; // If the previous builder was a string, add it as the first // entry in the composite control. // But if instrumentation is enabled, the strings need to be // treated separately, so don't combine them if (!PageInstrumentationService.IsEnabled) { string s = lastBuilder as string; if (s != null) { SubBuilders.RemoveAt(SubBuilders.Count - 1); dataBoundBuilder.AddLiteralString(s); } } } dataBoundBuilder.AddDataBindingExpression(codeBlockBuilder); if (!fNewDataBoundLiteralControl) return; subBuilder = dataBoundBuilder; } } else { // Set a flag if there is at least one block of ASP code ParseTimeData.HasAspCode = true; } } if (FIsNonParserAccessor) { throw new HttpException(SR.GetString(SR.Children_not_supported_on_not_controls)); } AddSubBuilder(subBuilder); }
internal static ParsedAttributeCollection ConvertDictionaryToParsedAttributeCollection(IDictionary attribs) { if (attribs is ParsedAttributeCollection) { return (ParsedAttributeCollection) attribs; } ParsedAttributeCollection attributes = new ParsedAttributeCollection(); foreach (DictionaryEntry entry in attribs) { string name = entry.Key.ToString(); attributes.AddFilteredAttribute(string.Empty, name, entry.Value.ToString()); } return attributes; }
public virtual void AppendSubBuilder(ControlBuilder subBuilder) { subBuilder.OnAppendToParentBuilder(this); if (this.FChildrenAsProperties) { if (subBuilder is CodeBlockBuilder) { throw new HttpException(System.Web.SR.GetString("Code_not_supported_on_not_controls")); } if (this.DefaultPropertyBuilder != null) { this.DefaultPropertyBuilder.AppendSubBuilder(subBuilder); } else { string tagName = subBuilder.TagName; if (subBuilder is TemplateBuilder) { TemplateBuilder builder = (TemplateBuilder) subBuilder; this.AddTemplateProperty(builder.Filter, tagName, builder); } else if (subBuilder is CollectionBuilder) { if ((subBuilder.SubBuilders != null) && (subBuilder.SubBuilders.Count > 0)) { IEnumerator enumerator = subBuilder.SubBuilders.GetEnumerator(); while (enumerator.MoveNext()) { ControlBuilder current = (ControlBuilder) enumerator.Current; subBuilder.AddCollectionItem(current); } subBuilder.SubBuilders.Clear(); this.AddComplexProperty(subBuilder.Filter, tagName, subBuilder); } } else if (subBuilder is StringPropertyBuilder) { if (!string.IsNullOrEmpty(((StringPropertyBuilder) subBuilder).Text.Trim())) { this.AddComplexProperty(subBuilder.Filter, tagName, subBuilder); } } else { this.AddComplexProperty(subBuilder.Filter, tagName, subBuilder); } } } else { CodeBlockBuilder codeBlockBuilder = subBuilder as CodeBlockBuilder; if (codeBlockBuilder != null) { if ((this.ControlType != null) && !this.flags[0x2000]) { throw new HttpException(System.Web.SR.GetString("Code_not_supported_on_not_controls")); } if (codeBlockBuilder.BlockType == CodeBlockType.DataBinding) { if (bindExpressionRegex.Match(codeBlockBuilder.Content, 0).Success) { ControlBuilder parentBuilder = this; while ((parentBuilder != null) && !(parentBuilder is TemplateBuilder)) { parentBuilder = parentBuilder.ParentBuilder; } if (((parentBuilder != null) && (parentBuilder.ParentBuilder != null)) && (parentBuilder is TemplateBuilder)) { throw new HttpException(System.Web.SR.GetString("DataBoundLiterals_cant_bind")); } } if (this.InDesigner) { IDictionary attribs = new ParsedAttributeCollection(); attribs.Add("Text", "<%#" + codeBlockBuilder.Content + "%>"); subBuilder = CreateBuilderFromType(this.Parser, this, typeof(DesignerDataBoundLiteralControl), null, null, attribs, codeBlockBuilder.Line, codeBlockBuilder.PageVirtualPath); } else { object lastBuilder = this.GetLastBuilder(); DataBoundLiteralControlBuilder builder5 = lastBuilder as DataBoundLiteralControlBuilder; bool flag = false; if (builder5 == null) { builder5 = new DataBoundLiteralControlBuilder(); builder5.Init(this.Parser, this, typeof(DataBoundLiteralControl), null, null, null); builder5.Line = codeBlockBuilder.Line; builder5.VirtualPath = codeBlockBuilder.VirtualPath; flag = true; string s = lastBuilder as string; if (s != null) { this.SubBuilders.RemoveAt(this.SubBuilders.Count - 1); builder5.AddLiteralString(s); } } builder5.AddDataBindingExpression(codeBlockBuilder); if (!flag) { return; } subBuilder = builder5; } } else { this.ParseTimeData.HasAspCode = true; } } if (this.FIsNonParserAccessor) { throw new HttpException(System.Web.SR.GetString("Children_not_supported_on_not_controls")); } this.AddSubBuilder(subBuilder); } }
internal void ProcessImplicitResources(ParsedAttributeCollection attribs) { string str = (string) ((IDictionary) attribs)["meta:localize"]; if (str != null) { bool flag; if (!this.IsValidForImplicitLocalization()) { throw new InvalidOperationException(System.Web.SR.GetString("meta_localize_notallowed", new object[] { this.TagName })); } if (!bool.TryParse(str, out flag)) { throw new HttpException(System.Web.SR.GetString("ControlBuilder_InvalidLocalizeValue", new object[] { str })); } this.ParseTimeData.Localize = flag; } else { this.ParseTimeData.Localize = true; } string str2 = (string) ((IDictionary) attribs)["meta:resourcekey"]; attribs.ClearFilter("meta"); if (str2 != null) { IImplicitResourceProvider service; if (!this.IsValidForImplicitLocalization()) { throw new InvalidOperationException(System.Web.SR.GetString("meta_reskey_notallowed", new object[] { this.TagName })); } if (!CodeGenerator.IsValidLanguageIndependentIdentifier(str2)) { throw new HttpException(System.Web.SR.GetString("Invalid_resourcekey", new object[] { str2 })); } if (!this.ParseTimeData.Localize) { throw new HttpException(System.Web.SR.GetString("meta_localize_error")); } this.ParseTimeData.ResourceKeyPrefix = str2; if (this.Parser.FInDesigner && (this.Parser.DesignerHost != null)) { service = (IImplicitResourceProvider) this.Parser.DesignerHost.GetService(typeof(IImplicitResourceProvider)); } else { service = this.Parser.GetImplicitResourceProvider(); } ICollection implicitResourceKeys = null; if (service != null) { implicitResourceKeys = service.GetImplicitResourceKeys(str2); } if (implicitResourceKeys != null) { IDesignerHost designerHost = this.DesignerHost; ExpressionBuilder expressionBuilder = ExpressionBuilder.GetExpressionBuilder("resources", this.Parser.CurrentVirtualPath, designerHost); bool flag2 = typeof(ResourceExpressionBuilder) == expressionBuilder.GetType(); foreach (ImplicitResourceKey key in implicitResourceKeys) { string str5; string expression = str2 + "." + key.Property; if (key.Filter.Length > 0) { expression = key.Filter + ':' + expression; } string name = key.Property.Replace('.', '-'); object parsedExpressionData = null; if (flag2) { parsedExpressionData = ResourceExpressionBuilder.ParseExpression(expression); str5 = string.Empty; } else { str5 = expression; } this.AddBoundProperty(key.Filter, name, "resources", str5, expressionBuilder, parsedExpressionData, true, string.Empty, string.Empty, false); } } } }
private void PreprocessAttributes(ParsedAttributeCollection attribs) { this.ProcessImplicitResources(attribs); foreach (FilteredAttributeDictionary dictionary in attribs.GetFilteredAttributeDictionaries()) { string filter = dictionary.Filter; foreach (DictionaryEntry entry in (IEnumerable) dictionary) { string attribname = entry.Key.ToString(); string attribvalue = entry.Value.ToString(); this.PreprocessAttribute(filter, attribname, attribvalue, false); } } }