BlogEngine.Net's contact form fixed for Hotmail users (well, hacked)

by Patrice 11/11/2008 11:10:06 AM

The other day, my wife decided to make a joke on me and used the contact page on this blog to ask funny questions. Yesterday, she was asking about my blog, how it was going, are people interested, do I receive... emails? hmmm, why is she asking all these questions suddenly? Finally the cat went out the bag... She told me about her joke... but I never received any email. Alright, this could be due to a SMTP configuration problem. But BlogEngine.Net "test" email function worked (this is part of the admin page to test SMTP values)... I then tried the contact form myself and I never received any feedback... I tried again by filling the "from" field using a different email and this time it worked... hmm, okay, the difference between my wife (as with my first test) and my second test is hotmail.com. I can even use the contact form using a fake "from" as bla@blablabla.bla and it will work.

This site is hosted on GoDaddy, my lfdx.com emails are hosted on GMail. It's known that to use GMail POP3 you need to use the port 465. But this port is blocked on GoDaddy servers. The solution is to set the SMTP server to relay-hosting.secureserver.net (GoDaddy server, considering that you already have set your MX records to point to googlemail.com). So, where is hotmail.com blocked? Somewhere within GoDaddy infrastructure I suppose. This is not crucial and I don't have time to investigate with GoDaddy.... Let hack the code then. Quicker and funnier!

Since I have compiled BlogEngine myself, it was easy to "debug" and "patch" the code... I opened contact.aspx.cs page and went to SenEmail() method. That's where I decided to hack the "from" field. Here is how... nothing complex.

I replaced this:

mail.From = new MailAddress(txtEmail.Text, txtName.Text);

to:

string email = txtEmail.Text.ToUpperInvariant();//for the String.Replace method
//Hotmail patch for GoDaddy-Hotmail-GMail issue
if (email.EndsWith("HOTMAIL.COM" ))
    email = email.Replace("HOTMAIL.COM", "_REMOVE_hotmail.com");

mail.From = new MailAddress(email, txtName.Text);

This way, I receive hotmail emails and if I need to do a reply, I just have to delete the _REMOVE_ part.

Unfortunately, I don't like the way I hacked BlogEngine.Net code since the next time I will upgrade BlogEngine.Net, this part will be overwritten. But I don't have time to figure a best way for now.... If anyone has one, you are welcome to share your solution!

Live Messenger API Status Icons

by Patrice 10/13/2008 10:43:21 PM

I just finished working on a small task where I wanted to use Live Messenger API in a web page (this allows the user to contact you using Messenger without having Messenger installed on his machine and having your contact set in it).  A friend of mine just did this for his business web site and I found it very useful. I decided to try it myself.

Since my friend has already done this, he guided me directly where I needed to go to learn about the API. After 10 minutes, it was done.  Basically, you just have to paste this (replace 1111111111111 by your user ID):

<a target="_blank" href="http://settings.messenger.live.com/Conversation/IMMe.aspx?
			invitee=1111111111111@apps.messenger.live.com&mkt=en-US">
    <img style="border-style:none;" src="http://messenger.services.live.com/users/1111111111111@
			apps.messenger.live.com/presenceimage?mkt=en-US" />
</a>

...and it returns this series of icons:

, , etc   ....they are small, just 16x16 and not "clean".

So what can I  do? After investigating, I found that I can get the status by two ways (1111111111111 is your user ID):

1- http://messenger.services.live.com/users/1111111111111@apps.messenger.live.com/presenceimage?mkt=en-US

...that will redirect to the status gif image.

2 - http://messenger.services.live.com/users/1111111111111@apps.messenger.live.com/presence?mkt=en-US

...that will return the status information in JSON format.

One thing I didn't want is use JavaScript. Obviously, if that wouldn't have been the case, JSON would have been the best choice here and easily implemented.

So I had to do the job from the server. I was looking for the easiest way so I just called ".../presenceimage?", using HttpWebRequest and just replaced "live.com" link by my server path... easy!

using (WebResponse response = request.GetResponse())
{
    string msnpath = response.ResponseUri.AbsolutePath;
    localImg += msnpath.Substring(msnpath.LastIndexOf("/") + 1);
}

Note that I don't download the image by calling GetResponseStream.

So by replacing the path, I obviously need to have the replacing image on my server. For that, I Googled a bit and found two set of icons that look much better. MSN Crystal Icons and Messenger Icon Pack... Just use your favorite image editor to resize then and/or change the format.

While I was there, I said "Well, why not a custom control?" To implement this I just rendered the a and img elements in a WebControl ... just few lines... look at the code if you are interested...  In the ASPX, it looks like this:

<lfdx:MSNMessenger uid="8a69c004ce9860b4" cssclass="wt" serverimgpath="images/" runat="server" />
  • uid is the Messenger user Id
  • cssclass class applied to a element
  • serverimgpath is the location of your custom images

Download the project here. Note that I have included the "Messenger Icon Pack" that I have resized to 30x30 gif images.

Nothing complex here just a fun project!

 

WebBrowser control... Mono/Gecko update

by Patrice 9/8/2008 9:46:19 AM

Since my last update everything run smoothly on the server. I'm a "Microsoft guy" but I always liked to experiment on Linux. Once a year, since college, I get an old machine, format it and re-install the latest Linux version and after everything is done... nothing... ha ha ha ha. ...but this time though, I had another goal in mind... compile my code with Mono and running it on a Linux box! (I know, I could have use Mono on Windows but, hey, what's the fun?)

So last weekend I undusted my machine, boot it up and reformatted it. This time I've installed openSUSE... The installation went smoothly without any issue.  First, I was curious to see if my code would compile at all using Mono... I have been very surprised to see that it did compile.... except the "interop" part where I use the browser obviously.

Hmmm, alright, it's time to try Gecko to produce my browser "screenshots". That was the easy part... there is still a sample code on the web that is dated '04 and does that. Before modifying my existing application, I compiled the sample code and tried it ... no issue here... except one thing: the browser needs to be "visible"... and that is not good.  That's the same issue I got when I tried IHTMLElementRender::DrawToDC version on Windows... I haven't found a way to hide the window and get the image... it only outputs a black image...

Unfortunately, time is precious and that's all I had to give to it...

See you next year Linux!

WebBrowser control... update

by Patrice 7/2/2008 10:08:49 AM

Just to update you on how my web page thumbnails generator (described in my post my WebBrowser experiment ) goes on...

Since this is used on a server, it , as expected, crashed a couple of times per load test... that's not very useful... I brought a little modification to it...  and it didn't crashed since then.... (note that this is not on production servers)

So the first thing I do is that I load the web page using HttpWebRequest and get its stream from HttpWebResponse.GetResponseStream. Once I get the stream I create a new WebBrowser but instead of opening the page from a URL (with WebBrowser.Navigate), I load the stream that I got from HttpWebResponse into my  WebBrowser's DocumentStream property. And that's it! the rest is the same as before! It's even nicer since I just get the WebBrowser.DocumentCompleted  called once... I don't need to look at the URL to see if it's my main page or an embedded Flash stream... and no more about:blank called after it is completed.

So here is my new method that I have added to my ScreenCapturerSTA class:

 

private void CaptureMS(object obj)
{
    m_byteImg = null;
 
    MemoryStream ms = obj as MemoryStream;
    try
    {
        using (WebBrowser webBrowser = new WebBrowser())
        {
            webBrowser.DocumentCompleted += 
                new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
            webBrowser.Height = 1000;
            webBrowser.Width = 1000;
            webBrowser.ScriptErrorsSuppressed = true;
            webBrowser.ScrollBarsEnabled = false;
            webBrowser.DocumentStream = ms;
            while (!m_done)
            {
                Application.DoEvents();
            }
        }
    }
    catch (Exception ex)
    {
        Trace.WriteLine(ex.ToString());
    }
}

So, just a coincidence? I mean, the WebBrowser still has to load the content...  at least it seems more stable now... 

Next step? hmmm, I'm tempted by a MONO/GECKO experiment...  I might give it a try...

HttpWebRequest.AllowReadStreamBuffering = false... Still buffering up to 4kb!

by Patrice 6/26/2008 6:58:00 AM

So why when you set it to "false" it doesn't seem to take effect?

This wasn't easy to guess... and this property is new in Beta 2 so not so much "discussion" on the web about it. After few hours stolen from my sleep time, I've found that the BeginGetResponse callback parameter will be called only when you'll have at least 4kb "buffered"... (is this "by design"?)...after 4kb of data received, you can receive a single byte at a time if you need to!

Look at my post on Silverlight forum for more details.

 

Update: This problem is specific to IE. It works in Firefox... but I have found another issue with Firefox; if you set a custom header webrequest.Headers["custom"]="custom" , AllowReadStreamBuffering won't work.... no effect... it will wait until the stream is all arrived.

Damn! Expression Blend 2.5 June Preview allow Template editing from Silverlight projects

by Patrice 6/9/2008 7:26:59 AM

In last my post about "Silverlight Project Structure" in Visual Studio, I talked about how Jose Fajardo was defining his project's structure and how it seems being a good approach. One problem, as Jose mentioned, was that "templates" edition weren't supported by VS-Blend combo. The solution was just to create a regular UserControl (so editable in Blend) and copy&paste the content in the app.xaml TemplateControl section (considering a "global" template).

If you got it right-on, that was good but after few copy&paste it became annoying. I was tired of editing my templates manually... manually as in "edit UserControl in Blend, open app.xaml, copy & paste UserControl code into the the TemplateControl section".

So I've started "googling" on "Visual Studio addon"... and it pointed me to the Visual Studio Extensibilty (VSX) web site... I've downloaded the SDK, tried the "wizard" project, modified it here and there, done some tests...

 

I ended up with a nice addon that converts my UserControl to TemplateControl by right-clicking my XAML file. Wow, that was much more effecient then a copy&paste...

 

 

 

 

 

 

 

 

All this to say that I was going to publish in more details my VS addon code and description project but after the last byte of Expression Blend 2.5 June Preview and Silverlight 2 Beta 2 releases, it's now irrelevant...

WebBrowser control...again about web site thumbnails/screenshots generated from the server

by Patrice 5/23/2008 5:10:46 PM

So, how did I start this easy project? Opened the browser, Googled for it. What did I get as results? It's mid 2008 and I got (personal statistics here) :

  1. 80% of samples, code snippet, suggestions using WebBrowser.DrawToBitmap
  2. 18% of IHTMLElementRender::DrawToDC
  3. 1% of Print screen
  4. 1% of IViewObject::Draw

Obvioulsy, the WebBrowser is just a wrapper around IE. After all these years, solutions on Internet should be trustable? no?...nope.

The first solution, at first, seems very easy: navigate to your page (WebBrowser.Navigate), once you get the DocumentCompleted event, call DrawToBitmap. But that works only with simple web sites. For the others, we get what people on forums call: the white page.... empty image. So that means that it would mostly never work for today's web sites. (I've found one solution on the web that was generating the images correctly but it uses so much code to solve the problem (refresh and reload) and it was implemented in a WinForm).

The second solution, is a bit more complex but easy to implement. Same as the first solution, it all starts with a call to WebBrowser.Navigate and then wait for the DocumentCompleted event. There, I said to myself: "that is it!". I started to test my solution (keep in mind that at this point, I'm using a WinForm project for test purposes). It was all good until I arrived on finance.yahoo.com... Dooh, just some parts of the page were copied to my file... test, change code, test, modify here and there, test... nothing always the same %#^$% result. I needed something else.

The third worked but I was getting the browser frame included in the image... so abandoned this one quickly.

Finally, the last one, is the answer to the second solution's problem. What I've found, is that IHTMLElementRender does not deal with opacity (transparency). It doesn't draw it and that's why my image was missing some parts. I've found the solution from an old post from Nathan Moinvaziri. So, I implemented his easy solution that is to use IViewObject instead of IHTMLElementRender... and it worked with all the sites I was browsing to... wooohoo!

...but I'm not done yet. It now runs in a WinForm application and I don't want this WinForm to pop up on my server... obviously. So, I said to myself, I just have to create a simple class library, reference it from my web project and that's it!... hmmm, not exactly. STA... this is at least documented everywhere... the WebBrowser control needs to run within a Single-Threaded Apartment... long time I haven't heard about this term, hehehe.

Alright, I just have to do it this way...  and it worked! Even for finance.yahoo.com! .... then I tried it with finance.yahoo.com/q?s=IBM  ... #%^*!@ ... "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))".... wtf is going on??? So, I'm getting exception on WebBrowser.ReadyState that I used in a "while" loop waiting for "WebBrowser.ReadyState == WebBrowserReadyState.Complete"... most of the code samples found for WebBrowser/STA do this trick... since I'm a dumass monkey, I did the same... alright, must be another way... I brought back my DocumentCompleted event but it's not obvious to deal with this since it has to be run within one call. I mixed the "while" loop with "Application.DoEvents()" to wait for the DocumentCompleted event be called and processed and then set a flag to "true" to exit the loop... here is the result:

public class ScreenCapturerSTA
{
    private string m_url;
    private byte[] m_byteImg;
    private bool m_done = false;
    private int m_tnWidth = 100;
    private int m_tnHeight = 100;

    /// <returns>Base64 string format</returns>
    public string CaptureBase64(string url)
    {
        return Convert.ToBase64String(Capture(url));
    }
    public byte[] Capture(string url)
    {
        return Capture(url, 60000/*1 min*/);
    }
    public byte[] Capture(string url, int timeout)
    {
        m_url = url;
        Thread t = new Thread(new ThreadStart(Capture));
        t.Name = "screenCapturer";
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        t.Join(timeout);
        return m_byteImg;
    }
    private void Capture()
    {
        m_byteImg = null;
        using (WebBrowser webBrowser = new WebBrowser())
        {
            webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
            webBrowser.Height = 1000;
            webBrowser.Width = 1000;
            webBrowser.ScriptErrorsSuppressed = true;
            webBrowser.ScrollBarsEnabled = false;
            webBrowser.Navigate(m_url);
            while (!m_done)
            {
                Application.DoEvents();
            }
        }
    }

    void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        if (e.Url == new Uri(m_url))//skip everything else
        {
            WebBrowser webBrowser = sender as WebBrowser;

            try
            {
                int width = webBrowser.ClientRectangle.Width;
                int height = webBrowser.ClientRectangle.Height;

                IHTMLDocument2 doc2 = (IHTMLDocument2)webBrowser.Document.DomDocument;
                using (Bitmap image = new Bitmap(width, height))
                {
                    using (Graphics grfx = Graphics.FromImage(image))
                    {
                        grfx.Clear(Color.White);

                        _RECTL bounds;
                        bounds.left = 0;
                        bounds.top = 0;
                        bounds.right = width;
                        bounds.bottom = height;

                        IntPtr grfxHdc = grfx.GetHdc();
                        IViewObject viewObject = doc2 as IViewObject;

                        viewObject.Draw(1, -1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
                            (IntPtr)grfxHdc, ref bounds, IntPtr.Zero, IntPtr.Zero, 0);

                        grfx.ReleaseHdc(grfxHdc);
                    }

                    using (Image thumbnailImage = image.GetThumbnailImage(m_tnWidth,
                        m_tnHeight, new Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero))
                    {
                        using (MemoryStream memstream = new MemoryStream())
                        {
                            thumbnailImage.Save(memstream, ImageFormat.Png);
                            m_byteImg = memstream.ToArray();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                using (Bitmap image = new Bitmap(m_tnWidth, m_tnHeight))
                {
                    using (Graphics grfx = Graphics.FromImage(image))
                    {
                        grfx.Clear(Color.White);

                        StringFormat format = new StringFormat();
                        format.LineAlignment = StringAlignment.Center;
                        format.Alignment = StringAlignment.Center;

                        using (SolidBrush brush = new SolidBrush(Color.FromArgb(61, 61, 61)))
                        {
                            grfx.DrawString("No image generated", new Font("arial", 6, 
                                FontStyle.Bold, GraphicsUnit.Point), brush, 
                                new Rectangle(0, 0, m_tnWidth, m_tnHeight), format);
                        }
                    }
                    using (MemoryStream memstream = new MemoryStream())
                    {
                        image.Save(memstream, ImageFormat.Png);
                        m_byteImg = memstream.ToArray();
                    }
                }
            }
            finally 
            {
                m_done = true;
            }
        }
    }

    public bool ThumbnailCallback()
    {
        return true;
    }

}
 
note: this hasn't been tested on a production environment yet, be careful!

 

Hopefully, it will serve fellow developers!

Missing ToTitleCase from TextInfo (Silverlight)

by Patrice 5/4/2008 12:35:00 AM

The other day I was converting some "utility" classes to be used within my Silverlight project and I realized (well, the compiler told me) that the ToTitleCase method was missing from System.Globalization.TextInfo. So I created one that ended up being more useful then the original one (well, for my own usage).

The default utility of ToTitleCase is obviously to change the first letter to uppercase and the rest to lowercase (mine can take a complete sentence too). Then a friend of mine gave me a case where it wouldn't work. Take for example "Merriam-Webster"; the W after the dash will be lower case. That's why I added a parameter to my ToTitleCase method, a character list, that are used as "uppercase after this character". The default value is naturally " " (space).

While I was there, I used the new Method Extensions feature.  So it can be used like:

"this sentence to titlecase".ToTitleCase(); 

 

   1:  public static  class UtilsClient
   2:  {
   3:      public static string ToTitleCase(this string value)
   4:      {
   5:          return ToTitleCase(value, new List<char> { ' ' });
   6:      }
   7:   
   8:      public static string ToTitleCase(this string value, List<char> separators)
   9:      {
  10:          string result = "";
  11:          bool nextUpper = true; //first letter always upper case
  12:   
  13:          value = value.ToLower();//initialize all to lower case
  14:   
  15:          for (int charIndex = 0; charIndex < value.Length; charIndex++)
  16:          {
  17:              string nextChar = value[charIndex].ToString();
  18:              if (nextUpper)
  19:              {
  20:                  nextChar = nextChar.ToUpper();
  21:              }
  22:   
  23:              result += nextChar;
  24:   
  25:              if (separators.Any(c => c.Equals(value[charIndex])))//put next char to upper case
  26:                  nextUpper = true;
  27:              else
  28:                  nextUpper = false;
  29:   
  30:          }
  31:   
  32:          return result;
  33:      }
  34:  }

Silverlight Project Structures : Design vs. Business Logic ( or UI vs. UX )

by Patrice 5/2/2008 11:07:00 PM

Since I've been experimenting with Silverlight V2.0 Beta1 (business logic in V1.0 was mostly JavaScript code, so mostly the same structure as regular web development), I've just played around by testing snippets of code in "test" projects. Now that I try to build more serious projects, I struggle on how structuring my project. I know, it might sounds stupid but Silverlight is not  Winform nor ASP.NET...or a little of both.

As much as people like to talk about the separation between design and business logic, I think it's a personal thing (as in "you", "your team" or "your company"). When the language/platform allows the developer to write "design" part in the business logic side and some business logic in the design side, it always ends up with "spaghetti" code. I remember classic ASP when we were mixing the client side JavaScript and the server side JavaScript code between HTML tags (supposedly the design part)... and when ASP.NET arrived it was supposed to be "the" answer for "spaghetti" code... I think I've seen worst in ASP.NET then ASP... design part done by spitting HTML strings from server controls. Even if it's the core of ASP.NET (hide the HTML spitting from the developers), there are a better ways of doing this (but anyway that's old technology, LOL).

With Silverlight, there is no "server side" code... but there is still a layer separation: user interface (UI) vs. user experience (UX).  So, we are faced again with the same interrogations... for example, should I write my "animation" in directly in XAML or create it dynamically from C#?  I'll find my way through experimentations...

I read Jose Fajardo blog frequently and two weeks ago he wrote about his preferred way of structuring his Silverlight projects. I really like it. I'll "borrow" his idea and start my new project with this structure. We'll see how much I'll keep the original form.

Powered by BlogEngine.NET 1.3.1.0

LFDX Software Inc.

About the author

P. Lafond Patrice Lafond
(and yes, it's Mr!)
Software Engineer
French Canadian expat in Bermuda for over 7 years.
flag QC  flag BDA

E-mail me Send mail

Calendar

<<  January 2009  >>
MoTuWeThFrSaSu
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar

Pages

    Recent comments

    Authors

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2009

    Sign in