using System;
using System.Web;
using System.Threading;
using System.Globalization;
using System.IO;
/*
* @page:    Global.asax.cs
* @copy:    ConceptDevelopment.NET
* @created: Jun-04
* @desc:    HttpFilter that processes outbound Html responses to 
*           search and replace 'language identifiers' in English
*           web pages so that the images & links point to French
*           pages (why? it's a DEMO, remember!)
*           Majority of the code is from this page
*           http://authors.aspalliance.com/aspxtreme/sys/Web/HttpResponseClassFilter.aspx
*           which has an HttpFilter example that converts all text
*           on the page to UPPERCASE
*/
namespace HttpFilterDemo {
	/// <remarks>[static] Global</remarks>
	public class Global : System.Web.HttpApplication {

		/// <summary>Constructor</summary>
		public Global() {
			InitializeComponent();
		}	
		
		/// <summary>App Request start</summary>
		protected void Application_BeginRequest(Object sender, EventArgs e) {
            // attach the Filter to each response object
			HttpResponse response = HttpContext.Current.Response;
			
			// In reality, you would want to decide here whether
			// or not you _wanted_ the Filter enabled (for example,
			// English pages don't need it, French pages do)
			if (response.ContentType == "text/html") {
				response.Filter = new LinkPathFilter(response.Filter);
			}

		}
			
		#region Web Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent() {}
		#endregion
	}
	
	
	
    /// <summary>
    /// The purpose of this Filter is to 'find and replace'
    /// language-identifiers in URLs/Links and in Image filenames.
    /// Urls are in the form http://server/lang/page.html 
    /// eg. change http://server/en/page.html to http://server/fr/page.html 
    /// Image names are in the form header_lang_1.gif
    /// eg. change header_e_1.gif to header_f_1.gif
    /// </summary>
    /// <remarks>
    /// Code for this 'demo' couresty of:
    /// http://www.aspalliance.com/aspxtreme/sys/Web/HttpResponseClassFilter.aspx
    /// http://authors.aspalliance.com/aspxtreme/sys/Web/HttpResponseClassFilter.aspx
    /// with ideas from
	/// http://www.aspnetresources.com/articles/HttpFilters.aspx
    /// </remarks>
	public class LinkPathFilter : Stream {
        private Stream _sink;
        private long _position;

        public LinkPathFilter ( Stream sink ) {
            _sink = sink;
        }

        // The following members of Stream must be overriden.
        public override bool CanRead {
            get { return true; }
        }
        
        public override bool CanSeek {
            get { return true; }
        }
        
        public override bool CanWrite {
            get { return true; }
        }
        
        public override long Length {
            get { return 0; }
        }
        
        public override long Position {
            get { return _position; }
            set { _position = value; }
        }
        
        public override long Seek ( long offset, System.IO.SeekOrigin direction ) {
            return _sink.Seek ( offset, direction );
        }
        
        public override void SetLength ( long length ) {
            _sink.SetLength ( length );
        }
        
        public override void Close ( ) {
            _sink.Close ( );
        }

        public override void Flush ( ) {
            _sink.Flush ( );
        }

        public override int Read ( byte [ ] buffer, int offset, int count ) {
            return _sink.Read ( buffer, offset, count );
        }

        // The Write method actually does the filtering.
        public override void Write ( byte [ ] buffer, int offset, int count )  {
      	
            byte [ ] data = new byte [ count ] ;
            Buffer.BlockCopy ( buffer, offset, data, 0, count );
    
            // <LinkPath specific changes to sample code>
            // This may not be pretty, but it works
            byte data1=data[0],data2=data[0],data3=data[0],data4=data[0];
            for ( int i = 0; i < count; i++ ) {
            
         	  if (i > 4){ // once we're far enough in
	         	 data4 = data3;
	         	 data3 = data2;
	         	 data2 = data1;
         	  }
         	  data1 = data[i];
         	  
         	  // test for /en/ pattern
         	  if (data1 == Convert.ToByte('/') ) {
         		 if ( (data4 == Convert.ToByte('/')) && (data3 == Convert.ToByte('e')) && (data2 == Convert.ToByte('n'))){
         			    // change it to /fr/
         			    data [ i-1 ] = Convert.ToByte('r');
         			    data [ i-2 ] = Convert.ToByte('f');
         		 }
         	  }
         	  // test for _e_ pattern
         	  else if (data1 == Convert.ToByte('_' )) {
         		 if ( (data3 == Convert.ToByte('_') ) && (data2 == Convert.ToByte('e') ) ){
                    // change it to _f_ 
                    data [ i-1 ] = Convert.ToByte('k');
         		 }
         	  }
            }
            // </LinkPath specific changes to sample code>
            _sink.Write ( data, 0, count );
        }
        
    } // LinkPathFilter
} // namespace