WmlMobileTextWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / MIT / System / Web / UI / MobileControls / Adapters / WmlMobileTextWriter.cs / 1305376 / WmlMobileTextWriter.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.Specialized;
using System.Globalization; 
using System.IO;
using System.Web.Mobile;
using System.Web.UI.MobileControls;
using System.Text.RegularExpressions; 
using System.Diagnostics;
using System.Web.Security; 
using System.Security.Permissions; 

using SR=System.Web.UI.MobileControls.Adapters.SR; 

#if COMPILING_FOR_SHIPPED_SOURCE
using Adapters=System.Web.UI.MobileControls.ShippedAdapterSource;
namespace System.Web.UI.MobileControls.ShippedAdapterSource 
#else
using Adapters=System.Web.UI.MobileControls.Adapters; 
namespace System.Web.UI.MobileControls.Adapters 
#endif
 
{
    /*
     * WmlMobileTextWriter class.
     * 
     * Copyright (c) 2000 Microsoft Corporation
     */ 
 
    /// 
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] 
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
    public class WmlMobileTextWriter : MobileTextWriter
    { 
        private TextWriter      _realInnerWriter;
        private EmptyTextWriter _analyzeWriter; 
        private bool            _analyzeMode = false; 
        private MobilePage      _page;
        private Form            _currentForm; 
        private bool[]          _usingPostBackType   = new bool[] { false, false };
        private bool[]          _writtenPostBackType = new bool[] { false, false };
        private int             _numberOfPostBacks;
        private bool            _postBackCardsEfficient = false; 
        private IDictionary     _formVariables = null;
        private IDictionary     _controlShortNames = null; 
        private Stack           _layoutStack = new Stack(); 
        private Stack           _formatStack = new Stack();
        private WmlLayout       _currentWrittenLayout = null; 
        private WmlFormat       _currentWrittenFormat = null;
        private bool            _pendingBreak = false;
        private bool            _inAnchor = false;
        private int             _numberOfSoftkeys; 
        private bool            _provideBackButton = false;
        private bool            _writtenFormVariables = false; 
        private bool            _alwaysScrambleClientIDs = false; 

        private const String    _largeTag  = "big"; 
        private const String    _smallTag  = "small";
        private const String    _boldTag   = "b";
        private const String    _italicTag = "i";
        internal const String   _postBackCardPrefix = "__pbc"; 
        private const String    _postBackWithVarsCardId = "__pbc1";
        private const String    _postBackWithoutVarsCardId = "__pbc2"; 
        internal const String   _postBackEventTargetVarName = "mcsvt"; 
        internal const String   _postBackEventArgumentVarName = "mcsva";
        private const String    _shortNamePrefix = "mcsv"; 
        private const int       _maxShortNameLength = 16;
        private static Random   _random = new Random();

        ///  
        public WmlMobileTextWriter(TextWriter writer, MobileCapabilities device, MobilePage page)
            : base(writer, device) 
        { 
            _realInnerWriter = writer;
            _page = page; 

            _numberOfSoftkeys = Device.NumberOfSoftkeys;
            if (_numberOfSoftkeys > 2)
            { 
                _numberOfSoftkeys = 2;
            } 
 
            // For phones that don't have a back button, assign a softkey.
 
            if (_numberOfSoftkeys == 2 && !Device.HasBackButton)
            {
                _numberOfSoftkeys = 1;
                _provideBackButton = true; 
                _alwaysScrambleClientIDs = _provideBackButton &&
                                                !device.CanRenderOneventAndPrevElementsTogether; 
            } 
        }
 
        // AnalyzeMode is set to true during first analysis pass of rendering.

        /// 
        public bool AnalyzeMode 
        {
            get 
            { 
                return _analyzeMode;
            } 
            set
            {
                _analyzeMode = value;
                if (value) 
                {
                    _analyzeWriter = new EmptyTextWriter(); 
                    InnerWriter = _analyzeWriter; 
                }
                else 
                {
                    InnerWriter = _realInnerWriter;
                }
            } 
        }
 
        internal bool HasFormVariables 
        {
            get 
            {
                return _writtenFormVariables;
            }
        } 

        ///  
        public override void EnterLayout(Style style) 
        {
            if (AnalyzeMode) 
            {
                return;
            }
 
            WmlLayout newLayout = new WmlLayout(style, CurrentLayout);
            _layoutStack.Push(newLayout); 
        } 

        ///  
        public override void ExitLayout(Style style, bool breakAfter)
        {
            if (!AnalyzeMode)
            { 
                if (breakAfter)
                { 
                    PendingBreak = true; 
                }
                _layoutStack.Pop(); 
            }
        }

        ///  
        public override void EnterFormat(Style style)
        { 
            if (AnalyzeMode) 
            {
                return; 
            }

            WmlFormat newFormat = new WmlFormat(style, CurrentFormat);
            _formatStack.Push(newFormat); 
        }
 
        ///  
        public override void ExitFormat(Style style)
        { 
            if (AnalyzeMode)
            {
                return;
            } 
            _formatStack.Pop();
        } 
 
        /// 
        public virtual void BeginForm(Form form) 
        {
            _cachedFormQueryString = null;
            _currentForm = form;
 
            _writtenFormVariables = false;
 
            // To keep track of postbacks which submit form variables, 
            // and postbacks that don't. Used for postback cards
            // (see UsePostBackCards) 

            _usingPostBackType[0] = _usingPostBackType[1] = false;

            if (AnalyzeMode) 
            {
                _numberOfPostBacks = 0; 
                _postBackCardsEfficient = false; 
                _controlShortNames = null;
            } 
            else
            {
                PendingBreak = false;
                _currentWrittenLayout = null; 
                _currentWrittenFormat = null;
 
                RenderBeginForm(form); 
            }
        } 

        /// 
        public virtual void EndForm()
        { 
            if (AnalyzeMode)
            { 
                // Analyze form when done. 
                PostAnalyzeForm();
            } 
            else
            {
                RenderEndForm();
            } 
        }
 
        // Single parameter - used for rendering ordinary inline text 
        // (with encoding but without breaks).
        ///  
        public void RenderText(String text)
        {
            RenderText(text, false, true);
        } 

        // Two parameters - used for rendering encoded text with or without breaks) 
        ///  
        public void RenderText(String text, bool breakAfter)
        { 
            RenderText(text, breakAfter, true);
        }

        ///  
        public virtual void RenderText(String text, bool breakAfter, bool encodeText)
        { 
            if (!AnalyzeMode) 
            {
                EnsureLayout(); 

                // Don't use formatting tags inside anchor.
                if (!_inAnchor)
                { 
                    EnsureFormat();
                } 
 
                WriteText(text, encodeText);
                if (breakAfter) 
                {
                    PendingBreak = true;
                }
            } 
        }
 
        // Escape '&' in XML if it hasn't been 
        internal String EscapeAmpersand(String url)
        { 
            const char ampersand = '&';
            const String ampEscaped = "amp;";

            if (url == null) 
            {
                return null; 
            } 

            int ampPos = url.IndexOf(ampersand); 
            while (ampPos != -1)
            {
                if (url.Length - ampPos <= ampEscaped.Length ||
                    url.Substring(ampPos + 1, ampEscaped.Length) != ampEscaped) 
                {
                    url = url.Insert(ampPos + 1, ampEscaped); 
                } 
                ampPos = url.IndexOf(ampersand, ampPos + ampEscaped.Length + 1);
            } 

            return url;
        }
 
        /// 
        public virtual void RenderBeginHyperlink(String targetUrl, 
                                                 bool encodeUrl, 
                                                 String softkeyLabel,
                                                 bool implicitSoftkeyLabel, 
                                                 bool mapToSoftkey)
        {
            if (!AnalyzeMode)
            { 
                EnsureLayout();
                EnsureFormat(); 
 
                WriteBeginTag("a");
                Write(" href=\""); 
                if (encodeUrl)
                {
                    WriteEncodedUrl(targetUrl);
                } 
                else
                { 
                    Write(EscapeAmpersand(targetUrl)); 
                }
                Write("\""); 
                if (softkeyLabel != null && softkeyLabel.Length > 0 && !RequiresNoSoftkeyLabels())
                {
                    WriteTextEncodedAttribute("title", softkeyLabel);
                } 
                Write(">");
                _inAnchor = true; 
            } 
        }
 
        /// 
        public virtual void RenderEndHyperlink(bool breakAfter)
        {
            if (!AnalyzeMode) 
            {
                WriteEndTag("a"); 
                if (breakAfter) 
                {
                    PendingBreak = true; 
                }
                _inAnchor = false;
            }
        } 

        ///  
        public virtual void RenderTextBox(String id, 
                                          String value,
                                          String format, 
                                          String title,
                                          bool password,
                                          int size,
                                          int maxLength, 
                                          bool generateRandomID,
                                          bool breakAfter) 
        { 
            if (!AnalyzeMode)
            { 
                // Input tags cannot appear inside character formatting tags,
                // so close any character formatting.

                CloseCharacterFormat(); 

                // Certain devices always render a break before a .  If 
                // we're on such a device, cancel any pending breaks so as not
                // to get an extra line of whitespace.
                if (Device.RendersBreakBeforeWmlSelectAndInput)
                { 
                    PendingBreak = false;
                } 
 
                EnsureLayout();
                WriteBeginTag("select"); 
                if (name != null && name.Length > 0)
                {
                    // Map the client ID to a short name. See
                    // MapClientIDToShortName for details. 
                    WriteAttribute("name", MapClientIDToShortName(name,  false));
                } 
                if (iname != null && iname.Length > 0) 
                {
                    // Map the client ID to a short name. See 
                    // MapClientIDToShortName for details.
                    WriteAttribute("iname", MapClientIDToShortName(iname, false));
                }
                if (!_writtenFormVariables && ivalue != null && ivalue.Length > 0) 
                {
                    WriteTextEncodedAttribute("ivalue", ivalue); 
                } 
                if (title != null && title.Length >0)
                { 
                    WriteTextEncodedAttribute("title", title);
                }
                if (multiSelect)
                { 
                    WriteAttribute("multiple", "true");
                } 
                Write(">"); 
            }
        } 

        /// 
        public virtual void RenderEndSelect(bool breakAfter)
        { 
            if (!AnalyzeMode)
            { 
                WriteEndTag("select"); 
                if (breakAfter && !Device.RendersBreaksAfterWmlInput)
                { 
                    PendingBreak = true;
                }
            }
        } 

        ///  
        public virtual void RenderSelectOption(String text) 
        {
            if (!AnalyzeMode) 
            {
                WriteFullBeginTag("option");
                WriteEncodedText(text);
                WriteEndTag("option"); 
            }
        } 
 
        /// 
        public virtual void RenderSelectOption(String text, String value) 
        {
            if (!AnalyzeMode)
            {
                WriteBeginTag("option"); 
                WriteAttribute("value", value, true);
                Write(">"); 
                WriteEncodedText(text); 
                WriteEndTag("option");
            } 
        }

        /// 
        public virtual void BeginCustomMarkup() 
        {
            if (!AnalyzeMode) 
            { 
                EnsureLayout();
            } 
        }

        /// 
        public virtual void EndCustomMarkup() 
        {
        } 
 
        /// 
        public void AddFormVariable(String clientID, String value, bool generateRandomID) 
        {
            // On first (analyze) pass, form variables are added to
            // an array. On second pass, they are rendered. This ensures
            // that only visible controls generate variables. 

            if (AnalyzeMode) 
            { 
                if (_formVariables == null)
                { 
                    _formVariables = new ListDictionary();
                }

                // Map the client ID to a short name. See 
                // MapClientIDToShortName for details.
                _formVariables[MapClientIDToShortName(clientID, generateRandomID)] = value; 
            } 
        }
 
        // Call to reset formatting state before outputting custom stuff.

        /// 
        public virtual void ResetFormattingState() 
        {
            if (!AnalyzeMode) 
            { 
                CloseCharacterFormat();
            } 
        }

        /// 
        public virtual void RenderExtraCards() 
        {
            RenderPostBackCards(); 
        } 

        ///  
        public virtual bool IsValidSoftkeyLabel(String label)
        {
            return label != null &&
                   label.Length > 0 && 
                   label.Length <= Device.MaximumSoftkeyLabelLength;
        } 
 
        /// 
        public virtual void RenderGoAction(String target, 
                                           String argument,
                                           WmlPostFieldType postBackType,
                                           bool includeVariables)
        { 

            WriteBeginTag("go"); 
            Write(" href=\""); 

            IDictionary postBackVariables = null; 
            if (includeVariables)
            {
                postBackVariables = ((WmlFormAdapter)CurrentForm.Adapter).CalculatePostBackVariables();
                if (postBackVariables == null || postBackVariables.Count == 0) 
                {
                    includeVariables = false; 
                } 
            }
 
            bool externalSubmit;
            if (postBackType == WmlPostFieldType.Submit)
            {
                externalSubmit = CurrentForm.Action.Length > 0; 
                postBackType = WmlPostFieldType.Normal;
            } 
            else 
            {
                externalSubmit = false; 
            }

            if (target != null && !externalSubmit && UsePostBackCard(includeVariables))
            { 
                _writtenPostBackType[includeVariables ? 0 : 1] = true;
 
                // If using postback cards, render a go action to the given 
                // postback card, along with setvars setting the target and
                // argument. 

                Write("#");
                Write(includeVariables ? _postBackWithVarsCardId : _postBackWithoutVarsCardId);
                Write("\">"); 
                WriteBeginTag("setvar");
                WriteAttribute("name", _postBackEventTargetVarName); 
                WriteAttribute("value", target); 
                Write("/>");
                WriteBeginTag("setvar"); 
                WriteAttribute("name", _postBackEventArgumentVarName);
                Write(" value=\"");
                if (argument != null)
                { 
                    if (postBackType == WmlPostFieldType.Variable)
                    { 
                        Write("$("); 
                        Write(argument);
                        Write(")"); 
                    }
                    else
                    {
                        WriteEncodedText(argument); 
                    }
                } 
                Write("\"/>"); 
            }
            else 
            {
                // This is the real postback.

                bool encode = false; 
                String url = CalculateFormPostBackUrl(externalSubmit, ref encode);
                FormMethod method = CurrentForm.Method; 
                String queryString = CalculateFormQueryString(); 

                if (encode) 
                {
                    WriteEncodedUrl(url);
                }
                else 
                {
                    Write(url); 
                } 

                if(externalSubmit && queryString != null && queryString.Length > 0) 
                {
                    if(Device.RequiresUniqueFilePathSuffix)
                    {
                        int loc = queryString.IndexOf('&'); 
                        if(loc != -1)
                        { 
                            queryString = queryString.Substring(0, loc); 
                        }
                    } 
                    else
                    {
                        queryString = null;
                    } 
                }
 
                // Add any query string. 
                if (queryString != null && queryString.Length > 0)
                { 
                    if(externalSubmit && (url.IndexOf('?') != -1))
                    {
                        Write("&");
                    } 
                    else
                    { 
                        Write("?"); 
                    }
                    if (queryString.IndexOf('$') != -1) 
                    {
                        queryString = queryString.Replace("$", "$$");
                    }
                    if(Page.Adapter.PersistCookielessData && Device.CanRenderOneventAndPrevElementsTogether) 
                    {
                        queryString = ReplaceFormsCookieWithVariable(queryString); 
                    } 
                    base.WriteEncodedText(queryString);
                } 
                Write("\"");

                // Method defaults to get in WML, so write it if it's not.
                if (method == FormMethod.Post) 
                {
                    WriteAttribute("method", "post"); 
                } 
                Write(">");
 
                // Write the view state as a postfield.
                if (!externalSubmit)
                {
                    String pageState = Page.ClientViewState; 
                    if (pageState != null)
                    { 
                        if (Device.RequiresSpecialViewStateEncoding) 
                        {
                            pageState = 
                                ((WmlPageAdapter) Page.Adapter).EncodeSpecialViewState(pageState);
                        }
                        WritePostField(MobilePage.ViewStateID, pageState);
                    } 

                    // Write the event target. 
                    if (target != null) 
                    {
                        WritePostField(MobilePage.HiddenPostEventSourceId, target); 
                    }
                    else
                    {
                        // Target is null when the action is generated from a postback 
                        // card itself. In this case, set the event target to whatever
                        // the original event target was. 
 
                        WritePostFieldVariable(MobilePage.HiddenPostEventSourceId, _postBackEventTargetVarName);
                    } 

                    // Write the event argument, if valid.

                    if (argument != null) 
                    {
                        WritePostField(MobilePage.HiddenPostEventArgumentId, argument, postBackType); 
                    } 
                }
 
                // Write postfields for form variables, if desired. Commands, for example,
                // include form variables. Links do not.

                if (includeVariables) 
                {
                    if (postBackVariables != null) 
                    { 
                        foreach (DictionaryEntry entry in postBackVariables)
                        { 
                            Control ctl = (Control)entry.Key;
                            Object value = entry.Value;

                            if (value == null) 
                            {
                                // Dynamic value. 
                                // Map the client ID to a short name. See 
                                // MapClientIDToShortName for details.
                                // Note: Because this is called on the second pass, 
                                // we can just pass false as the second parameter
                                WritePostFieldVariable(ctl.UniqueID, MapClientIDToShortName(ctl.ClientID, false));
                            }
                            else 
                            {
                                // Static value. 
                                WritePostField(ctl.UniqueID, (String)value); 
                            }
                        } 
                    }
                }

                // Always include page hidden variables. 

                if (Page.HasHiddenVariables()) 
                { 
                    String hiddenVariablePrefix = MobilePage.HiddenVariablePrefix;
                    foreach (DictionaryEntry entry in Page.HiddenVariables) 
                    {
                        if (entry.Value != null)
                        {
                            WritePostField(hiddenVariablePrefix + (String)entry.Key, (String)entry.Value); 
                        }
                    } 
                } 
            }
 
            WriteEndTag("go");
        }

        // Called after form is completed to analyze. 

        ///  
        protected virtual void PostAnalyzeForm() 
        {
            // Use postback cards if the number of postbacks exceeds the number 
            // of required postback cards.
            //

 
            int numberOfCardsRequired = (_usingPostBackType[0] ? 1 : 0) +
                                        (_usingPostBackType[1] ? 1 : 0); 
            if (_numberOfPostBacks > numberOfCardsRequired) 
            {
                _postBackCardsEfficient = true; 
            }
        }

        // Calculates the URL to output for the postback. Other writers may 
        // override.
 
        ///  
        protected virtual String CalculateFormPostBackUrl(bool externalSubmit, ref bool encode)
        { 
            String url = CurrentForm.Action;
            if (externalSubmit && url.Length > 0)
            {
                url = CurrentForm.ResolveUrl(url); 
                encode = false;
            } 
            else 
            {
                url = Page.RelativeFilePath; 
                encode = true;
            }
            return url;
        } 

        // Calculates the query string to output for the postback. Other 
        // writers may override. 

        internal String ReplaceFormsCookieWithVariable(String queryString) 
        {
            String formsAuthCookieName = FormsAuthentication.FormsCookieName;
            if(!String.IsNullOrEmpty(formsAuthCookieName))
            { 
                int index = queryString.IndexOf(formsAuthCookieName + "=", StringComparison.Ordinal);
                if(index != -1) 
                { 
                    int valueStart = index + formsAuthCookieName.Length + 1;
                    int valueEnd = queryString.IndexOf('&', valueStart); 
                    if(valueStart < queryString.Length)
                    {
                        int length = ((valueEnd != -1) ? valueEnd : queryString.Length) - valueStart;
                        queryString = queryString.Remove(valueStart, length); 
                        queryString = queryString.Insert(valueStart, "$(" + MapClientIDToShortName("__facn", false) + ")");
                    } 
                } 
            }
            return queryString; 
        }

        private String _cachedFormQueryString;
        ///  
        protected virtual String CalculateFormQueryString()
        { 
            if (_cachedFormQueryString != null) 
            {
                return _cachedFormQueryString; 
            }

            String queryString = null;
            if (CurrentForm.Method != FormMethod.Get) 
            {
                queryString = Page.QueryStringText; 
            } 

            if (Device.RequiresUniqueFilePathSuffix) 
            {
                String ufps = Page.UniqueFilePathSuffix;
                if (queryString != null && queryString.Length > 0)
                { 
                    queryString = String.Concat(ufps, "&", queryString);
                } 
                else 
                {
                    queryString = ufps; 
                }
            }

            _cachedFormQueryString = queryString; 
            return queryString;
        } 
 
        internal virtual bool ShouldWriteFormID(Form form)
        { 
            WmlPageAdapter pageAdapter = (WmlPageAdapter)CurrentForm.MobilePage.Adapter;

            return (form.ID != null && pageAdapter.RendersMultipleForms());
        } 

        // Renders the beginning of a form. 
        // 

        ///  
        protected virtual void RenderBeginForm(Form form)
        {
            WmlFormAdapter formAdapter = (WmlFormAdapter)CurrentForm.Adapter;
 
            IDictionary attributes = new ListDictionary();
            if (ShouldWriteFormID(form)) 
            { 
                attributes.Add("id", form.ClientID);
            } 

            String title = form.Title;
            if (title.Length > 0)
            { 
                attributes.Add("title", title);
            } 
 
            // Let the form adapter render the tag. This bit of indirection is
            // somewhat horky, but necessary so that people can subclass adapters 
            // without worrying about the fact that much of the real work is done
            // in the writer.

            formAdapter.RenderCardTag(this, attributes); 

            // Write form variables. 
 
            if ((_formVariables != null && _formVariables.Count > 0) &&
                    (!_provideBackButton || 
                 Device.CanRenderOneventAndPrevElementsTogether))
            {
                _writtenFormVariables = true;
                Write(""); 
                foreach (DictionaryEntry entry in _formVariables)
                { 
                    WriteBeginTag("setvar"); 
                    WriteAttribute("name", (String)entry.Key);
                    WriteTextEncodedAttribute("value", (String)entry.Value); 
                    Write(" />");
                }
                WriteLine("");
 
            }
 
            formAdapter.RenderExtraCardElements(this); 

            if (_provideBackButton) 
            {
                Write(""); 
            }
        } 
 
        // Renders the ending of a form.
 
        /// 
        protected virtual void RenderEndForm()
        {
            CloseParagraph(); 
            WriteEndTag("card");
            WriteLine(); 
        } 

        // Postback cards provide an alternate, space-efficient way of doing 
        // postbacks, on forms that have a lot of postback links. Instead of
        // posting back directly, postback links switch to a postback card, setting
        // variables for event target and argument. The postback card has
        // an onenterforward event that submits the postback. It also has 
        // an onenterbackward, so that it becomes transparent in the card history.
        // (Clicking Back to enter the postback card immediately takes you 
        // to the previous card) 

        ///  
        protected virtual bool UsePostBackCard(bool includeVariables)
        {
            bool b = _postBackCardsEfficient && Device.CanRenderPostBackCards;
            if (b && includeVariables) 
            {
                WmlPageAdapter pageAdapter = (WmlPageAdapter)CurrentForm.MobilePage.Adapter; 
                if (pageAdapter.RendersMultipleForms()) 
                {
                    b = false; 
                }
            }

            return b; 
        }
 
 
        // Renders postback cards.
 
        private void RenderPostBackCards()
        {
            for (int i = 0; i < 2; i++)
            { 
                if (_writtenPostBackType[i])
                { 
                    WriteBeginTag("card"); 
                    WriteAttribute("id", i == 0 ? _postBackWithVarsCardId : _postBackWithoutVarsCardId);
                    WriteLine(">"); 

                    Write("");
                    RenderGoAction(null, _postBackEventArgumentVarName, WmlPostFieldType.Variable, i == 0);
                    WriteLine(""); 

                    WriteLine(""); 
                    WriteLine(""); 
                }
            } 
        }

        /// 
        protected void RenderFormDoEvent(String doType, String arg, WmlPostFieldType postBackType, String text) 
        {
            RenderDoEvent(doType, CurrentForm.UniqueID, arg, postBackType, text, true); 
        } 

        ///  
        protected void RenderDoEvent(String doType, String target, String arg, WmlPostFieldType postBackType, String text, bool includeVariables)
        {
            //EnsureLayout();
            WriteBeginTag("do"); 
            WriteAttribute("type", doType);
            if (text != null && text.Length > 0) 
            { 
                WriteTextEncodedAttribute("label", text);
            } 
            Write(">");
            RenderGoAction(target, arg, postBackType, includeVariables);
            WriteEndTag("do");
        } 

        // Makes sure the writer has rendered a paragraph tag corresponding to 
        // the current layout. 

        ///  
        protected virtual void EnsureLayout()
        {
            WmlLayout layout = CurrentLayout;
 
            if (_currentWrittenLayout != null && layout.Compare(_currentWrittenLayout))
            { 
                // Same layout as before. Only write any pending break. 
                if (PendingBreak)
                { 
                    // Avoid writing tags like  AFTER the 
, instead // writing them before. if (_currentWrittenFormat != null && !CurrentFormat.Compare(_currentWrittenFormat)) { CloseCharacterFormat(); } WriteBreak(); } } else { // Layout has changed. Close current layout, and open new one. CloseParagraph(); OpenParagraph(layout, layout.Align != Alignment.Left, layout.Wrap != Wrapping.Wrap); } PendingBreak = false; } // Makes sure the writer has rendered character formatting tags // corresponding to the current format. /// protected virtual void EnsureFormat() { WmlFormat format = CurrentFormat; if (_currentWrittenFormat == null || !format.Compare(_currentWrittenFormat)) { CloseCharacterFormat(); OpenCharacterFormat(format, format.Bold, format.Italic, format.Size != FontSize.Normal); } } // Opens a paragraph with the given layout. Only the specified // attributes are used. /// protected virtual void OpenParagraph(WmlLayout layout, bool writeAlignment, bool writeWrapping) { if (_currentWrittenLayout == null) { WriteBeginTag("p"); if (writeAlignment) { String alignment; switch (layout.Align) { case Alignment.Right: alignment = "right"; break; case Alignment.Center: alignment = "center"; break; default: alignment = "left"; break; } WriteAttribute("align", alignment); } if (writeWrapping) { WriteAttribute("mode", layout.Wrap == Wrapping.NoWrap ? "nowrap" : "wrap"); } Write(">"); _currentWrittenLayout = layout; } } // Close any open paragraph. /// protected virtual void CloseParagraph() { if (_currentWrittenLayout != null) { CloseCharacterFormat(); WriteEndTag("p"); _currentWrittenLayout = null; } } // Renders tags to enter the given character format. Only the specified // attributes are used. /// protected virtual void OpenCharacterFormat(WmlFormat format, bool writeBold, bool writeItalic, bool writeSize) { if (_currentWrittenFormat == null) { if (writeBold && format.Bold) { WriteFullBeginTag(_boldTag); format.WrittenBold = true; } if (writeItalic && format.Italic) { WriteFullBeginTag(_italicTag); format.WrittenItalic = true; } if (writeSize && format.Size != FontSize.Normal) { WriteFullBeginTag(format.Size == FontSize.Large ? _largeTag : _smallTag); format.WrittenSize = true; } _currentWrittenFormat = format; } } // Close any open character formatting tags. /// protected virtual void CloseCharacterFormat() { if (_currentWrittenFormat != null) { if (_currentWrittenFormat.WrittenSize) { WriteEndTag(_currentWrittenFormat.Size == FontSize.Large ? _largeTag : _smallTag); } if (_currentWrittenFormat.WrittenItalic) { WriteEndTag(_italicTag); } if (_currentWrittenFormat.WrittenBold) { WriteEndTag(_boldTag); } _currentWrittenFormat = null; } } private static readonly char[] _attributeCharacters = new char[] {'"', '&', '<', '>', '$'}; /// public override void WriteAttribute(String attribute, String value, bool encode) { // If in analyze mode, we don't actually have to perform the conversion, because // it's not getting written anyway. // If the value is null, we return without writing anything. This is different // from HtmlTextWriter, which writes the name of the attribute, but no value at all. // A name with no value is illegal in Wml. if (value == null) { return; } if (AnalyzeMode) { encode = false; } if (encode) { // Unlike HTML encoding, we need to replace $ with $$, and <> with < and >. // We can't do this by piggybacking HtmlTextWriter.WriteAttribute, because it // would translate the & in < or > to &. So we more or less copy the // ASP.NET code that does similar encoding. Write(' '); Write(attribute); Write("=\""); int cb = value.Length; int pos = value.IndexOfAny(_attributeCharacters); if (pos == -1) { Write(value); } else { char[] s = value.ToCharArray(); int startPos = 0; while (pos < cb) { if (pos > startPos) { Write(s, startPos, pos - startPos); } char ch = s[pos]; switch (ch) { case '\"': Write("""); break; case '&': Write("&"); break; case '<': Write("<"); break; case '>': Write(">"); break; case '$': Write("$$"); break; } startPos = pos + 1; pos = value.IndexOfAny(_attributeCharacters, startPos); if (pos == -1) { Write(s, startPos, cb - startPos); break; } } } Write('\"'); } else { base.WriteAttribute(attribute, value, encode); } } /// protected void WriteTextEncodedAttribute(String attribute, String value) { WriteAttribute(attribute, value, true); } /// protected Form CurrentForm { get { return _currentForm; } } /// protected MobilePage Page { get { return _page; } } /// protected int NumberOfSoftkeys { get { return _numberOfSoftkeys; } } /// protected virtual void AnalyzePostBack(bool includeVariables, WmlPostFieldType postBackType) { _usingPostBackType[includeVariables ? 0 : 1] = true; if (postBackType != WmlPostFieldType.Submit || CurrentForm.Action.Length == 0) { _numberOfPostBacks++; } } /// public override void WriteEncodedUrl(String url) { if (url == null) { return; } int i = url.IndexOf('?'); if (i != -1) { WriteUrlEncodedString(url.Substring(0, i), false); String s = url.Substring(i); if (s.IndexOf('$') != -1) { s = s.Replace("$", "%24"); } base.WriteEncodedText(s); //WriteEncodedText(url.Substring(i)); } else { WriteUrlEncodedString(url, false); } } /// public override void WriteEncodedText(String text) { if (text == null) { return; } if (text.IndexOf('$') != -1) { text = text.Replace("$", "$$"); } base.WriteEncodedText(text); } /// public void WriteText(String text, bool encodeText) { if (encodeText) { WriteEncodedText(text); } else { WritePlainText(text); } } private void WritePlainText(String text) { if (text == null) { return; } if (text.IndexOf('$') != -1) { text = text.Replace("$", "$$"); } Write(text); } /// protected new void WriteBreak() { Write("
\r\n"); } /// public void WritePostField(String name, String value) { WritePostField(name, value, WmlPostFieldType.Normal); } /// public void WritePostFieldVariable(String name, String arg) { WritePostField(name, arg, WmlPostFieldType.Variable); } /// public void WritePostField(String name, String value, WmlPostFieldType type) { Write(""); } // MapClientIDToShortName provides a unique map of control ClientID properties // to shorter names. In cases where a control has a very long ClientID, a // shorter unique name is used. All references to the client ID on the page // are mapped, resulting in the same postback regardless of mapping. // MapClientIDToShortName also scrambles client IDs that need to be // scrambled for security reasons. /// protected internal String MapClientIDToShortName(String clientID, bool generateRandomID) { if (_alwaysScrambleClientIDs) { generateRandomID = true; } if (_controlShortNames != null) { String lookup = (String)_controlShortNames[clientID]; if (lookup != null) { return lookup; } } if (!generateRandomID) { bool shortID = clientID.Length < _maxShortNameLength; // Map names with underscores and conflicting names regardless of length. bool goodID = !HasUnnamedControlId(clientID) && !NameConflicts(clientID); if (shortID && goodID) { return clientID; } } if (_controlShortNames == null) { _controlShortNames = new ListDictionary(); } String shortName; if (generateRandomID) { shortName = GetRandomID(5); } else { shortName = String.Empty; } shortName = String.Concat(_shortNamePrefix, shortName, _controlShortNames.Count.ToString(CultureInfo.InvariantCulture)); _controlShortNames[clientID] = shortName; return shortName; } // VSWhidbey 280485: We used to check '_' for default control id. But // VSWhidbey 188477 removed the '_', so here it checks "ctl" with id // separator (for naming container case) instead. private bool HasUnnamedControlId(string clientID) { const string unnamedIdPrefix = "ctl"; if (clientID.StartsWith(unnamedIdPrefix, StringComparison.Ordinal)) { return true; } string unnamedIdPrefixWithIdSeparator = Page.IdSeparator + unnamedIdPrefix; int unnamedIdPrefixLength = unnamedIdPrefix.Length; if (clientID.Length > unnamedIdPrefixLength && clientID.IndexOf(unnamedIdPrefixWithIdSeparator, unnamedIdPrefixLength, StringComparison.Ordinal) != -1) { return true; } return false; } private String GetRandomID(int length) { Byte[] randomBytes = new Byte[length]; _random.NextBytes(randomBytes); char[] randomChars = new char[length]; for (int i = 0; i < length; i++) { randomChars[i] = (char)((((int)randomBytes[i]) % 26) + 'a'); } return new String(randomChars); } private bool NameConflicts(String name) { if (name == null) { return false; } Debug.Assert(_postBackEventTargetVarName.ToLower(CultureInfo.InvariantCulture) == _postBackEventTargetVarName && _postBackEventArgumentVarName.ToLower(CultureInfo.InvariantCulture) == _postBackEventArgumentVarName && _shortNamePrefix.ToLower(CultureInfo.InvariantCulture) == _shortNamePrefix); name = name.ToLower(CultureInfo.InvariantCulture); return name == _postBackEventTargetVarName || name == _postBackEventArgumentVarName || name.StartsWith(_shortNamePrefix, StringComparison.Ordinal); } private static readonly WmlLayout _defaultLayout = new WmlLayout(Alignment.Left, Wrapping.Wrap); /// protected virtual WmlLayout DefaultLayout { get { return _defaultLayout; } } private WmlLayout CurrentLayout { get { if (_layoutStack.Count > 0) { return (WmlLayout)_layoutStack.Peek(); } else { return DefaultLayout; } } } /// protected bool PendingBreak { get { return _pendingBreak; } set { _pendingBreak = value; } } private static readonly WmlFormat _defaultFormat = new WmlFormat(false, false, FontSize.Normal); /// protected virtual WmlFormat DefaultFormat { get { return _defaultFormat; } } private WmlFormat CurrentFormat { get { if (_formatStack.Count > 0) { return (WmlFormat)_formatStack.Peek(); } else { return DefaultFormat; } } } private bool _requiresNoSoftkeyLabels = false; private bool _haveRequiresNoSoftkeyLabels = false; private bool RequiresNoSoftkeyLabels() { if (!_haveRequiresNoSoftkeyLabels) { String RequiresNoSoftkeyLabelsString = Device["requiresNoSoftkeyLabels"]; if (RequiresNoSoftkeyLabelsString == null) { _requiresNoSoftkeyLabels = false; } else { _requiresNoSoftkeyLabels = Convert.ToBoolean(RequiresNoSoftkeyLabelsString, CultureInfo.InvariantCulture); } _haveRequiresNoSoftkeyLabels = true; } return _requiresNoSoftkeyLabels; } /// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] protected class WmlLayout { private Wrapping _wrap; private Alignment _align; /// public WmlLayout(Style style, WmlLayout currentLayout) { Alignment align = (Alignment)style[Style.AlignmentKey, true]; Align = (align != Alignment.NotSet) ? align : currentLayout.Align; Wrapping wrap = (Wrapping)style[Style.WrappingKey , true]; Wrap = (wrap != Wrapping.NotSet) ? wrap : currentLayout.Wrap; } /// public WmlLayout(Alignment alignment, Wrapping wrapping) { Align = alignment; Wrap = wrapping; } /// public Wrapping Wrap { get { return _wrap; } set { _wrap = value; } } /// public Alignment Align { get { return _align; } set { _align = value; } } /// public virtual bool Compare(WmlLayout layout) { return Wrap == layout.Wrap && Align == layout.Align; } } /// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] protected class WmlFormat { private bool _bold; private bool _italic; private FontSize _size; private bool _writtenBold = false; private bool _writtenItalic = false; private bool _writtenSize = false; /// public WmlFormat(Style style, WmlFormat currentFormat) { BooleanOption bold = (BooleanOption)style[Style.BoldKey, true]; Bold = (bold != BooleanOption.NotSet) ? bold == BooleanOption.True : currentFormat.Bold; BooleanOption italic = (BooleanOption)style[Style.ItalicKey, true]; Italic = (italic != BooleanOption.NotSet) ? italic == BooleanOption.True : currentFormat.Italic; FontSize fontSize = (FontSize)style[Style.FontSizeKey, true]; Size = (fontSize != FontSize.NotSet) ? fontSize : currentFormat.Size; } /// public WmlFormat(bool bold, bool italic, FontSize size) { Bold = bold; Italic = italic; Size = size; } /// public bool Bold { get { return _bold; } set { _bold = value; } } /// public bool Italic { get { return _italic; } set { _italic = value; } } /// public FontSize Size { get { return _size; } set { _size = value; } } /// public bool WrittenBold { get { return _writtenBold; } set { _writtenBold = value; } } /// public bool WrittenItalic { get { return _writtenItalic; } set { _writtenItalic = value; } } /// public bool WrittenSize { get { return _writtenSize; } set { _writtenSize = value; } } /// public virtual bool Compare(WmlFormat format) { return Bold == format.Bold && Italic == format.Italic && Size == format.Size; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Specialized; using System.Globalization; using System.IO; using System.Web.Mobile; using System.Web.UI.MobileControls; using System.Text.RegularExpressions; using System.Diagnostics; using System.Web.Security; using System.Security.Permissions; using SR=System.Web.UI.MobileControls.Adapters.SR; #if COMPILING_FOR_SHIPPED_SOURCE using Adapters=System.Web.UI.MobileControls.ShippedAdapterSource; namespace System.Web.UI.MobileControls.ShippedAdapterSource #else using Adapters=System.Web.UI.MobileControls.Adapters; namespace System.Web.UI.MobileControls.Adapters #endif { /* * WmlMobileTextWriter class. * * Copyright (c) 2000 Microsoft Corporation */ /// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")] public class WmlMobileTextWriter : MobileTextWriter { private TextWriter _realInnerWriter; private EmptyTextWriter _analyzeWriter; private bool _analyzeMode = false; private MobilePage _page; private Form _currentForm; private bool[] _usingPostBackType = new bool[] { false, false }; private bool[] _writtenPostBackType = new bool[] { false, false }; private int _numberOfPostBacks; private bool _postBackCardsEfficient = false; private IDictionary _formVariables = null; private IDictionary _controlShortNames = null; private Stack _layoutStack = new Stack(); private Stack _formatStack = new Stack(); private WmlLayout _currentWrittenLayout = null; private WmlFormat _currentWrittenFormat = null; private bool _pendingBreak = false; private bool _inAnchor = false; private int _numberOfSoftkeys; private bool _provideBackButton = false; private bool _writtenFormVariables = false; private bool _alwaysScrambleClientIDs = false; private const String _largeTag = "big"; private const String _smallTag = "small"; private const String _boldTag = "b"; private const String _italicTag = "i"; internal const String _postBackCardPrefix = "__pbc"; private const String _postBackWithVarsCardId = "__pbc1"; private const String _postBackWithoutVarsCardId = "__pbc2"; internal const String _postBackEventTargetVarName = "mcsvt"; internal const String _postBackEventArgumentVarName = "mcsva"; private const String _shortNamePrefix = "mcsv"; private const int _maxShortNameLength = 16; private static Random _random = new Random(); /// public WmlMobileTextWriter(TextWriter writer, MobileCapabilities device, MobilePage page) : base(writer, device) { _realInnerWriter = writer; _page = page; _numberOfSoftkeys = Device.NumberOfSoftkeys; if (_numberOfSoftkeys > 2) { _numberOfSoftkeys = 2; } // For phones that don't have a back button, assign a softkey. if (_numberOfSoftkeys == 2 && !Device.HasBackButton) { _numberOfSoftkeys = 1; _provideBackButton = true; _alwaysScrambleClientIDs = _provideBackButton && !device.CanRenderOneventAndPrevElementsTogether; } } // AnalyzeMode is set to true during first analysis pass of rendering. /// public bool AnalyzeMode { get { return _analyzeMode; } set { _analyzeMode = value; if (value) { _analyzeWriter = new EmptyTextWriter(); InnerWriter = _analyzeWriter; } else { InnerWriter = _realInnerWriter; } } } internal bool HasFormVariables { get { return _writtenFormVariables; } } /// public override void EnterLayout(Style style) { if (AnalyzeMode) { return; } WmlLayout newLayout = new WmlLayout(style, CurrentLayout); _layoutStack.Push(newLayout); } /// public override void ExitLayout(Style style, bool breakAfter) { if (!AnalyzeMode) { if (breakAfter) { PendingBreak = true; } _layoutStack.Pop(); } } /// public override void EnterFormat(Style style) { if (AnalyzeMode) { return; } WmlFormat newFormat = new WmlFormat(style, CurrentFormat); _formatStack.Push(newFormat); } /// public override void ExitFormat(Style style) { if (AnalyzeMode) { return; } _formatStack.Pop(); } /// public virtual void BeginForm(Form form) { _cachedFormQueryString = null; _currentForm = form; _writtenFormVariables = false; // To keep track of postbacks which submit form variables, // and postbacks that don't. Used for postback cards // (see UsePostBackCards) _usingPostBackType[0] = _usingPostBackType[1] = false; if (AnalyzeMode) { _numberOfPostBacks = 0; _postBackCardsEfficient = false; _controlShortNames = null; } else { PendingBreak = false; _currentWrittenLayout = null; _currentWrittenFormat = null; RenderBeginForm(form); } } /// public virtual void EndForm() { if (AnalyzeMode) { // Analyze form when done. PostAnalyzeForm(); } else { RenderEndForm(); } } // Single parameter - used for rendering ordinary inline text // (with encoding but without breaks). /// public void RenderText(String text) { RenderText(text, false, true); } // Two parameters - used for rendering encoded text with or without breaks) /// public void RenderText(String text, bool breakAfter) { RenderText(text, breakAfter, true); } /// public virtual void RenderText(String text, bool breakAfter, bool encodeText) { if (!AnalyzeMode) { EnsureLayout(); // Don't use formatting tags inside anchor. if (!_inAnchor) { EnsureFormat(); } WriteText(text, encodeText); if (breakAfter) { PendingBreak = true; } } } // Escape '&' in XML if it hasn't been internal String EscapeAmpersand(String url) { const char ampersand = '&'; const String ampEscaped = "amp;"; if (url == null) { return null; } int ampPos = url.IndexOf(ampersand); while (ampPos != -1) { if (url.Length - ampPos <= ampEscaped.Length || url.Substring(ampPos + 1, ampEscaped.Length) != ampEscaped) { url = url.Insert(ampPos + 1, ampEscaped); } ampPos = url.IndexOf(ampersand, ampPos + ampEscaped.Length + 1); } return url; } /// public virtual void RenderBeginHyperlink(String targetUrl, bool encodeUrl, String softkeyLabel, bool implicitSoftkeyLabel, bool mapToSoftkey) { if (!AnalyzeMode) { EnsureLayout(); EnsureFormat(); WriteBeginTag("a"); Write(" href=\""); if (encodeUrl) { WriteEncodedUrl(targetUrl); } else { Write(EscapeAmpersand(targetUrl)); } Write("\""); if (softkeyLabel != null && softkeyLabel.Length > 0 && !RequiresNoSoftkeyLabels()) { WriteTextEncodedAttribute("title", softkeyLabel); } Write(">"); _inAnchor = true; } } /// public virtual void RenderEndHyperlink(bool breakAfter) { if (!AnalyzeMode) { WriteEndTag("a"); if (breakAfter) { PendingBreak = true; } _inAnchor = false; } } /// public virtual void RenderTextBox(String id, String value, String format, String title, bool password, int size, int maxLength, bool generateRandomID, bool breakAfter) { if (!AnalyzeMode) { // Input tags cannot appear inside character formatting tags, // so close any character formatting. CloseCharacterFormat(); // Certain devices always render a break before a . If // we're on such a device, cancel any pending breaks so as not // to get an extra line of whitespace. if (Device.RendersBreakBeforeWmlSelectAndInput) { PendingBreak = false; } EnsureLayout(); WriteBeginTag("select"); if (name != null && name.Length > 0) { // Map the client ID to a short name. See // MapClientIDToShortName for details. WriteAttribute("name", MapClientIDToShortName(name, false)); } if (iname != null && iname.Length > 0) { // Map the client ID to a short name. See // MapClientIDToShortName for details. WriteAttribute("iname", MapClientIDToShortName(iname, false)); } if (!_writtenFormVariables && ivalue != null && ivalue.Length > 0) { WriteTextEncodedAttribute("ivalue", ivalue); } if (title != null && title.Length >0) { WriteTextEncodedAttribute("title", title); } if (multiSelect) { WriteAttribute("multiple", "true"); } Write(">"); } } /// public virtual void RenderEndSelect(bool breakAfter) { if (!AnalyzeMode) { WriteEndTag("select"); if (breakAfter && !Device.RendersBreaksAfterWmlInput) { PendingBreak = true; } } } /// public virtual void RenderSelectOption(String text) { if (!AnalyzeMode) { WriteFullBeginTag("option"); WriteEncodedText(text); WriteEndTag("option"); } } /// public virtual void RenderSelectOption(String text, String value) { if (!AnalyzeMode) { WriteBeginTag("option"); WriteAttribute("value", value, true); Write(">"); WriteEncodedText(text); WriteEndTag("option"); } } /// public virtual void BeginCustomMarkup() { if (!AnalyzeMode) { EnsureLayout(); } } /// public virtual void EndCustomMarkup() { } /// public void AddFormVariable(String clientID, String value, bool generateRandomID) { // On first (analyze) pass, form variables are added to // an array. On second pass, they are rendered. This ensures // that only visible controls generate variables. if (AnalyzeMode) { if (_formVariables == null) { _formVariables = new ListDictionary(); } // Map the client ID to a short name. See // MapClientIDToShortName for details. _formVariables[MapClientIDToShortName(clientID, generateRandomID)] = value; } } // Call to reset formatting state before outputting custom stuff. /// public virtual void ResetFormattingState() { if (!AnalyzeMode) { CloseCharacterFormat(); } } /// public virtual void RenderExtraCards() { RenderPostBackCards(); } /// public virtual bool IsValidSoftkeyLabel(String label) { return label != null && label.Length > 0 && label.Length <= Device.MaximumSoftkeyLabelLength; } /// public virtual void RenderGoAction(String target, String argument, WmlPostFieldType postBackType, bool includeVariables) { WriteBeginTag("go"); Write(" href=\""); IDictionary postBackVariables = null; if (includeVariables) { postBackVariables = ((WmlFormAdapter)CurrentForm.Adapter).CalculatePostBackVariables(); if (postBackVariables == null || postBackVariables.Count == 0) { includeVariables = false; } } bool externalSubmit; if (postBackType == WmlPostFieldType.Submit) { externalSubmit = CurrentForm.Action.Length > 0; postBackType = WmlPostFieldType.Normal; } else { externalSubmit = false; } if (target != null && !externalSubmit && UsePostBackCard(includeVariables)) { _writtenPostBackType[includeVariables ? 0 : 1] = true; // If using postback cards, render a go action to the given // postback card, along with setvars setting the target and // argument. Write("#"); Write(includeVariables ? _postBackWithVarsCardId : _postBackWithoutVarsCardId); Write("\">"); WriteBeginTag("setvar"); WriteAttribute("name", _postBackEventTargetVarName); WriteAttribute("value", target); Write("/>"); WriteBeginTag("setvar"); WriteAttribute("name", _postBackEventArgumentVarName); Write(" value=\""); if (argument != null) { if (postBackType == WmlPostFieldType.Variable) { Write("$("); Write(argument); Write(")"); } else { WriteEncodedText(argument); } } Write("\"/>"); } else { // This is the real postback. bool encode = false; String url = CalculateFormPostBackUrl(externalSubmit, ref encode); FormMethod method = CurrentForm.Method; String queryString = CalculateFormQueryString(); if (encode) { WriteEncodedUrl(url); } else { Write(url); } if(externalSubmit && queryString != null && queryString.Length > 0) { if(Device.RequiresUniqueFilePathSuffix) { int loc = queryString.IndexOf('&'); if(loc != -1) { queryString = queryString.Substring(0, loc); } } else { queryString = null; } } // Add any query string. if (queryString != null && queryString.Length > 0) { if(externalSubmit && (url.IndexOf('?') != -1)) { Write("&"); } else { Write("?"); } if (queryString.IndexOf('$') != -1) { queryString = queryString.Replace("$", "$$"); } if(Page.Adapter.PersistCookielessData && Device.CanRenderOneventAndPrevElementsTogether) { queryString = ReplaceFormsCookieWithVariable(queryString); } base.WriteEncodedText(queryString); } Write("\""); // Method defaults to get in WML, so write it if it's not. if (method == FormMethod.Post) { WriteAttribute("method", "post"); } Write(">"); // Write the view state as a postfield. if (!externalSubmit) { String pageState = Page.ClientViewState; if (pageState != null) { if (Device.RequiresSpecialViewStateEncoding) { pageState = ((WmlPageAdapter) Page.Adapter).EncodeSpecialViewState(pageState); } WritePostField(MobilePage.ViewStateID, pageState); } // Write the event target. if (target != null) { WritePostField(MobilePage.HiddenPostEventSourceId, target); } else { // Target is null when the action is generated from a postback // card itself. In this case, set the event target to whatever // the original event target was. WritePostFieldVariable(MobilePage.HiddenPostEventSourceId, _postBackEventTargetVarName); } // Write the event argument, if valid. if (argument != null) { WritePostField(MobilePage.HiddenPostEventArgumentId, argument, postBackType); } } // Write postfields for form variables, if desired. Commands, for example, // include form variables. Links do not. if (includeVariables) { if (postBackVariables != null) { foreach (DictionaryEntry entry in postBackVariables) { Control ctl = (Control)entry.Key; Object value = entry.Value; if (value == null) { // Dynamic value. // Map the client ID to a short name. See // MapClientIDToShortName for details. // Note: Because this is called on the second pass, // we can just pass false as the second parameter WritePostFieldVariable(ctl.UniqueID, MapClientIDToShortName(ctl.ClientID, false)); } else { // Static value. WritePostField(ctl.UniqueID, (String)value); } } } } // Always include page hidden variables. if (Page.HasHiddenVariables()) { String hiddenVariablePrefix = MobilePage.HiddenVariablePrefix; foreach (DictionaryEntry entry in Page.HiddenVariables) { if (entry.Value != null) { WritePostField(hiddenVariablePrefix + (String)entry.Key, (String)entry.Value); } } } } WriteEndTag("go"); } // Called after form is completed to analyze. /// protected virtual void PostAnalyzeForm() { // Use postback cards if the number of postbacks exceeds the number // of required postback cards. // int numberOfCardsRequired = (_usingPostBackType[0] ? 1 : 0) + (_usingPostBackType[1] ? 1 : 0); if (_numberOfPostBacks > numberOfCardsRequired) { _postBackCardsEfficient = true; } } // Calculates the URL to output for the postback. Other writers may // override. /// protected virtual String CalculateFormPostBackUrl(bool externalSubmit, ref bool encode) { String url = CurrentForm.Action; if (externalSubmit && url.Length > 0) { url = CurrentForm.ResolveUrl(url); encode = false; } else { url = Page.RelativeFilePath; encode = true; } return url; } // Calculates the query string to output for the postback. Other // writers may override. internal String ReplaceFormsCookieWithVariable(String queryString) { String formsAuthCookieName = FormsAuthentication.FormsCookieName; if(!String.IsNullOrEmpty(formsAuthCookieName)) { int index = queryString.IndexOf(formsAuthCookieName + "=", StringComparison.Ordinal); if(index != -1) { int valueStart = index + formsAuthCookieName.Length + 1; int valueEnd = queryString.IndexOf('&', valueStart); if(valueStart < queryString.Length) { int length = ((valueEnd != -1) ? valueEnd : queryString.Length) - valueStart; queryString = queryString.Remove(valueStart, length); queryString = queryString.Insert(valueStart, "$(" + MapClientIDToShortName("__facn", false) + ")"); } } } return queryString; } private String _cachedFormQueryString; /// protected virtual String CalculateFormQueryString() { if (_cachedFormQueryString != null) { return _cachedFormQueryString; } String queryString = null; if (CurrentForm.Method != FormMethod.Get) { queryString = Page.QueryStringText; } if (Device.RequiresUniqueFilePathSuffix) { String ufps = Page.UniqueFilePathSuffix; if (queryString != null && queryString.Length > 0) { queryString = String.Concat(ufps, "&", queryString); } else { queryString = ufps; } } _cachedFormQueryString = queryString; return queryString; } internal virtual bool ShouldWriteFormID(Form form) { WmlPageAdapter pageAdapter = (WmlPageAdapter)CurrentForm.MobilePage.Adapter; return (form.ID != null && pageAdapter.RendersMultipleForms()); } // Renders the beginning of a form. // /// protected virtual void RenderBeginForm(Form form) { WmlFormAdapter formAdapter = (WmlFormAdapter)CurrentForm.Adapter; IDictionary attributes = new ListDictionary(); if (ShouldWriteFormID(form)) { attributes.Add("id", form.ClientID); } String title = form.Title; if (title.Length > 0) { attributes.Add("title", title); } // Let the form adapter render the tag. This bit of indirection is // somewhat horky, but necessary so that people can subclass adapters // without worrying about the fact that much of the real work is done // in the writer. formAdapter.RenderCardTag(this, attributes); // Write form variables. if ((_formVariables != null && _formVariables.Count > 0) && (!_provideBackButton || Device.CanRenderOneventAndPrevElementsTogether)) { _writtenFormVariables = true; Write(""); foreach (DictionaryEntry entry in _formVariables) { WriteBeginTag("setvar"); WriteAttribute("name", (String)entry.Key); WriteTextEncodedAttribute("value", (String)entry.Value); Write(" />"); } WriteLine(""); } formAdapter.RenderExtraCardElements(this); if (_provideBackButton) { Write(""); } } // Renders the ending of a form. /// protected virtual void RenderEndForm() { CloseParagraph(); WriteEndTag("card"); WriteLine(); } // Postback cards provide an alternate, space-efficient way of doing // postbacks, on forms that have a lot of postback links. Instead of // posting back directly, postback links switch to a postback card, setting // variables for event target and argument. The postback card has // an onenterforward event that submits the postback. It also has // an onenterbackward, so that it becomes transparent in the card history. // (Clicking Back to enter the postback card immediately takes you // to the previous card) /// protected virtual bool UsePostBackCard(bool includeVariables) { bool b = _postBackCardsEfficient && Device.CanRenderPostBackCards; if (b && includeVariables) { WmlPageAdapter pageAdapter = (WmlPageAdapter)CurrentForm.MobilePage.Adapter; if (pageAdapter.RendersMultipleForms()) { b = false; } } return b; } // Renders postback cards. private void RenderPostBackCards() { for (int i = 0; i < 2; i++) { if (_writtenPostBackType[i]) { WriteBeginTag("card"); WriteAttribute("id", i == 0 ? _postBackWithVarsCardId : _postBackWithoutVarsCardId); WriteLine(">"); Write(""); RenderGoAction(null, _postBackEventArgumentVarName, WmlPostFieldType.Variable, i == 0); WriteLine(""); WriteLine(""); WriteLine(""); } } } /// protected void RenderFormDoEvent(String doType, String arg, WmlPostFieldType postBackType, String text) { RenderDoEvent(doType, CurrentForm.UniqueID, arg, postBackType, text, true); } /// protected void RenderDoEvent(String doType, String target, String arg, WmlPostFieldType postBackType, String text, bool includeVariables) { //EnsureLayout(); WriteBeginTag("do"); WriteAttribute("type", doType); if (text != null && text.Length > 0) { WriteTextEncodedAttribute("label", text); } Write(">"); RenderGoAction(target, arg, postBackType, includeVariables); WriteEndTag("do"); } // Makes sure the writer has rendered a paragraph tag corresponding to // the current layout. /// protected virtual void EnsureLayout() { WmlLayout layout = CurrentLayout; if (_currentWrittenLayout != null && layout.Compare(_currentWrittenLayout)) { // Same layout as before. Only write any pending break. if (PendingBreak) { // Avoid writing tags like AFTER the
, instead // writing them before. if (_currentWrittenFormat != null && !CurrentFormat.Compare(_currentWrittenFormat)) { CloseCharacterFormat(); } WriteBreak(); } } else { // Layout has changed. Close current layout, and open new one. CloseParagraph(); OpenParagraph(layout, layout.Align != Alignment.Left, layout.Wrap != Wrapping.Wrap); } PendingBreak = false; } // Makes sure the writer has rendered character formatting tags // corresponding to the current format. /// protected virtual void EnsureFormat() { WmlFormat format = CurrentFormat; if (_currentWrittenFormat == null || !format.Compare(_currentWrittenFormat)) { CloseCharacterFormat(); OpenCharacterFormat(format, format.Bold, format.Italic, format.Size != FontSize.Normal); } } // Opens a paragraph with the given layout. Only the specified // attributes are used. /// protected virtual void OpenParagraph(WmlLayout layout, bool writeAlignment, bool writeWrapping) { if (_currentWrittenLayout == null) { WriteBeginTag("p"); if (writeAlignment) { String alignment; switch (layout.Align) { case Alignment.Right: alignment = "right"; break; case Alignment.Center: alignment = "center"; break; default: alignment = "left"; break; } WriteAttribute("align", alignment); } if (writeWrapping) { WriteAttribute("mode", layout.Wrap == Wrapping.NoWrap ? "nowrap" : "wrap"); } Write(">"); _currentWrittenLayout = layout; } } // Close any open paragraph. /// protected virtual void CloseParagraph() { if (_currentWrittenLayout != null) { CloseCharacterFormat(); WriteEndTag("p"); _currentWrittenLayout = null; } } // Renders tags to enter the given character format. Only the specified // attributes are used. /// protected virtual void OpenCharacterFormat(WmlFormat format, bool writeBold, bool writeItalic, bool writeSize) { if (_currentWrittenFormat == null) { if (writeBold && format.Bold) { WriteFullBeginTag(_boldTag); format.WrittenBold = true; } if (writeItalic && format.Italic) { WriteFullBeginTag(_italicTag); format.WrittenItalic = true; } if (writeSize && format.Size != FontSize.Normal) { WriteFullBeginTag(format.Size == FontSize.Large ? _largeTag : _smallTag); format.WrittenSize = true; } _currentWrittenFormat = format; } } // Close any open character formatting tags. /// protected virtual void CloseCharacterFormat() { if (_currentWrittenFormat != null) { if (_currentWrittenFormat.WrittenSize) { WriteEndTag(_currentWrittenFormat.Size == FontSize.Large ? _largeTag : _smallTag); } if (_currentWrittenFormat.WrittenItalic) { WriteEndTag(_italicTag); } if (_currentWrittenFormat.WrittenBold) { WriteEndTag(_boldTag); } _currentWrittenFormat = null; } } private static readonly char[] _attributeCharacters = new char[] {'"', '&', '<', '>', '$'}; /// public override void WriteAttribute(String attribute, String value, bool encode) { // If in analyze mode, we don't actually have to perform the conversion, because // it's not getting written anyway. // If the value is null, we return without writing anything. This is different // from HtmlTextWriter, which writes the name of the attribute, but no value at all. // A name with no value is illegal in Wml. if (value == null) { return; } if (AnalyzeMode) { encode = false; } if (encode) { // Unlike HTML encoding, we need to replace $ with $$, and <> with < and >. // We can't do this by piggybacking HtmlTextWriter.WriteAttribute, because it // would translate the & in < or > to &. So we more or less copy the // ASP.NET code that does similar encoding. Write(' '); Write(attribute); Write("=\""); int cb = value.Length; int pos = value.IndexOfAny(_attributeCharacters); if (pos == -1) { Write(value); } else { char[] s = value.ToCharArray(); int startPos = 0; while (pos < cb) { if (pos > startPos) { Write(s, startPos, pos - startPos); } char ch = s[pos]; switch (ch) { case '\"': Write("""); break; case '&': Write("&"); break; case '<': Write("<"); break; case '>': Write(">"); break; case '$': Write("$$"); break; } startPos = pos + 1; pos = value.IndexOfAny(_attributeCharacters, startPos); if (pos == -1) { Write(s, startPos, cb - startPos); break; } } } Write('\"'); } else { base.WriteAttribute(attribute, value, encode); } } /// protected void WriteTextEncodedAttribute(String attribute, String value) { WriteAttribute(attribute, value, true); } /// protected Form CurrentForm { get { return _currentForm; } } /// protected MobilePage Page { get { return _page; } } /// protected int NumberOfSoftkeys { get { return _numberOfSoftkeys; } } /// protected virtual void AnalyzePostBack(bool includeVariables, WmlPostFieldType postBackType) { _usingPostBackType[includeVariables ? 0 : 1] = true; if (postBackType != WmlPostFieldType.Submit || CurrentForm.Action.Length == 0) { _numberOfPostBacks++; } } /// public override void WriteEncodedUrl(String url) { if (url == null) { return; } int i = url.IndexOf('?'); if (i != -1) { WriteUrlEncodedString(url.Substring(0, i), false); String s = url.Substring(i); if (s.IndexOf('$') != -1) { s = s.Replace("$", "%24"); } base.WriteEncodedText(s); //WriteEncodedText(url.Substring(i)); } else { WriteUrlEncodedString(url, false); } } /// public override void WriteEncodedText(String text) { if (text == null) { return; } if (text.IndexOf('$') != -1) { text = text.Replace("$", "$$"); } base.WriteEncodedText(text); } /// public void WriteText(String text, bool encodeText) { if (encodeText) { WriteEncodedText(text); } else { WritePlainText(text); } } private void WritePlainText(String text) { if (text == null) { return; } if (text.IndexOf('$') != -1) { text = text.Replace("$", "$$"); } Write(text); } /// protected new void WriteBreak() { Write("
\r\n"); } /// public void WritePostField(String name, String value) { WritePostField(name, value, WmlPostFieldType.Normal); } /// public void WritePostFieldVariable(String name, String arg) { WritePostField(name, arg, WmlPostFieldType.Variable); } /// public void WritePostField(String name, String value, WmlPostFieldType type) { Write(""); } // MapClientIDToShortName provides a unique map of control ClientID properties // to shorter names. In cases where a control has a very long ClientID, a // shorter unique name is used. All references to the client ID on the page // are mapped, resulting in the same postback regardless of mapping. // MapClientIDToShortName also scrambles client IDs that need to be // scrambled for security reasons. /// protected internal String MapClientIDToShortName(String clientID, bool generateRandomID) { if (_alwaysScrambleClientIDs) { generateRandomID = true; } if (_controlShortNames != null) { String lookup = (String)_controlShortNames[clientID]; if (lookup != null) { return lookup; } } if (!generateRandomID) { bool shortID = clientID.Length < _maxShortNameLength; // Map names with underscores and conflicting names regardless of length. bool goodID = !HasUnnamedControlId(clientID) && !NameConflicts(clientID); if (shortID && goodID) { return clientID; } } if (_controlShortNames == null) { _controlShortNames = new ListDictionary(); } String shortName; if (generateRandomID) { shortName = GetRandomID(5); } else { shortName = String.Empty; } shortName = String.Concat(_shortNamePrefix, shortName, _controlShortNames.Count.ToString(CultureInfo.InvariantCulture)); _controlShortNames[clientID] = shortName; return shortName; } // VSWhidbey 280485: We used to check '_' for default control id. But // VSWhidbey 188477 removed the '_', so here it checks "ctl" with id // separator (for naming container case) instead. private bool HasUnnamedControlId(string clientID) { const string unnamedIdPrefix = "ctl"; if (clientID.StartsWith(unnamedIdPrefix, StringComparison.Ordinal)) { return true; } string unnamedIdPrefixWithIdSeparator = Page.IdSeparator + unnamedIdPrefix; int unnamedIdPrefixLength = unnamedIdPrefix.Length; if (clientID.Length > unnamedIdPrefixLength && clientID.IndexOf(unnamedIdPrefixWithIdSeparator, unnamedIdPrefixLength, StringComparison.Ordinal) != -1) { return true; } return false; } private String GetRandomID(int length) { Byte[] randomBytes = new Byte[length]; _random.NextBytes(randomBytes); char[] randomChars = new char[length]; for (int i = 0; i < length; i++) { randomChars[i] = (char)((((int)randomBytes[i]) % 26) + 'a'); } return new String(randomChars); } private bool NameConflicts(String name) { if (name == null) { return false; } Debug.Assert(_postBackEventTargetVarName.ToLower(CultureInfo.InvariantCulture) == _postBackEventTargetVarName && _postBackEventArgumentVarName.ToLower(CultureInfo.InvariantCulture) == _postBackEventArgumentVarName && _shortNamePrefix.ToLower(CultureInfo.InvariantCulture) == _shortNamePrefix); name = name.ToLower(CultureInfo.InvariantCulture); return name == _postBackEventTargetVarName || name == _postBackEventArgumentVarName || name.StartsWith(_shortNamePrefix, StringComparison.Ordinal); } private static readonly WmlLayout _defaultLayout = new WmlLayout(Alignment.Left, Wrapping.Wrap); /// protected virtual WmlLayout DefaultLayout { get { return _defaultLayout; } } private WmlLayout CurrentLayout { get { if (_layoutStack.Count > 0) { return (WmlLayout)_layoutStack.Peek(); } else { return DefaultLayout; } } } /// protected bool PendingBreak { get { return _pendingBreak; } set { _pendingBreak = value; } } private static readonly WmlFormat _defaultFormat = new WmlFormat(false, false, FontSize.Normal); /// protected virtual WmlFormat DefaultFormat { get { return _defaultFormat; } } private WmlFormat CurrentFormat { get { if (_formatStack.Count > 0) { return (WmlFormat)_formatStack.Peek(); } else { return DefaultFormat; } } } private bool _requiresNoSoftkeyLabels = false; private bool _haveRequiresNoSoftkeyLabels = false; private bool RequiresNoSoftkeyLabels() { if (!_haveRequiresNoSoftkeyLabels) { String RequiresNoSoftkeyLabelsString = Device["requiresNoSoftkeyLabels"]; if (RequiresNoSoftkeyLabelsString == null) { _requiresNoSoftkeyLabels = false; } else { _requiresNoSoftkeyLabels = Convert.ToBoolean(RequiresNoSoftkeyLabelsString, CultureInfo.InvariantCulture); } _haveRequiresNoSoftkeyLabels = true; } return _requiresNoSoftkeyLabels; } /// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] protected class WmlLayout { private Wrapping _wrap; private Alignment _align; /// public WmlLayout(Style style, WmlLayout currentLayout) { Alignment align = (Alignment)style[Style.AlignmentKey, true]; Align = (align != Alignment.NotSet) ? align : currentLayout.Align; Wrapping wrap = (Wrapping)style[Style.WrappingKey , true]; Wrap = (wrap != Wrapping.NotSet) ? wrap : currentLayout.Wrap; } /// public WmlLayout(Alignment alignment, Wrapping wrapping) { Align = alignment; Wrap = wrapping; } /// public Wrapping Wrap { get { return _wrap; } set { _wrap = value; } } /// public Alignment Align { get { return _align; } set { _align = value; } } /// public virtual bool Compare(WmlLayout layout) { return Wrap == layout.Wrap && Align == layout.Align; } } /// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] protected class WmlFormat { private bool _bold; private bool _italic; private FontSize _size; private bool _writtenBold = false; private bool _writtenItalic = false; private bool _writtenSize = false; /// public WmlFormat(Style style, WmlFormat currentFormat) { BooleanOption bold = (BooleanOption)style[Style.BoldKey, true]; Bold = (bold != BooleanOption.NotSet) ? bold == BooleanOption.True : currentFormat.Bold; BooleanOption italic = (BooleanOption)style[Style.ItalicKey, true]; Italic = (italic != BooleanOption.NotSet) ? italic == BooleanOption.True : currentFormat.Italic; FontSize fontSize = (FontSize)style[Style.FontSizeKey, true]; Size = (fontSize != FontSize.NotSet) ? fontSize : currentFormat.Size; } /// public WmlFormat(bool bold, bool italic, FontSize size) { Bold = bold; Italic = italic; Size = size; } /// public bool Bold { get { return _bold; } set { _bold = value; } } /// public bool Italic { get { return _italic; } set { _italic = value; } } /// public FontSize Size { get { return _size; } set { _size = value; } } /// public bool WrittenBold { get { return _writtenBold; } set { _writtenBold = value; } } /// public bool WrittenItalic { get { return _writtenItalic; } set { _writtenItalic = value; } } /// public bool WrittenSize { get { return _writtenSize; } set { _writtenSize = value; } } /// public virtual bool Compare(WmlFormat format) { return Bold == format.Bold && Italic == format.Italic && Size == format.Size; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK