Update of /cvsroot/magicajax/magicajax/Core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31357/magicajax/Core Modified Files: AjaxCallHelper.cs MagicAjax NET 2.0.csproj MagicAjax.csproj MagicAjaxModule.cs StoredPageInfo.cs Util.cs Added Files: MagicAjaxContext.cs PageFilter.cs Log Message: Major changes to enable MagicAjax for concurrent users. Added: MagicAjaxContext class (containing properties like 'IsAjaxCall') Added: PageFilter.cs (just moved the PageFilter class from MagicAjaxModule.cs) Index: MagicAjax NET 2.0.csproj =================================================================== RCS file: /cvsroot/magicajax/magicajax/Core/MagicAjax NET 2.0.csproj,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** MagicAjax NET 2.0.csproj 20 Nov 2005 15:21:31 -0000 1.7 --- MagicAjax NET 2.0.csproj 23 Nov 2005 15:12:48 -0000 1.8 *************** *** 118,121 **** --- 118,122 ---- <SubType>Code</SubType> </Compile> + <Compile Include="MagicAjaxContext.cs" /> <Compile Include="MagicAjaxException.cs"> <SubType>Code</SubType> *************** *** 124,127 **** --- 125,129 ---- <SubType>Code</SubType> </Compile> + <Compile Include="PageFilter.cs" /> <Compile Include="StoredPageInfo.cs"> <SubType>Code</SubType> Index: Util.cs =================================================================== RCS file: /cvsroot/magicajax/magicajax/Core/Util.cs,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** Util.cs 21 Nov 2005 12:18:36 -0000 1.5 --- Util.cs 23 Nov 2005 15:12:48 -0000 1.6 *************** *** 19,23 **** static public string GetFingerprint(string input) { ! MagicAjax.Configuration.OutputCompareMode compareMode = MagicAjaxModule.Instance.Configuration.PageStore.CompareMode; switch (compareMode) { --- 19,23 ---- static public string GetFingerprint(string input) { ! MagicAjax.Configuration.OutputCompareMode compareMode = MagicAjaxContext.Configuration.PageStore.CompareMode; switch (compareMode) { Index: MagicAjax.csproj =================================================================== RCS file: /cvsroot/magicajax/magicajax/Core/MagicAjax.csproj,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** MagicAjax.csproj 20 Nov 2005 15:21:32 -0000 1.4 --- MagicAjax.csproj 23 Nov 2005 15:12:48 -0000 1.5 *************** *** 105,108 **** --- 105,113 ---- /> <File + RelPath = "MagicAjaxContext.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "MagicAjaxException.cs" SubType = "Code" *************** *** 115,118 **** --- 120,128 ---- /> <File + RelPath = "PageFilter.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "StoredPageInfo.cs" SubType = "Code" --- NEW FILE: MagicAjaxContext.cs --- using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Web.UI; using System.Configuration; using MagicAjax.Configuration; namespace MagicAjax { /// <summary> /// MagicAjaxContext contains all information about the MagicAjax configuration and current request /// </summary> public class MagicAjaxContext { #region Private properties private bool _isAjaxCall = false; private bool _completedAjaxCall = false; private bool _exceptionThrown = false; private bool _isBrowserSupported = false; private StoredPageInfo _storedPageInfo = null; #endregion #region Public properties /// <summary> /// Returns true if request was made from the browser's XmlHttpRequest object /// </summary> public bool IsAjaxCall { get { return _isAjaxCall; } set { _isAjaxCall = value; } } /// <summary> /// True of ajax call was completed /// </summary> public bool CompletedAjaxCall { get { return _completedAjaxCall; } set { _completedAjaxCall = value; } } /// <summary> /// Has an exception been thrown during this callback /// </summary> public bool ExceptionThrown { get { return _exceptionThrown; } set { _exceptionThrown = value; } } /// <summary> /// Returns if this browser is supported by MagicAjax. /// For now (version 0.2) only IE and FireFox are supported. /// </summary> public bool IsBrowserSupported { get { return _isBrowserSupported; } set { _isBrowserSupported = value; } } /// <summary> /// Information about current (stored) page. Only used for Session/Cache store mode. /// </summary> public StoredPageInfo StoredPageInfo { get { return _storedPageInfo; } set { _storedPageInfo = value; } } /// <summary> /// Returns the AjaxCall type, suitable for a switch block. /// </summary> public AjaxCallType AjaxCallType { get { if (IsAjaxCallTimer) return AjaxCallType.Timer; else if (IsAjaxCall) return AjaxCallType.Control; else return AjaxCallType.None; } } /// <summary> /// Determines whether the page is stored or recreated at each AjaxCall. /// </summary> public bool IsPageNoStoreMode { get { return MagicAjaxContext.Configuration.PageStore.Mode == MagicAjax.Configuration.PageStoreMode.NoStore; } } /// <summary> /// Gets the argument string the was sent by the client. /// </summary> public string AjaxCallArgument { get { if (IsAjaxCall) return HttpContext.Current.Request.Form["__EVENTARGUMENT"]; else return null; } } /// <summary> /// Determines whether the AjaxCall occured by the AjaxCallTimer. /// </summary> /// <remarks> /// See the remarks of the SetAjaxCallTimerInterval method. /// </remarks> public bool IsAjaxCallTimer { get { return (HttpContext.Current.Request.Form["__EVENTTARGET"] == "__AJAX_AJAXCALLTIMER"); } } /// <summary> /// Determines if the page is being processed for an AjaxCall. It's more accurate /// than IsAjaxCall because it returns false if the page is being processed /// for Server.Transfer. /// </summary> /// <remarks> /// When the page is being processed for Server.Transfer, the Page's /// IsPostBack property will be false. If this is the case IsAjaxCallForPage /// will return false. /// </remarks> public bool IsAjaxCallForPage(Page page) { return (IsAjaxCall && ((IsPageNoStoreMode && page.IsPostBack) || (!IsPageNoStoreMode && StoredPageInfo.Page == page))); } #endregion #region Public Ctor public MagicAjaxContext() { //store initial settings on first call (per request) if (HttpContext.Current != null) { HttpBrowserCapabilities caps = HttpContext.Current.Request.Browser; if (caps.Browser != null && caps.EcmaScriptVersion.Major >= 1 && caps.W3CDomVersion.Major >= 1) { switch (caps.Browser.ToLower()) { case "ie": _isBrowserSupported = caps.MajorVersion > 5 || (caps.MajorVersion == 5 && caps.MinorVersion >= 5); break; case "gecko": _isBrowserSupported = caps.Type.ToLower().StartsWith("firefox") && caps.MajorVersion >= 1; break; case "firefox": _isBrowserSupported = caps.MajorVersion >= 1; break; //TODO: add support for Opera, Netscape and Safari } } } } #endregion #region Public Static properties public static MagicAjaxContext Current { get { MagicAjaxContext magicAjaxContext = null; if (HttpContext.Current != null) { // get the portal context for the current HTTP request if (HttpContext.Current.Items.Contains("__MAGICAJAXCONTEXT")) { magicAjaxContext = (MagicAjaxContext)HttpContext.Current.Items["__MAGICAJAXCONTEXT"]; } else { // create a new context and add it to the items collection for later retrieval magicAjaxContext = new MagicAjaxContext(); HttpContext.Current.Items.Add("__MAGICAJAXCONTEXT", magicAjaxContext); } } return magicAjaxContext; } } private static MagicAjaxConfiguration _configuration = null; public static MagicAjaxConfiguration Configuration { get { if (_configuration == null) { // Note: there is no need to cache this as singleton, .NET framework does this automatically (only a single instance is created) _configuration = (MagicAjaxConfiguration)ConfigurationSettings.GetConfig("magicAjax"); if (_configuration == null) { _configuration = new MagicAjaxConfiguration(null); } } return _configuration; } } #endregion } } Index: StoredPageInfo.cs =================================================================== RCS file: /cvsroot/magicajax/magicajax/Core/StoredPageInfo.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** StoredPageInfo.cs 14 Nov 2005 18:50:43 -0000 1.2 --- StoredPageInfo.cs 23 Nov 2005 15:12:48 -0000 1.3 *************** *** 11,15 **** private Page _page; private int _ajaxCallsCount; ! private DateTime _lastAccess; public Page Page --- 11,15 ---- private Page _page; private int _ajaxCallsCount; ! private DateTime _lastAccess; public Page Page Index: AjaxCallHelper.cs =================================================================== RCS file: /cvsroot/magicajax/magicajax/Core/AjaxCallHelper.cs,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** AjaxCallHelper.cs 20 Nov 2005 08:47:29 -0000 1.7 --- AjaxCallHelper.cs 23 Nov 2005 15:12:48 -0000 1.8 *************** *** 56,137 **** private AjaxCallHelper() { } ! private static ArrayList _sbWritingLevels; ! private static int _writingLevel; ! ! private static void MergeNextWritingLevelRecursive (int writingLevel) ! { ! int nextLevel = writingLevel + 1; ! if (_sbWritingLevels.Count == nextLevel) ! return; ! ! MergeNextWritingLevelRecursive (nextLevel); ! (_sbWritingLevels[writingLevel] as StringBuilder).Append((_sbWritingLevels[nextLevel] as StringBuilder).ToString()); ! _sbWritingLevels.RemoveAt (nextLevel); ! } ! #endregion ! ! #region Static Properties ! /// <summary> ! /// Returns the AjaxCall type, suitable for a switch block. ! /// </summary> ! public static AjaxCallType AjaxCallType { get { ! if ( IsAjaxCallTimer ) ! return AjaxCallType.Timer; ! else if ( IsAjaxCall ) ! return AjaxCallType.Control; else ! return AjaxCallType.None; } } ! ! /// <summary> ! /// Determines whether an AjaxCall was invoked on the server by the client. ! /// </summary> ! public static bool IsAjaxCall { get { ! return ( HttpContext.Current != null && MagicAjaxModule.Instance.IsAjaxCall ); } ! } ! ! /// <summary> ! /// Determines whether the page is stored or recreated at each AjaxCall. ! /// </summary> ! public static bool IsPageNoStoreMode ! { ! get { return ( HttpContext.Current != null && MagicAjaxModule.Instance.Configuration.PageStore.Mode == Configuration.PageStoreMode.NoStore ); } ! } ! ! /// <summary> ! /// Gets the argument string the was sent by the client. ! /// </summary> ! public static string AjaxCallArgument ! { ! get { ! if ( IsAjaxCall ) ! return MagicAjaxModule.Instance.Form["__EVENTARGUMENT"]; else ! return null; } } ! /// <summary> ! /// Determines whether the AjaxCall occured by the AjaxCallTimer. ! /// </summary> ! /// <remarks> ! /// See the remarks of the SetAjaxCallTimerInterval method. ! /// </remarks> ! public static bool IsAjaxCallTimer { ! get ! { ! return ( MagicAjaxModule.Instance.Form["__EVENTTARGET"] == "__AJAX_AJAXCALLTIMER" ); ! } } /// <summary> --- 56,117 ---- private AjaxCallHelper() { } ! private static ArrayList _sbWritingLevels { get { ! if (HttpContext.Current.Items.Contains("_sbWritingLevels")) ! { ! return (ArrayList)(HttpContext.Current.Items["_sbWritingLevels"]); ! } ! return null; ! } ! set ! { ! if (!HttpContext.Current.Items.Contains("_sbWritingLevels")) ! { ! HttpContext.Current.Items.Add("_sbWritingLevels", value); ! } else ! { ! HttpContext.Current.Items["_sbWritingLevels"] = value; ! } } } ! private static int _writingLevel { get { ! if (HttpContext.Current.Items.Contains("_writingLevel")) ! { ! return (int)(HttpContext.Current.Items["_writingLevel"]); ! } ! return 0; } ! set { ! if (!HttpContext.Current.Items.Contains("_writingLevel")) ! { ! HttpContext.Current.Items.Add("_writingLevel", value); ! } else ! { ! HttpContext.Current.Items["_writingLevel"] = value; ! } } } ! private static void MergeNextWritingLevelRecursive(int writingLevel) { ! int nextLevel = writingLevel + 1; ! if (_sbWritingLevels.Count == nextLevel) ! return; ! ! MergeNextWritingLevelRecursive (nextLevel); ! (_sbWritingLevels[writingLevel] as StringBuilder).Append((_sbWritingLevels[nextLevel] as StringBuilder).ToString()); ! _sbWritingLevels.RemoveAt (nextLevel); } + #endregion + + #region Static Methods /// <summary> *************** *** 144,190 **** } - /// <summary> - /// Included for convenience. - /// </summary> - public static HttpContext Context - { - get - { - return System.Web.HttpContext.Current; - } - } - - /// <summary> - /// Included for convenience. - /// </summary> - public static HttpResponse Response - { - get - { - HttpResponse hr = System.Web.HttpContext.Current.Response; - if (hr == null) - throw new MagicAjaxException("AjaxCallHelper could not access current HttpResponse object"); - - return hr; - } - } - - /// <summary> - /// Included for convenience. - /// </summary> - public static HttpRequest Request - { - get - { - HttpRequest hr = System.Web.HttpContext.Current.Request; - if (hr == null) - throw new MagicAjaxException("AjaxCallHelper could not access current HttpRequest object"); - - return hr; - } - } - #endregion - - #region Static Methods /// <summary> /// Increases the script writing level. --- 124,127 ---- *************** *** 240,259 **** /// <summary> - /// Determines if the page is being processed for an AjaxCall. It's more accurate - /// than IsAjaxCall because it returns false if the page is being processed - /// for Server.Transfer. - /// </summary> - /// <remarks> - /// When the page is being processed for Server.Transfer, the Page's - /// IsPostBack property will be false. If this is the case IsAjaxCallForPage - /// will return false. - /// </remarks> - public static bool IsAjaxCallForPage (Page page) - { - return (AjaxCallHelper.IsAjaxCall && - ( (IsPageNoStoreMode && page.IsPostBack) || (!IsPageNoStoreMode && MagicAjaxModule.Instance.CurrentPageInfo.Page == page) ) ); - } - - /// <summary> /// Obtains a reference to a client-side script function that causes, when invoked, /// the control to raise an AjaxCall event to the server. This method also passes --- 177,180 ---- *************** *** 333,337 **** if (milliSeconds > 0) { ! if ( IsAjaxCall ) Write (String.Format("AJAXCbo.SetIntervalForAjaxCall({0});", milliSeconds)); else --- 254,258 ---- if (milliSeconds > 0) { ! if (MagicAjaxContext.Current.IsAjaxCall) Write (String.Format("AJAXCbo.SetIntervalForAjaxCall({0});", milliSeconds)); else *************** *** 344,348 **** else { ! if ( IsAjaxCall ) Write ("AJAXCbo.ClearIntervalForAjaxCall();"); else --- 265,269 ---- else { ! if (MagicAjaxContext.Current.IsAjaxCall) Write ("AJAXCbo.ClearIntervalForAjaxCall();"); else *************** *** 516,520 **** internal static void Init() { ! HttpResponse hr = AjaxCallHelper.Response; hr.StatusCode = 200; hr.StatusDescription = "OK"; --- 437,441 ---- internal static void Init() { ! HttpResponse hr = HttpContext.Current.Response; hr.StatusCode = 200; hr.StatusDescription = "OK"; *************** *** 539,549 **** WriteEndSignature(); ! HttpResponse hr = AjaxCallHelper.Response; hr.Clear(); MergeNextWritingLevelRecursive (0); hr.Write ((_sbWritingLevels[0] as StringBuilder).ToString()); ! ! MagicAjaxModule.Instance.CompletedAjaxCall = true; hr.Flush(); --- 460,470 ---- WriteEndSignature(); ! HttpResponse hr = HttpContext.Current.Response; hr.Clear(); MergeNextWritingLevelRecursive (0); hr.Write ((_sbWritingLevels[0] as StringBuilder).ToString()); ! ! MagicAjaxContext.Current.CompletedAjaxCall = true; hr.Flush(); --- NEW FILE: PageFilter.cs --- using System; using System.IO; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using System.Web; namespace MagicAjax { /// <summary> /// Used to store and retrieve the html rendering of the page during an AjaxCall /// </summary> internal class PageFilter : Stream { private Stream _responseStream; private Stream _memStream; public PageFilter(Stream _responseStream) { this._responseStream = _responseStream; this._memStream = new MemoryStream(); } public string GetViewStateFieldValue() { //TODO: use regular expression (much faster) #if NET_2_0 string search = "<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\""; #else string search = "<input type=\"hidden\" name=\"__VIEWSTATE\" value=\""; #endif string html = GetHtmlPage(); int si = html.IndexOf(search); if (si == -1) return null; si += search.Length; int ei = html.IndexOf('\"', si); if (ei == -1) return null; return html.Substring(si, ei - si); } #if NET_2_0 /// <summary> /// Look for javascript generated for draggable webparts (IE only), and returns these javascripts. /// </summary> public string GetWebPartManagerScriptValue(string formID) { string html = GetHtmlPage(); // Look for webpartmanager object creation script string searchWPManager = "<script type=\"text\\/javascript\">\\r\\n\\r\\n__wpm = new WebPartManager\\(\\);\\r\\n(?<WPManagerScript>.*?)<\\/script>"; Regex regExWPManager = new Regex(searchWPManager, RegexOptions.Singleline | RegexOptions.Compiled); Match match = regExWPManager.Match(html); // If no webpartmanager script exists in html -> exit if (!match.Success) return null; // Stringbuilder to hold the output script StringBuilder wpmScript = new StringBuilder(); // First look for hidden drag element (if not exists : add this to page) string searchDragElm = "<div id=\"(?<DragElmId>.+?___Drag)\" style=\"display:none.+?><\\/div>"; Regex regExDragElm = new Regex(searchDragElm, RegexOptions.Multiline | RegexOptions.Compiled); Match matchDragElm = regExDragElm.Match(html); if (matchDragElm.Success) { //add this element to the html page, if it didn't exist string elmID = matchDragElm.Groups["DragElmId"].Value; wpmScript.AppendLine(string.Format("if (document.getElementById('{0}') == null)", elmID)); wpmScript.AppendLine(string.Format(" AJAXCbo.AddElementScript('{0}','span','__DragHolder',{1},'null');", formID, AjaxCallHelper.EncodeString(matchDragElm.Value))); } // Now append the WebpartManager script wpmScript.AppendLine(match.Groups["WPManagerScript"].Value); // Now append the webpart menu scripts string searchWPMenus = "<script type=\"text\\/javascript\">\\r\\n(?<MenuScript>var menuWebPart_.*?)<\\/script>"; Regex regExMenuScripts = new Regex(searchWPMenus, RegexOptions.Singleline | RegexOptions.Compiled); MatchCollection matches = regExMenuScripts.Matches(html); //ei for (int i = 0; i < matches.Count; i++) { wpmScript.AppendLine(matches[i].Groups["MenuScript"].Value); } return wpmScript.ToString(); } #endif private string _htmlPage; public string GetHtmlPage() { if (_htmlPage == null) { byte[] buffer = new byte[_memStream.Length]; _memStream.Position = 0; _memStream.Read(buffer, 0, (int)_memStream.Length); _htmlPage = HttpContext.Current.Response.ContentEncoding.GetString(buffer); } return _htmlPage; } #region Stream overrides public override bool CanRead { get { return true; } } public override bool CanSeek { get { return true; } } public override bool CanWrite { get { return true; } } public override void Close() { _responseStream.Close(); } public override void Flush() { _responseStream.Flush(); } public override long Length { get { return _responseStream.Length; } } public override long Position { get { return _responseStream.Position; } set { _responseStream.Position = value; } } public override long Seek(long offset, SeekOrigin origin) { return _responseStream.Seek(offset, origin); } public override void SetLength(long length) { _responseStream.SetLength(length); } public override int Read(byte[] buffer, int offset, int count) { return _responseStream.Read(buffer, offset, count); } public override void Write(byte[] buffer, int offset, int count) { if (MagicAjaxContext.Current.IsAjaxCall) { _memStream.Write(buffer, offset, count); if (MagicAjaxContext.Current.CompletedAjaxCall) _responseStream.Write(buffer, offset, count); } else { _responseStream.Write(buffer, offset, count); } } #endregion } } Index: MagicAjaxModule.cs =================================================================== RCS file: /cvsroot/magicajax/magicajax/Core/MagicAjaxModule.cs,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** MagicAjaxModule.cs 22 Nov 2005 10:37:50 -0000 1.25 --- MagicAjaxModule.cs 23 Nov 2005 15:12:48 -0000 1.26 *************** *** 54,114 **** public class MagicAjaxModule: IHttpModule { - #region Static Properties - private static MagicAjaxModule _instance = null; - - public static MagicAjaxModule Instance - { - get - { - if (_instance == null) [...1121 lines suppressed...] - - public override void Write(byte[] buffer, int offset, int count) - { - if ( AjaxCallHelper.IsAjaxCall ) - { - _memStream.Write (buffer, offset, count); - - if ( MagicAjaxModule.Instance.CompletedAjaxCall ) - _responseStream.Write (buffer, offset, count); - } - else - { - _responseStream.Write (buffer, offset, count); - } - } - #endregion - } } } --- 856,859 ---- |